SQL injection, Oracle and full-width characters

Despite the fact that SQL injection is relatively old and solved problem, it is still commonly found in web applications.

During one pentest I faced PHP application, which was vulnerable to SQL injection, but exploitation was kinda tricky, since it was replacing comma with part of additional SQL query. So every time you send , in your SQL payload, it gets replaced to something like OR like ‘%blabla%’ and breaks your appended query’s syntax. Since I was not aware how to reliably extract data from Oracle database without using commas (since Oracle does not have LIMIT clause, you have to use ROWNUM which requires commas) I decided to try Unicode symbols with the hope that vulnerable PHP application will not recognize such symbols but it will be accepted by Oracle database as regular comma. After a quick googling I found a nice website, which showed me all characters with COMMA in character name together with UTF-8 representations.

First, I was looking for characters that visibly looks like regular comma. After a few tries it turned out that FULL-WIDTH COMMA perfectly works in this case — PHP application does not treat it as a comma (it does not get replaced), but works fine for Oracle database as legitimate part of SQL syntax. Voila.

Unicode code point/Character/UTF-8 encoding (hex)/Unicode character name 
U+FF0C/,/ef bc 8c/FULLWIDTH COM­MA

It is quite rare to have Oracle database outside corporate environment. So, for playing more with it and confirm that Oracle database really treats full-width UTF-8 characters as valid syntax and it is not some PHP application behavior, I was planning to play with it on SQLFiddle. Turns out that SQLFiddle is no longer working with Oracle database. Luckily, Oracle has a free service called Oracle Live SQL, which is basically the same as SQLFiddle — it allows to access Oracle database via web interface.

Executing SQL query on Oracle Live SQL

Replacing regular comma (below) with full-width variant gives the same results as shown in a picture above.

SELECT OWNER,PRIVILEGE FROM user_tab_privs;

Meanwhile, passing any other representation of comma gives error (e.g. small comma — U+FE50). The following query:

SELECT OWNER﹐PRIVILEGE FROM user_tab_privs;

Results in :

ORA-00911: invalid character

To automate exploitation using SQLMAP I had to instruct SQLMAP to replace regular commas to full-width commas, which can be achieved using tamper scripts. Luckily for me, there is already a very similar tamper script that is replacing regular quote to full-width quote named apostrophemask.py.

#!/usr/bin/env python
“””
Copyright © 2006–2017 sqlmap developers (http://sqlmap.org/)
See the file ‘doc/COPYING’ for copying permission
“””
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.LOWEST
def dependencies():
 pass
def tamper(payload, **kwargs):
 “””
 Replaces apostrophe character with its UTF-8 full width counterpart
References:
 * http://www.utf8-chartable.de/unicode-utf8-table.pl?start=65280&number=128
 * http://lukasz.pilorz.net/testy/unicode_conversion/
 * http://sla.ckers.org/forum/read.php?13,11562,11850
 * http://lukasz.pilorz.net/testy/full_width_utf/index.phps
>>> tamper(“1 AND ‘1’=’1”)
 ‘1 AND %EF%BC%871%EF%BC%87=%EF%BC%871’
 “””
return payload.replace(‘\’’, “%EF%BC%87”) if payload else payload

I quickly made slightly changes and was able to automate data extraction using SQLMAP.

#!/usr/bin/env python
“””
Copyright © 2006–2017 sqlmap developers (http://sqlmap.org/)
See the file ‘doc/COPYING’ for copying permission
“””
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.LOWEST
def dependencies():
 pass
def tamper(payload, **kwargs):
 “””
 Replaces comma character with its UTF-8 full width counterpart
 “””
return payload.replace(‘,’, “%EF%BC%8C”) if payload else payload

As you can see, bypassing security filters using Unicode characters is not new, but still an effective technique. Oracle also accepts full-width commas and, most likely, other characters. Thus, don’t forget to update your payloads lists with such characters.

P.S. Oracle Live SQL runs on Oracle Database 12c Enterprise Edition Release 12.2.0.1.0–64bit.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.