当赋值给PHP变量的整型超过PHP的最大值PHP_INT_MAX时,PHP将无法计算出正确结果,攻击者可能会利用其跳过某些校验逻辑,如密码校验(无须输入正确的密码就可以直接登录用户的账号)、账号充值校验(充值很小的金额就可以进行巨额资金入账)等。下面代码示例中$a、$b、$aa、$bb
均超出了PHP的最大值,所以运算结果超出了预期。
<?php
$a = 92233720368547758079223372036854775807;
$b = 92233720368547758079223372036854775819;
$aa = '92233720368547758079223372036854775807';
$bb = '92233720368547758079223372036854775819';
var_dump($a === $b); //输出bool(true)
var_dump($a%100); //输出int(0)
var_dump($b%100); //输出int(0)
var_dump($aa === $bb); //输出bool(false)
var_dump($aa%100); //输出int(47)
var_dump($bb%100); //输出int(47)
在实际的业务逻辑中(如充值金额、订单数量),一定要对最大值进行限制,避免数据越界而导致错误的执行结果。下面是一段商品购买的示例代码,其中对传入的价格和购买数量进行了范围校验,可避免数据越界产生错误的结果。
$price = $_GET['price'];
$num = $_GET['num'];
if($price<=0){
die("价格必须为正数");
}
if($price>PHP_INT_MAX){
die("价格不能超出系统最大的限制");
}
if($num<=0){
die("购买数量必须为正数");
}
if($num>PHP_INT_MAX){
die("购买数量不能超过系统最大限制");
当赋值给PHP变量超长浮点数时,PHP的结果也将出现错误。在下面的代码示例中,当uid=0.99999999999999999
时,代码逻辑会正常进入if语句,查询出uid=0
的用户信息。以此类推,1.99999999999999999
将会跳入$uid==“2”
的判断中。
$uid = $_GET['uid'];
if($uid == '1'){
$uid = intval($uid);
$query = "select * from 'users' where uid=$uid;"
}
$result = mysql_query($query) or die(mysql_error());
print_r(mysql_fetch_row($result));
在使用变量时要先校验所传入的数据类型是否符合预期,如果超出预期,应该终止系统逻辑执行,避免浮点数在转换成整数时发生意外情况。下面是修复后的代码。
$uid = $_GET['uid'];
if(!is_int($uid)){
die('传入的uid数据类型错误,系统已终止');
}
if($uid == '1'){
$uid = intval($uid);
$query = "select * from 'users' where uid=$uid;"
}
$result = mysql_query($query) or die(mysql_error());
print_r(mysql_fetch_row($result));
在代码中添加is_int($uid)
判断传入的变量是否为整数。如果不是整数,则终止程序的执行。
原文始发于微信公众号(船山信安):渗透培训笔记:数字转换比较缺陷
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论