Персональные инструменты
Вы здесь: Главная Блог Positive Hack Days CTF: .2 walkthrough

Positive Hack Days CTF: .2 walkthrough

Автор: Георгий Носеевич at 2011-12-27 01:05 |

A brief note about exploiting blind SQL injection in Postrges in the absense of important keywords.

As a part of PHDays qualification round we had to exploit an unusual SQL injection.

The exploited URI was http://192.168.0.2/index.php?cmd=__PAYLOAD__, which led to a query similar to:

SELECT * FROM cmd WHERE cmd_id = '__PAYLOAD__'

There were three useful values for cmd_id field - id, hello, test, which all resulted in different answers. Any other value or an erroneous query resulted in an generic error message.

We quickly found that custom filtering was in place. Several important keywords were blocked, such as AND, SELECT, UNION and the like. Simple tricks such as MiXedCAse didn't do the trick (and Postgres is more strict that MySQL and disallows sel/**/ect stuff) , but we were able to do get version(), user(), etc. with the following request:

192.168.0.2/index.php?cmd=i'||(case+(substr(version(),1,1))+when+5+then+'d'+end)+--

This proved that the exploitation is possible, but we still couldn't find out the way to find out table names and to extract data.
One possible solution was to inject a stored procedure, but we didn't succeed because the DB user had insufficient privileges. File reading and writing was also prohibited. 

 

That is when we started skimming through postgres docs and finally found a solution - the   XML manipulation functions! As we found out, these are a powerful and universal way of extracting metadata and content from psql databases. We can use {database,schema,cursor,table}_to_xml to dump entire tables and databases, and the mighty query_to_xml to execute custom queries. In the latter function, the executed query is a string parameter that can be specified via 0x notation to evade filtering.

In this case we didn't know what we needed and decided to dump the entire database. To make data extraction faster we use 4 possible responces to extract 2 bits of the string at a time. The following  extracts lowest two bits from a char of text (for an extra speed boost I used plain old xargs wrapper over this, the full script is here):

out=`curl "http://192.168.0.2/index.php?cmd='||(case+ascii(substr($QUERY,$CHAR_POS,1))+&+3+when+3+then+'id'+when+2+then+'hello'+when+1+then+'test'+else+'invalid'+end)+--" 2>/dev/null`

The database dump revealed a couple of usernames with hashed passwords, but they were not valid flags. Googling for hashes we found that one of them was a md5(md5(test), so probably there was some other webapp with a weird password hashing alorithm? Yep, the robots.txt revealed the admin area, where we could successfully log in using the dumped credentials. This revealed the flag.

 

Действия с Документом