0x01普通注入
sql参数拼接,未做任何过滤
例:
$con = mysql_connect("localhost","root","root");
mysql_select_db("test", $con);
$id = stripcslashes($_REQUEST[ ‘id‘ ]);
$query = "SELECT * FROM users WHERE id = $id "
0x02宽字节注入
A、MySQL中有宽字符注入
例:
$con = mysql_connect("localhost","root","root");
mysql_query("SET NAMES ‘gbk‘");
mysql_select_db("test", $con);
$id = isset($_GET[‘id‘]) ? addslashes($_GET[‘id‘]) : 1;
$query = "SELECT * FROM users WHERE id =‘{$id}‘ ";
解决方法:
方案一:指定php连接MySQL字符集
mysql_set_charset(‘gbk‘,$con);
id=mysqlrealescapestring(_GET[‘id‘]); //转义其中的特殊字符
方案二:将character_set_client设置为binary(二进制)
mysql_query("SET character_set_connection=gbk,caracter_set_results=gbk,character_set_client=binary",$conn);
所有数据以二进制的方式传递,避免宽字节注入
B、PHP编码转换
$con = mysql_connect("localhost","root","root");
mysql_query("SET NAMES ‘gbk‘");
mysql_select_db("test", $con);
mysql_query("SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary", $con);
$id = isset($_GET[‘id‘]) ? addslashes($_GET[‘id‘]) : 1;
$id=iconv(‘utf-8‘,‘gbk‘,$id); //还有类似的函数为mb_convert_encoding(id,‘utf-8‘,‘gbk‘)
$query = "SELECT * FROM users WHERE id =‘{$id}‘ ";
解决方法:
PHP字符编码绕过漏洞总结 http://www.cnblogs.com/Safe3/archive/2008/08/22/1274095.html
0x003 编码解码
找一些编码解码的函数来绕过防护,,如urldecode() 、rawurldecode()、base64_decode()
例:
$con = mysql_connect("localhost","root","root");
mysql_select_db("test", $con);
$id = addslashes($_REQUEST[‘id‘]);
$id = urldecode($id);//$id = base64_decode($id);
$query = "SELECT * FROM users WHERE id = ‘{$id}‘";
绕过方法:
1‘union select 1,2,3,4%23 单引号Urlencode 1%2527union select 1,2,3,4%23
1‘union select 1,2,3,4# Base64 Encode MSd1bmlvbiBzZWxlY3QgMSwyLDMsNCM=
0x04二次注入
入库后转义符就会消失,变成hack‘,查询出库的就是hack‘,如果拼接到SQL语句,成功引入了单引号闭合前面字符, 导致注入。
例:
解决方法:
过滤插入的特殊字符,限定插入时的字符类型
0x05全局防护盲点
1、str_replace函数 过滤单引号等,可能造成注入;
2、stripslashes() 函数删除由 addslashes() 函数添加的反斜杠。stripslashes函数使用不当,可能造成注入;
①注入点类似id=1这种整型的参数就会完全无视GPC的过滤;
②注入点包含键值对的,那么这里只检测了value,对 key的过滤就没有防护; ③有时候全局的过滤只过滤掉GET、POST和COOKIE,但是没过滤SERVER。
①FILES注入,全局只转义掉GET、POST等传来的参数,遗漏了FILES; ②变量覆盖,危险函数:extract()、 parse_str()、$$。
0x06漏洞防护
基本思路:输入(解决数字型注入)-------转义处理(解决字符型注入)-------输出(解决数据库报错)
1、检查输入的数据是否具有所期望的数据格式。PHP 有很多可以用于检查输入的函数,从简单的变量函数和字符类 型函数(比如 is_numeric(),ctype_digit())到复杂的 Perl 兼容正则表达式函数都可以完成这个工作。如果程序等待 输入一个数字,可以考虑使用 is_numeric() 来检查,或者直接使用 settype() 来转换它的类型,也可以用 sprintf() 把 它格式化为数字。
2、PHP内置转义函数
Addslashes() http://php.net/manual/zh/function.addslashes.php
magic_quote_gpc http://php.net/manual/zh/info.configuration.php#ini.magic-quotes-gpc
mysql_real_escape_string() http://php.net/manual/zh/function.mysql-real-escape-string.php
mysql_escape_string() http://php.net/manual/zh/function.mysql-escape-string.php
3、数据库报错信息泄露防范:
A、把php.ini文件display_errors = Off
B、数据库查询函数前面加一个@字符
C、最有效可预防SQL注入攻击的防御方式:
预处理技术进行数据库查询: