Summary
Code White have already an impressive publication record on Java Deserialization. This post is dedicated to a vulnerability in SAP NetWeaver Java. We could reach remote code execution through the p4 protocol and the Jdk7u21 gadget with certain engines and certain versions of the SAP JVM.We would like to emphasize the big threat unauthenticated RCE poses to a SAP NetWeaver Java. An attacker with a remote shell can read out the secure storage, access the database, create a local NetWeaver user with administrative privileges, in other words, fully compromise the host. Unfortunately, this list is far from being complete. An SAP landscape is usually a network of tightly
connected servers and services. It wouldn’t be unusual that the database of the server stores technical users with high privileges for other SAP systems, be it NetWeaver ABAP or others. Once the attacker gets hold of credentials for those users she can extend her foothold in the organization and eventually compromise the entire SAP landscape.
We tested our exploit successfully on 7.20, 7.30 and 7.40 machines, for detailed version numbers see below. When contacted, SAP Product Security Response told us they published 3 notes (see [7], [8] and [9]) about updates fixing the problems (already in June 2013) with SAP JVM versions 1.5.0_086, 1.6.0_052 and 1.7.0_009 (we tested on earlier versions, see below). In addition SAP have recently adopted JDK JEP 290 (a Java enhancement that allows to filter incoming serialized data). However, neither do these three notes mention Java Deserialization nor is it obvious to the reader they relate to security in any other way.
Due to missing access to the SAP Service Marketplace we’re unable to make any statement about the aforementioned SAP JVM versions. We could only analyze the latest available SAP JVM from tools.hana.ondemand.com (see [6]) which contained a fix for the problem.
Details
In hisThe natural entry point in this area is the p4 protocol. We found a p4 test client on SAP Collaboration Network and sniffed the traffic. One doesn’t need to wait long until a serialized object is sent over the wire:
00000000 76 31 v1
00000002 18 23 70 23 34 4e 6f 6e 65 3a 31 32 37 2e 30 2e .#p#4Non e:127.0.
00000012 31 2e 31 3a 35 39 32 35 36 1.1:5925 6
00000000 76 31 19 23 70 23 34 4e 6f 6e 65 3a 31 30 2e 30 v1.#p#4N one:10.0
00000010 2e 31 2e 31 38 34 3a 35 30 30 30 34 .1.184:5 0004
0000001B 00 00 11 00 00 00 00 00 00 00 ff ff ff ff 00 00 ........ ........
0000002B 00 00 00 00 00 00 0a 00 63 00 6f 00 63 00 72 ........ c.o.c.r
0000001C 00 00 75 00 00 00 ff ff ff ff 9e 06 60 00 00 00 ..u..... ....`...
0000002C 00 00 00 00 00 00 0b 9e 06 60 00 f7 25 e4 05 00 ........ .`..%...
0000003C 00 00 00 00 00 00 00 98 9c 0e 2a 00 4e 00 6f 00 ........ ..*.N.o.
0000004C 6e 00 65 00 3a 00 31 00 30 00 2e 00 31 00 30 00 n.e.:.1. 0...1.0.
0000005C 2e 00 31 00 30 00 2e 00 31 00 30 00 3a 00 35 00 ..1.0... 1.0.:.5.
0000006C 30 00 30 00 30 00 34 00 3a 00 4e 00 6f 00 6e 00 0.0.0.4. :.N.o.n.
0000007C 65 00 3a 00 31 00 30 00 2e 00 30 00 2e 00 31 00 e.:.1.0. ..0...1.
0000008C 2e 00 31 00 38 00 34 00 3a 00 35 00 30 00 30 00 ..1.8.4. :.5.0.0.
0000009C 30 00 34 0.4
0000003A 00 00 16 00 00 00 9e 06 60 00 ff ff ff ff fe 00 ........ `.......
0000004A 00 00 00 00 00 00 14 00 00 00 00 00 00 00 00 00 ........ ........
0000005A 98 9c 0e 2a ...*
0000005E 00 00 75 00 00 00 9e 06 60 00 ff ff ff ff 01 00 ..u..... `.......
0000006E 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 67 ........ .... ..g
0000007E 00 65 00 74 00 43 00 6c 00 61 00 73 00 73 00 42 .e.t.C.l .a.s.s.B
0000008E 00 79 00 4e 00 61 00 6d 00 65 00 28 00 6a 00 61 .y.N.a.m .e.(.j.a
0000009E 00 76 00 61 00 2e 00 6c 00 61 00 6e 00 67 00 2e .v.a...l .a.n.g..
000000AE 00 53 00 74 00 72 00 69 00 6e 00 67 00 29 00 00 .S.t.r.i .n.g.)..
000000BE 00 00 00 00 00 00 98 9c 0e 2a ac ed 00 05 74 00 ........ .*....t.
000000CE 12 43 6c 69 65 6e 74 49 44 50 72 6f 70 61 67 61 .ClientI DPropaga
000000DE 74 6f 72 tor
The highlighted part is just the java.lang.String object “ClientIDPropagator”.
Now our plan was to replace this serialized object by a ysoserial payload. Therefore, we needed to find out how the length of such a message block is encoded.
When we look at offset 0000005E, for instance, the 00 00 75 00 looks like 2 header null bytes and then a length in little endian format. Hex 75 is 117, but the total length of the last block is 8*16+3 = 131. If one looks at the blocks the client sent before (at offset 0000001B and 0000003A) one can easily spot that the real length of the block is always 14 more than what is actually sent. This lead to the first conclusion: a message block consists of 2 null bytes, 2 bytes length of the payload in little endian format, then 10 bytes of some (not understood) header information, then the payload:
When running the test client several times and by spotting the messages carefully enough one can see that the payload and header aren’t static: They use 2 4-bytes words sent in the second reply from
the server:
That was enough to set up a first small python program: Send the corresponding byte arrays in the right order, read the replies from the network, set the 4 byte words accordingly and replace “ClientIDPropagator” by the ysoserial Jdk7u21 gadget.
Unfortunately, this didn’t work out at first. A bit later we realized that SAP NetWeaver Java obviously didn’t serialize with the plain vanilla Java ObjectOutputStream but with a custom serializer. After twisting and tweaking a bit we were finally successful. Details are left to the reader ;-)
To demonstrate how dangerous this is we have published a disarmed exploit on github [5]. Instead of using a payload that writes a simple file to the current directory (e.g. cw98653.txt with contents "VULNERABLE"), like we did, an attacker can also add bytecode that runs Runtime.getRuntime().exec("rm -rf *") or establish a remote shell on the system and thereby compromise the system or in the worst case even parts of the SAP landscape.
We could successfully verify this exploit on the following systems:
- SAP Application Server Java 7.20 with SAPJVM 1.6.0_07 (build 007)
- SAP Application Server Java 7.30 with SAPJVM 1.6.0_23 (build 034)
- SAP Application Server Java 7.40 with SAPJVM 1.6.0_43 (build 048)
However, since staying up-to-date with modern software product release cycles is a big challenge for customers and the corresponding SAP notes do not explicitely bring the reader’s attention to a severe security vulnerability, we’d like to raise awareness that not updating the SAP JVM can expose their SAP systems to serious threats.
Mitigation
- Block p4 on your firewall
- Make sure your SAP JVM is up-to-date
References
- https://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkinsopennms-
and-your-application-have-in-common-this-vulnerability/ - http://codewhitesec.blogspot.de/2016/04/infiltrate16-slidedeck-java-deserialization.html
- https://github.com/frohoff/ysoserial
- https://cal.sap.com/
- https://github.com/codewhitesec/sap-p4-java-deserialization-exploit
- https://tools.hana.ondemand.com/additional/sapjvm-6.1.099-linux-x64.zip
- SAP Note 1875035 (available to customers since June, 2013) for SAP JVM 5
- SAP Note 1875026 (available to customers since June, 2013) for SAP JVM 6
- SAP Note 1875042 (available to customers since June, 2013) for SAP JVM 7
- SAP note 2443673 from April 2017