Kos SecurityA blog about security.

[RL] PostgreSQL String Filter Evasion & UDF

Recently I came across an application that:

I had straight up SQL injection (on an INSERT statement, but fortunately stacked queries are supported in PostgreSQL + ASP.NET/JSP), but I was having a hard time getting things to work nicely.

After a little bit of searching for filter evasion and PostgreSQL, I discovered this paper: Advanced PostgreSQL SQL Injection and Filter Bypass Techniques by
Leon Juranić of DefenseCode.

I suggest reading the whole paper, it’s great, but what I took away from it was exactly what I needed at the time. It turns out that in PostgreSQL, to denominate a string, you can use single tick (‘), quotes (“), or, get this, double dollar signs ($$).

The reason for this is to make SQL more readable when including single ticks and qoutes.
Imagine a query like:

SELECT * FROM shops WHERE shopName ID = 'Rick\'s Ice Cream';

Notice the escape character? (Disregard the fact that I could have just used double quotes instead.) PostgreSQL decided to solve this solution by adding another delimiter, the double dollar signs ($$). So suddenly, the above statement becomes:

SELECT * FROM shops WHERE shopName ID = $$Rick's Ice Cream$$;

Here’s the documentation on it. What does this mean? Easier filter evasion for us!

But that’s not all I faced during my testing. It turns out, that as of PostgreSQL 8.2 or 8.3, PostgreSQL will not longer allow you to load a C library unless the PostgreSQL “Magic Token” has been defined, PG_MODULE_MAGIC;. This means that I can’t simply load /lib/libc.so anymore, which means I can’t map a new user defined function to system()! Bummer!

Fortunately, I was able to discover file upload functionality in this application that let me upload binary files, I simply snipped out SQLMap‘s lib_postgresqludf_sys.c, compiled it against the version of PostgreSQL I was attacking, and boom, I had a valid C library that I could load into PostgreSQL with and execute system() functions.

In the end, the SQL statement looked like this, with my attack vector in bold.

SELECT * FROM users WHERE ID = 1;CREATE OR REPLACE FUNCTION system(cstring) RETURNS int AS $$/www/some/upload/path/uploadedfile.so$$, $$system$$ LANGUAGE $$C$$ STRICT;select system($$ nc -e /bin/sh -l 1025 $$);– and password = ‘password’;

No comments posted.

Leave a Reply

Your email address will not be published. Required fields are marked *


five − 3 =

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>