Web


Nmap discovered a Web server on the target port 80 The running service is Apache httpd 2.4.54

Webroot at /index.php It appears to be an online retailer for watch

Wappalyzer identified technologies involved It’s written in PHP

The Client section reveals 3 potential users

The Contact section doesn’t appear to be responsive

There are 2 additional files hard-coded in to the web root; /shop and /upload.php

/shop


301 to /shop/index.php It lists recently added products

These products are set with a parameter of id within the page=product parameter

/shop/index.php?page=cart


Adding an item to the cart sends a POST request to the /shop/index.php?page=cart page with the POST data

Then it loads the /shop/index.php?page=cart page with a GET request

The Update button also sends a POST request to the /shop/index.php?page=cart page with the shown POST data This seems to refresh the session, which refreshes the cart

Same goes for the Place Order button, but it leads to the /shop/index.php?page=placeorder page afterwards

The Clear button however empties the cart

I will check for other potential values to the page parameter

Parameter Mining


┌──(kali㉿kali)-[~/archive/htb/labs/zipping]
└─$ ffuf -c -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-large-words-lowercase.txt -u http://$IP/shop/index.php?page=FUZZ -ic -fw 811
________________________________________________
 
 :: Method           : GET
 :: URL              : http://10.10.11.229/shop/index.php?page=FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/seclists/Discovery/Web-Content/raft-large-words-lowercase.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
 :: Filter           : Response words: 811
________________________________________________
 
[Status: 500, Size: 0, Words: 1, Lines: 1, Duration: 42ms]
    * FUZZ: index
 
[Status: 200, Size: 2033, Words: 670, Lines: 64, Duration: 31ms]
    * FUZZ: cart
 
[Status: 200, Size: 15, Words: 3, Lines: 1, Duration: 31ms]
    * FUZZ: product
 
[Status: 200, Size: 2584, Words: 825, Lines: 68, Duration: 31ms]
    * FUZZ: products
 
[Status: 500, Size: 0, Words: 1, Lines: 1, Duration: 27ms]
    * FUZZ: functions
 
[Status: 200, Size: 1192, Words: 312, Lines: 38, Duration: 28ms]
    * FUZZ: placeorder
 
:: Progress: [107982/107982] :: Job [1/1] :: 621 req/sec :: Duration: [0:02:46] :: Errors: 0 ::

ffuf found 4 additional values to the page parameter

/shop/index.php?page=product


It seems that the page=product parameter is used to display a single item with the id parameter as it’s required

Like so

/shop/index.php?page=products


Whereas the page=products displays all the product

index and functions


┌──(kali㉿kali)-[~/archive/htb/labs/zipping]
└─$ curl http://$IP/shop/index.php?page=index -I    
HTTP/1.0 500 Internal Server Error
date: Wed, 30 Aug 2023 11:08:27 GMT
server: Apache/2.4.54 (Ubuntu)
set-cookie: PHPSESSID=jlb15v1ndtvo6b0lqfitveoha7; path=/
expires: Thu, 19 Nov 1981 08:52:00 GMT
cache-control: no-store, no-cache, must-revalidate
pragma: no-cache
connection: close
content-type: text/html; charset=UTF-8
 
┌──(kali㉿kali)-[~/archive/htb/labs/zipping]
└─$ curl http://$IP/shop/index.php?page=functions -I
HTTP/1.0 500 Internal Server Error
date: Wed, 30 Aug 2023 11:08:19 GMT
server: Apache/2.4.54 (Ubuntu)
set-cookie: PHPSESSID=9hu9d1h7akk0braaddvl3kbn08; path=/
expires: Thu, 19 Nov 1981 08:52:00 GMT
cache-control: no-store, no-cache, must-revalidate
pragma: no-cache
connection: close
content-type: text/html; charset=UTF-8

index and functions to the page parameter returns code 500

/upload.php


The /upload.php file supports file upload A PDF file archived with .zip extension is expected

