你真的会php吗
原题链接
http://ctf5.shiyanbar.com/web/PHP/index.php
分析
burp抓包看到响应头中有一个hint。
hint: 6c525af4059b4fe7d8c33a.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); #如果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变换为整型再变换成字符串要和原来number相等
- number不能是一个水仙花数
- number反转要和原来相等
条件1和2矛盾,3和4矛盾。
下面有两种办法解决:
-
number=0e00%00
或者number=0e00%20
%00表示空字符,%20表示空格,这样满足了字符串,相等。
由于0是反转还是0,3,4也满足。 - 利用函数溢出的方法
number=2147483647%00
从这一个题目里面学到一个新点
那就是Intval最大的值取决于操作系统。
32位系统最大带符号的 integer 范围是 -2147483648 到 2147483647。举例,在这样的系统上,intval('1000000000000')
会返回2147483647
。
所以在第三个条件的时候翻转变成7463847412
再变成整形也是2147483647
,绕过第三个条件,第四个条件也就一起绕过了。
flag
第二遍复现时,环境挂了。。。在自己电脑上弄得环境,测试发现payload是正确的。
知识点
代码审计,intval(),溢出