详解php比较操作符的安全问题
php  /  管理员 发布于 7年前   168
php的比较操作符有==(等于)松散比较,===(完全等于)严格比较,这里面就会引入很多有意思的问题。 在松散比较的时候,php会将他们的类型统一,比如说字符到数字,非bool类型转换成bool类型,为了避免意想不到的运行效果,应该使用严格比较。如下是php manual上的比较运算符表: 0x01 安全问题 1 hash比较缺陷 php在处理hash字符串的时候会用到!=,==来进行hash比较,如果hash值以0e开头,后边都是数字,再与数字比较,就会被解释成0*10^n还是为0,就会被判断相等,绕过登录环节。 root@kali:~/tool# php -r 'var_dump("00e0345" == "0");var_dump("0e123456789"=="0");var_dump("0e1234abc"=="0");' 当全是数字的时候,宽松的比较会执行尽力模式,如0e12345678会被解释成0*10^12345678,除了e不全是数字的时候就不会相等,这能从var_dump("0e1234abc"=="0")可以看出来。 2 bool 欺骗 当存在json_decode和unserialize的时候,部分结构会被解释成bool类型,也会造成欺骗。json_decode示例代码: 运行结果: root@kali:/var/www# php /root/php/hash.php unserialize示例代码: 运行结果如下: root@kali:/var/www# php /root/php/hash.php 3 数字转换欺骗 将user_id=0.999999999999999999999发送出去得到结果如下: Array 本来是要查询user_id的数据,结果却是user_id=0的数据。int和intval在转换数字的时候都是就低的,再如下代码: 假如传入1.1,就绕过了$_POST['uid']!=1的判断,就能对uid=1的用户进行操作了。另外intval还有个尽力模式,就是转换所有数字直到遇到非数字为止,如果采用: 攻击者传入123456 union select version()进行攻击。 4 PHP5.4.4 特殊情况 这个版本的php的一个修改导致两个数字型字符溢出导致比较相等 $ php -r 'var_dump("61529519452809720693702583126814" == "61529519452809720000000000000000");' 3 题外话: 同样有类似问题的还有php strcmp函数,manual上是这么解释的,int strcmp ( string $str1 , string $str2 ),str1是第一个字符串,str2是第二个字符串,如果str1小于str2,返回<0,如果str1>str2,返回>0,两者相等返回0,假如str2为一个array呢? 运行结果: root@kali:~/php# php strcmp.php 比较多种类型例子 名称 结果$a == $b 等于 TRUE,如果类型转换后 $a 等于 $b。$a === $b 全等 TRUE,如果 $a 等于 $b,并且它们的类型也相同。$a != $b 不等 TRUE,如果类型转换后 $a 不等于 $b。$a <> $b 不等 TRUE,如果类型转换后 $a 不等于 $b。$a !== $b 不全等 TRUE,如果 $a 不等于 $b,或者它们的类型不同。$a < $b 小与 TRUE,如果 $a 严格小于 $b。$a > $b 大于 TRUE,如果 $a 严格大于 $b。$a <= $b 小于等于 TRUE,如果 $a 小于或者等于 $b。$a >= $b 大于等于 TRUE,如果 $a 大于或者等于 $b。
bool(true)
bool(true)
bool(false)$json_str = '{"user":true,"pass":true}';$data = json_decode($json_str,true);if ($data['user'] == 'admin' && $data['pass']=='secirity'){ print_r('logined in as bool'."\n");}
logined in as bool$unserialize_str = 'a:2:{s:4:"user";b:1;s:4:"pass";b:1;}';$data_unserialize = unserialize($unserialize_str);if ($data_unserialize['user'] == 'admin' && $data_unserialize['pass']=='secirity'){ print_r('logined in unserialize'."\n");}
logined in unserialize$user_id = ($_POST['user_id']);if ($user_id == "1"){ $user_id = (int)($user_id); #$user_id = intval($user_id); $qry = "SELECT * FROM `users` WHERE user_id='$user_id';";}$result = mysql_query($qry) or die('
' . mysql_error() . '
' );print_r(mysql_fetch_row($result));
(
[0] => 0
[1] => lxx'
[2] =>
[3] =>
[4] =>
[5] =>
)if ($_POST['uid'] != 1) { $res = $db->query("SELECT * FROM user WHERE uid=%d", (int)$_POST['uid']); mail(...);} else { die("Cannot reset password of admin");}
if (intval($qq) === '123456'){ $db->query("select * from user where qq = $qq")}
bool(true)$_GET['key'] = array();$key = "llocdpocuzion5dcp2bindhspiccy";$flag = strcmp($key, $_GET['key']);if ($flag == 0) { print "Welcome!";} else { print "Bad key!";}
PHP Warning: strcmp() expects parameter 2 to be string, array given in /root/php/strcmp.php on line 13
Welcome!运算数 1 类型 运算数 1 类型 结果 null 或 string string 将 NULL 转换为 "",进行数字或词汇比较 bool 或 null 任何其它类型 转换为 bool,FALSE < TRUE object object 内置类可以定义自己的比较,不同类不能比较,相同类和数组同样方式比较属性(PHP 4 中),PHP 5 有其自己的说明 string,resource或 number string,resource或 number 将字符串和资源转换成数字,按普通数学比较 array array 具有较少成员的数组较小,如果运算数 1 中的键不存在于运算数 2 中则数组无法比较,否则挨个值比较(见下例) array 任何其它类型 array 总是更大 object 任何其它类型 object 总是更大 您可能感兴趣的文章:
122 在
学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..123 在
Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..原梓番博客 在
在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..博主 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..1111 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
Copyright·© 2019 侯体宗版权所有·
粤ICP备20027696号