矛盾

开卷看题

代码审计题

代码分析

1
2
3
4
5
6
7
$num=$_GET['num']; // 从GET参数中提取num
if(!is_numeric($num)) // 如果num不是一个数字
{
echo $num; // 输出num的值
if($num==1) // 如果num值弱等于1则输出flag
echo 'flag{**********}';
}

总结:提交一个名为num的GET参数,如果他不是一个数字但是值又弱等于1则输出flag

行吧,终于明白标题的含义了

探索真相

本题中能有暗箱操作的地方只有is_numeric函数和弱等于了

先看看is_numeric函数:函数用于检测变量是否为数字或数字字符串

详细说明参考:PHP官方菜鸟教程

也就是说只要字符串中存在非数字字符即返回false


那么现在的问题就变成了如何在数字字符串中中包含非数字字符,嗯……………….

有了,科学计数法中用e表示10,可能有戏

不清楚的同学先看看这个:科学计数法PHP科学计数法

由于任何数的零次幂都为1,所以我们可以使用1e0表示1

第一次尝试

嗯??为什么不行,这脸打得啪啪的

而且是完全不行,连第一道关卡都没过得去

深刻反思

科学计数法应该没问题啊。为什么会出现这种情况

既然自己不行事,找找别人的参考一下下

翻遍了WP,发现都是说的科学计数法,但是和我想的有一个明显的区别:

别人的payload:1*e*0.1

我的payload:1e0

这就很奇怪了,首先他这表达式就不是科学计数法,其次科学计数法幂数哪来的小数?????

先试试人家的吧,康康情况

这???不会吧,好歹我高考数学也是60分的

为什么???????????????

绝不认输

即便他人的答案是正确的,但是我绝对不相信这是用了科学计数法

开始疯狂尝试payload:

  • 1e0.1
  • 1e0.
  • 1e
  • 1+
  • ………..

  我发现,好像只要在1后面存在非数字字符就可以,这时候我突然想到会不会是在数值转换的过程存在不可告人的秘密呢?

查阅一下资料:PHP数字和字符串比较

总结一下,当字符串和数字进行比较时,系统自动从前到后截取连续的数字字符

  所以为什么他们的payload可以成功?因为号在隐式转换中截断了后续字符所以最终表达式值为1而不是他们以为的科学计数法立的功

  那么为什么1e0不能成功,因为科学计数法也是可以转换为数字的(本来就是数字的表达式),所以你写一个合法的自然就over了,当payload为1e0.1时,由于表达式不是合法的科学计数法,所以从e处截断了,最终为1


最终payload的一种方案为:1加上任意非数字字符即可

后记

  • 善于参考借鉴但是不可盲目相信
  • 一定一定一定要自己多尝试一下,弄懂原理
  • 发现问题一定要尝试,找出原因