When mime-type validation isn’t enough

Recently a client’s machine had been accessed through some holes in his application. We were given access to the source code and started to figure out how the hacker was able to get in and execute code to elevate his privileges, post financial transactions and reset accounts.

The first place we looked were places where images could be uploaded to the system as that is usually a very easy place to upload code. The file uploader checked for the presence of .gif/.jpg/.jpeg and checked the mime type, but, the check merely made sure that .jpg was contained within the filename, not that it was anchored to the right hand side. Looking through a number of directories where files could be written and be web accessible, we had a few possible locations to focus our efforts. Two sections of code were focused on and we came up with the following code:

00000000  ff d8 ff e0 00 10 4a 46  49 46 00 01 01 01 00 48  |......JFIF.....H|
00000010  00 48 00 00 ff db 00 43  00 01 01 01 01 01 01 01  |.H.....C........|
00000020  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
00000030  01 01 01 01 01 01 01 01  01 01 01 01 01 02 02 01  |................|
00000040  01 02 01 01 01 02 02 02  02 02 02 02 02 02 01 02  |................|
00000050  02 02 02 02 02 02 02 02  02 ff db 00 43 01 01 01  |............C...|
00000060  01 01 01 01 01 01 01 01  02 01 01 01 02 02 02 02  |................|
00000070  02 02 02 02 02 02 02 02  02 02 02 02 02 02 02 02  |................|
*
00000090  02 02 02 02 02 02 02 02  02 02 02 02 02 02 ff c2  |................|
000000a0  00 11 08 02 15 02 58 03  01 22 00 02 11 01 03 11  |......X.."......|
000000b0  01 ff c4 00 1e 00 00 00  06 03 01 01 00 00 00 00  |................|
000000c0  00 00 00 00 00 00 04 05  06 07 08 09 00 02 03 0a  |................|
000000d0  3c 3f 70 68 70 20 65 63  68 6f 20 22 74 65 73 74  |< ?php echo "test|
000000e0  22 3b 3f 3e 0a                                    |";?>.|
000000e5

You can recreate the exploit:

head -n 1 somefile.jpg > file.jpg.php
echo '< ?php echo "hello";?>' >> file.jpg.php

The file was named file.jpg.php, uploaded through the application, the file was then written to the avatars directory and was web accessible. Since the file contained .jpg and had a proper jpeg header, it passed the two validation tests. The payload contained with the file shows ‘junk’ before the word test is printed.

A number of factors made this attack vector possible. A client could upload content that contained filenames that could be executed by .php/.cgi if they contained .gif/.jpg/.jpeg. In addition, the avatar directory (and one other) allowed execution of scripts. Using filesmatch or removing the mimetypes for anything but the static images allowed would have prevented the files from being executed.

In reality, the hole that was used was even easier to exploit as the application allowed preview of a work unit where the url wasn’t sanitized properly allowing XSS, however, this method could have been utilized.

Every time you deal with user supplied content, check, double-check and triple-check the server configuration, directory permissions, ability to traverse directories, etc. Ideally, making sure your server has minimal abilities in those directories is a step in the right direction.

Tags:

Leave a Reply

You must be logged in to post a comment.

Entries (RSS) and Comments (RSS).
Cluster host: li