Pwning Postgres 9.1
I recently came across a Postgres based SQL Injection in a web application. The database in question was the latest version (9.1). I was in luck and the back-end database user was “postgres” which is the default superuser account in Postgres. If you recall, Postgres and Php allows execution of stacked queries; ie, if the injection was in SELECT statement, you can terminate the SELECT statement and start a new statement like ‘CREATE TABLE..” etc, by using semi-colon between them:
http://host/vuln.php?id=injection';create table NotSoSecure (data varchar(200));--
This means that you can execute OS code on the back-end database. Sqlmap already supports this. The way Sqlmap does this is by injecting a User Defined Function (UDF).
From Postgres site:
“User-defined functions can be written in C (or a language that can be made compatible with C, such as C++). Such functions are compiled into dynamically loadable objects (also called shared libraries) and are loaded by the server on demand”
Remember, while there is a default shared library present in Operating system libc.so.6 which already has a system() function defined, you cannot use it because Postgres has a limitation that:
all UDF must include a magic block after having included the header fmgr.h
So, you need to create your own shared library, upload it, create a function referring to this library and then execute the function. Sqlmap, already has the libraries created for various postgres version and different OS versions. I have to say, Bernardo has done an awesome job.
In case of Postgres 9.1, this attack did not work. After a little debugging, it was clear that sqlmap for now don’t have support for Postgres 9.1. it was trying to upload the library for 9.0 which was incompatible with 9.1. Bernardo, kindly pointed me to the instructions to compile the library for my architecture (64 bit). So, I compiled the library for Postgres 9.1 64 bit linux and you can download it here. Using this, I was able to create a function manually and execute the code, as shown in screenshot:
There are some caveats though:
Sqlmap uploads pre-compiled shared library to the database system. The library file I have compiled is about 10KB in size and postgres by default don’t allow creation of objects bigger than 8KB in size. So, changing the library file in sqlmap folder won’t do the trick. You will have to compile this file with some funky compiling options to reduce the size less than 8KB. I am sure sqlmap will look into this and get this sorted soon. I had to manually upload this file to the server using another file upload issue.
Note: Stacking queries through web applications is rare in MySql and hence the same techniq doesn’t work under MySql.
That’s all for now.