php中的浮点数安全问题

关于浮点数, php语言里使用float表达,其他语言一般也是,这个是通用的。

英文里有浮动的意思, 从英文解释里, 也许就能猜的出来浮点数的大概意思,这个时候我们首先就想到了,它也许是不确定的, 因为是(浮动)。

咱们回到php语言中, 在php语言中, float说的其实是多种数据类型的一种, 浮点型。

浮点型数据咱们简单点理解就是, 它是一个包含小数的数, 只能用来表示近似, 不能完全确定, 比如取3.1415926 ~ 精确到第几位, 工程计算中误差要达到什么等级, 这个时候要用到的就是浮点数。

比如

$woshifudianshu = 3.1415926;
var_dump($woshifudianshu);

这个时候得到的就会是一个float(3.1415926) 。

我们有时候会看到, 有一些大牛在代码审计绕过一些函数的时候, 使用到了.0这种或者类似的表达形式, 有些人可能知道它这是浮点数,有些人可能不会太理解, 这里就来说一下, 继续看例子。

<?php

$a = 0;
$b = .0;  // float 0
var_dump($b);

?>

这个时候, 通过var_dump方法打印出来的函数$b得到的结果就是一个float 0。我们又知道了, 在php中可以用is_numeric来判断它是不是一个数字

is_numeric的原则是, 如果为NULL或者为空或者其他非数字, 就为False,否则就为True。咱们来看一下。

<?php

$a = NULL;
$b = .0;  // float 0
var_dump($b);

if(is_numeric($a))
{
  echo "报告大哥,是数字!";
}
else
{
  echo "不是数字!!";
}
?>

因为这个时候, 变量$a被设置成了NULL, 也就是空, 所以输出不是数字。

<?php

$a = 'aaaa';
$b = .0;  // float 0
var_dump($b);

if(is_numeric($a))
{
  echo "报告大哥,是数字!";
}
else
{
  echo "不是数字!!";
}


?>

变量$a对应的是字符串aaaa,故还是输出, 不是数字!!。

<?php

$a = 'aaaa';
$b = .0;  // float 0
var_dump($b);

if(is_numeric($b))
{
  echo "报告大哥,是数字!";
}
else
{
  echo "不是数字!!";
}


?>

变量b, 是一个浮点数, 故is_numberic不会把.判断成其他类型, 所以输出, 报告大哥, 是数字。

这个时候场景来了, 我写了一个功能, 只有进入逻辑与(&&,都为正时才为正,否则为False)判断结果为正时才会执行, 逻辑与里用到了is_numeric和preg_match, 而preg_match又没考虑到浮点数的问题于是这个时候我们输入.0 is_numeric判断它是一个数字(浮点型), preg正则里又没有对它进行过滤, 于是都为正, 顺利进入执行, 造成绕过问题, 如果这个时候正里写的功能是上传, 文件就会被顺利上传, 如果是登录, 就会被绕过登录以此类推。

关于防御, 方法有很多

1. 可以在带入前先对数据类型进行转换,可以专门处理不允许.x这种类型数据的输入。

2. 可以用replace方法把它替换成指定信息。

3. 可以使用取反判断。

4. 可以判断ascii值

5. 使用逻辑运算式

扩展

练习使用正则过滤浮点数问题。

学习如何在进入判断前对其类型进行转换。

自行研究更多防御方法。

一个小Demo(注意,只是演示如何过滤.0的一种,这样并不安全)

<?php

$a = $_GET['num'];
$a = str_replace(".0","fuckyou",$a);
echo $a;

?>
此条目发表在php security分类目录,贴了, , , , 标签。将固定链接加入收藏夹。

发表评论

电子邮件地址不会被公开。 必填项已用*标注