本来不想更的,因为懒。
其实是手头的项目有点积压!T T
后来今天看到了一题CTF,和同事研究了下,觉得不错。分享给了团队的学弟妹们。只不过懒,没有时间写write up,就让达写了。
-------------------------------------------
Vaf大兄弟搞了一个CTF题,题目是这样的(大牛可以略过):
最终目的就是要通过重重的ifelse难关获取到这里面的东西。
废话不多说,拿源码自己本地搭建下。
搭完后开搞。
首先第一步:从源码得知,只要4个key不为空的get传输,就可以进去第一个if
很好,成功报错,我们突破了第一个门槛的if。
接着看源码
Intval()的意思是对括号的值取整(去掉小数部分)。
我们如果要进入到if($key1 == 1) 里面,既要让intval($key)<1又要让$key1=1…...这尼玛。。。。
不过这还是很容易过去的。(实际上在0~1之间徘徊了一小会)
介绍两种方法:
1、$key1=0.99999999999999999999(输入一大串9,不行继续输)
2、$key1=0x1(16进制表示,intval(0x1)后得到为0)
得到:
结果改变,这样就成功的进去了我们要进的if块。
然后继续,我们需要改变$key2的值进入到如下红框部分,即$key2>=1 and intval($key2+$key1)<=1
这个边工作边搞定的,搞了很久。试了下$key2=0.99999999999999999999999999999、$key2=0x1无果。
最后直接$key2=99999999999999999999或者0xffffffffffffff(16进制)或者077777777777777777(八进制)
数据溢出绕过。
分析下原因,这里是为整数类型的,学过C语言的都知道(long long int最大值9223372036854775807,int最大值2147438647)
当超过这个最大值时就会发生数据溢出,因此只要$key2直接大于这个最大值(我选long long int),数据溢出后变成负数就绕过了。
我们终于走到这里了。离最后的flag只差一步之遥了。
只要$key3和$key4都是整数,并且$key3和$key4又不全是整数,就可以拿到flag了。
看到这里,是不是感觉有点不可能。哈哈。
实际上这里都是is_numeric这个函数在作怪。
这个算是php的一个黑魔法,因为当有两个is_numeric进行判断并且用and连接时,and后面的is_numeric无论判断的是不是数字皆可以绕过。
也就是说
$check = is_numeric(123) and is_numeric(123),//$check=1;
$check = is_numeric(123) and is_numeric(‘abc’),//$check=1;
看到这里,知道该怎么做了吧。
成功get。
感谢vaf大表哥平台。
提醒:可以试着将每个key的值输出,以及他们intval的值,以便观察。
后面说下,为什么要给达打码呢?因为他是色达!