Bypassing File Upload Restrictions with Magic Byte and a Hex Editor
This is a pretty cool, but easy, trick I learned today when working on a challenge. We've talked a bit about Magic Byte in the past when we did Networked on HTB.
Basically, it's a string that indicates a file type. You can check out a bunch of them here.
I was working on a challenge that required me to upload a file, but restricted me to certain image files. Unfortunately, GIF was not one of them, otherwise, I could have just appended GIF8; to the start of my webshell and called it good. That wasn't the case, and I had to figure out how to trick the target into accepting my file upload.
A bit of Google searching and I stumbled onto the the following post on Geeks for Geeks. The objective was different in that it discussed repairing a file with a corrupted magic number. However, it taught me the coolness of hexedit, which you can install with:
sudo apt-get install hexedit
In the following example, I have a text file called "tacos.txt.jpg". If I cat the file out, I see the actual text:
nux@KakaLinpoop:~/Documents/htb/boxes/magic/uploads$ cat tacos.txt.jpg
Drink Pepsi.
Pop Boxes.
Drop Shells.
Eat Tacos.
Okay, cool.
Running xxd | head
results in the following:
nux@KakaLinpoop:~/Documents/htb/boxes/magic/uploads$ xxd tacos.txt.jpg | head
00000000: 0a44 7269 6e6b 2050 6570 7369 2e0a 506f .Drink Pepsi..Po
00000010: 7020 426f 7865 732e 0a44 726f 7020 5368 p Boxes..Drop Sh
00000020: 656c 6c73 2e0a 4561 7420 5461 636f 732e ells..Eat Tacos.
00000030: 0a
Then checking the filetype with file gives us:
nux@KakaLinpoop:~/Documents/htb/boxes/magic/uploads$ file tacos.txt.jpg
tacos.txt.jpg: ASCII text
It's a text file. That's correct.
Magic Numbers
Now, based on what we know from Geeks for Geeks, a jpg file usually has one of the following magic numbers: FFD8 DDE0
, FFD8 FFDB
or FFD8 FFE1
. When uploading our file, we just have to go with trial and error attempts. I had to try the first one, fail then try the second combination to make it work in the challenge I was working on.
Another useful post came from StackOverFlow. It pointed to a Wikipedia entry that said JPEG image files begin with FFD8
and end with FFD9
. Now we know the bytes that start and end a valid jpg file. Let's apply it.
Creating a "jpeg" File
First, we run hexedit: hexedit tacos.txt.jpg
.
We see something like this:
hexedit lets us edit the file's hex. Let's change the first bytes and the last bytes as we saw above:
- First bytes will be:
FFD8 FFDB
- Last bytes will be:
FFD9
It's a little difficult to tell here, but these are the first and last bytes. There's a wraparound and I've only cropped the relevant portion:
Now, when we run xxd, we see this:
nux@KakaLinpoop:~/Documents/htb/boxes/magic/uploads$ xxd tacos.txt.jpg
00000000: ffd8 ffdb 6e6b 2050 6570 7369 2e0a 506f ....nk Pepsi..Po
00000010: 7020 426f 7865 732e 0a44 726f 7020 5368 p Boxes..Drop Sh
00000020: 656c 6c73 2e0a 4561 7420 5461 636f 732e ells..Eat Tacos.
00000030: ffd9
If we check the filetype, we will see that it's a "jpeg":
nux@KakaLinpoop:~/Documents/htb/boxes/magic/uploads$ file tacos.txt.jpg
tacos.txt.jpg: JPEG image data
This is great for bypassing file upload restrictions for uploading things like php webshells. It's a pretty cool trick, and it's really easy.