This seems to suggest that there is someone on the other end that actively checks for uploaded files by opening them, which provides an opportunity for an attacker to upload a malicious PDF file that could potentially open up a door for other attack vectors including SSRF or RCE

I tested the file upload feature by uploading a ZIP archive with a testing PDF file in it It shows that the file was successfully uploaded and UNZIPPED and is waiting for review by a staff member

The UNZIPPED content appears to be saved to uploads/8cf3bbfea34209ac4333ee48a0c09d7e/test.pdf

It is indeed available at `uploads/8cf3bbfea34209ac4333ee48a0c09d7e/test.pdf Interesting thing here is that the web application generated a directory whose name appears be a MD5 hash string

┌──(kali㉿kali)-[~/archive/htb/labs/zipping]
└─$ hashid 8cf3bbfea34209ac4333ee48a0c09d7e                           
Analyzing '8cf3bbfea34209ac4333ee48a0c09d7e'
[+] MD2 
[+] MD5 
[+] MD4 
[+] Double MD5 
[+] LM 
[+] RIPEMD-128 
[+] Haval-128 
[+] Tiger-128 
[+] Skein-256(128) 
[+] Skein-512(128) 
[+] Lotus Notes/Domino 5 
[+] Skype 
[+] Snefru-128 
[+] NTLM 
[+] Domain Cached Credentials 
[+] Domain Cached Credentials 2 
[+] DNSSEC(NSEC3) 
[+] RAdmin v2.x 

It definitely looks to be a hash string

┌──(kali㉿kali)-[~/archive/htb/labs/zipping]
└─$ md5sum test.zip                        
8cf3bbfea34209ac4333ee48a0c09d7e  test.zip

It turns out to be the calculated hash string of the ZIP file itself

Extension


┌──(kali㉿kali)-[~/archive/htb/labs/zipping]
└─$ touch a.php ; zip a.zip a.php 
  adding: a.php (stored 0%)

Content with PHP extension seems to fail to upload due to the extension filter in the server side

I can make it work by modifying the POST data, but the uploaded file will be saved with the .pdf extension However, I cannot load the content let alone invoking code execution due to the .pdf extension

It would work only if I could control the extension One method would be the Nullbyte Injection

Nullbyte Injection


┌──(kali㉿kali)-[~/archive/htb/labs/zipping]
└─$ echo "hello there 123" > b.txtA.pdf ; zip b.zip b.txtA.pdf
  adding: b.txtA.pdf (stored 0%)

I will first create an arbitrary txt file with the .txtA.pdf extension and archive it to b.zip Then I will inject a null byte to the location of the A character. This will terminate the remaining, but the web app will still see the content as a valid PDF file

It worked. Notice the whitespace; b.txt .pdf

Moving on to the Exploitation phase

Fuzzing


┌──(kali㉿kali)-[~/archive/htb/labs/zipping]
└─$ ffuf -c -w /usr/share/wordlists/seclists/discovery/web-content/directory-list-2.3-medium.txt -u http://$IP/FUZZ -ic -e .php, .txt 
________________________________________________
 
 :: Method           : GET
 :: URL              : http://10.10.11.229/FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
 :: Extensions       : .php  
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________
[status: 301, Size: 314, Words: 20, Lines: 10, Duration: 25ms]
    * fuzz: uploads
 
[status: 301, Size: 311, Words: 20, Lines: 10, Duration: 26ms]
    * fuzz: shop
 
[status: 301, Size: 313, Words: 20, Lines: 10, Duration: 27ms]
    * fuzz: assets
 
[status: 200, Size: 5321, Words: 1882, Lines: 113, Duration: 27ms]
    * fuzz: upload.php
 
[status: 200, Size: 16738, Words: 5717, Lines: 318, Duration: 4483ms]
    * fuzz: index.php
	
[status: 403, Size: 277, Words: 20, Lines: 10, Duration: 29ms]
    * fuzz: server-status
 
:: Progress: [661641/661641] :: Job [1/1] :: 1503 req/sec :: Duration: [0:07:49] :: Errors: 0 ::

No additional endpoint found