经过这道题,我真的明白了,我不懂PHP...
0x00 PHP有什么问题
尽管PHP
是最好的语言,但是由于它是弱类型语言,所以它还是存在许多安全问题。
-
精度绕过
php的数值有一定精度,如果超过精度,就会溢出
还有对于指定位数的计算机,所能表示的整数最大值也是有一定范围,如果超过最大值,就取他的最大值。
-
类型转换
is_numberic
函数是用来判断传入的数据是否为数字,或者数字字符串但是,我们可以用一个简单的方法就让他识别错误。
如果,我们传入一个
521ym
,他就会识别不是数字,但是当我们在拿521ym
和520比较时,521ym
就会自动转换为数字521,实现绕过。这就是弱类型带来的危险。 -
==比较
我们知道,在比较两个变量上是否相等有两种方式,
==
,===
那么,他们有什么区别呢?
b :TRUE if b after type juggling.
b : TRUE if b, and they are of the same type.
所以,区别就在于类型转换。
还有,由此引发的还有MD5的绕过问题。
-
其他
比如说,
trim
函数功能缺失,他在代码设计中没有过滤一些字符,比如说:他没有过滤%00
然后,配合
is_numberic
函数,我们就可以做出一些流辟的操作。
0x01 题目解析
题目:http://ctf5.shiyanbar.com/web/PHP/index.php
我们打开题目,可以看到,只有一行“have a fun!!”
于是,我们抓一包,发现有hint,告诉我们代码放在一个txt
中,然后就可以审计代码.....
<?php
$info = "";
$req = [];
$flag="xxxxxxxxxx";
ini_set("display_error", false);
error_reporting(0);
if(!isset($_POST['number'])){
header("hint:6c525af4059b4fe7d8c33a.txt");
die("have a fun!!");
}
foreach([$_POST] as $global_var) {
foreach($global_var as $key => $value) {
$value = trim($value);
is_string($value) && $req[$key] = addslashes($value);
}
}
function is_palindrome_number($number) {
$number = strval($number);
$i = 0;
$j = strlen($number) - 1;
while($i < $j) {
if($number[$i] !== $number[$j]) {
return false;
}
$i++;
$j--;
}
return true;
}
if(is_numeric($_REQUEST['number'])){
$info="sorry, you cann't input a number!";
}elseif($req['number']!=strval(intval($req['number']))){
$info = "number must be equal to it's integer!! ";
}else{
$value1 = intval($req["number"]);
$value2 = intval(strrev($req["number"]));
if($value1!=$value2){
$info="no, this is not a palindrome number!";
}else{
if(is_palindrome_number($req["number"])){
$info = "nice! {$value1} is a palindrome number!";
}else{
$info=$flag;
}
}
}
echo $info;
我们可以发现整个代码的逻辑:
- 我们需要POST一个参数number
- number必须是一个数字(
is_numberic
检验),而且strval(intval($req["number"]))
要和$req["number"]
不同。 - 而且number还需要是一个回文数,又不能是一个回文数。
- 满足以上,
echo
flag
但是,我们知道,intval会把字符串全部返回0,那么就没法和他本身的值相等了。所以,我们不能传入一个非数字字符串,于是,这里我们就用到了%00
来绕过is_numberic
的检验了。
现在,我们已经绕过了,然后需要将他以字符串方式翻转过来不相同,但是以整数方式又是回文,所以,我们用科学计数法绕过,也就是传入0e-0
,其实就是0。
这样我们就拿到了flag。
至于工具,我用的是burpsuite
的repeater
。
0x02 后话
顺便记录一下另一道题吧,用=号去截断sql语句来绕过where的条件判断,题目简单,就不另外写了。
网友评论