源码:
<?php
$info="";
$req=[];
$flag="123456";
ini_set("display_error",false);//为一个配置选项设置值
error_reporting(0);//关闭所有PHP错误报告
if(!isset($_GET['number'])){
header("hint:26966dc52e85af40f59b4fe73d8c323a.txt");//HTTP头显示hint26966dc52e85af40f59b4fe73d8c323a.txt
die("haveafun!!");//die—等同于exit()
}
foreach([$_GET,$_POST]as$global_var){//foreach语法结构提供了遍历数组的简单方式
foreach($global_varas$key=>$value){
$value=trim($value);//trim—去除字符串首尾处的空白字符(或者其他字符)
is_string($value)&&$req[$key]=addslashes($value);//is_string—检测变量是否是字符串,addslashes—使用反斜线引用字符串
}
}
functionis_palindrome_number($number){
$number=strval($number);//strval—获取变量的字符串值
$i=0;
$j=strlen($number)-1;//strlen—获取字符串长度
while($i<$j){
if($number[$i]!==$number[$j]){
returnfalse;
}
$i++;
$j--;
}
returntrue;
}
if(is_numeric($_REQUEST['number']))//is_numeric—检测变量是否为数字或数字字符串
{
$info="sorry,youcann'tinputanumber!";
}
elseif($req['number']!=strval(intval($req['number'])))//intval—获取变量的整数值
{
$info="numbermustbeequaltoit'sinteger!!";
}
else
{
$value1=intval($req["number"]);
$value2=intval(strrev($req["number"]));
if($value1!=$value2){
$info="no,thisisnotapalindromenumber!";
}
else
{
if(is_palindrome_number($req["number"])){
$info="nice!{$value1}isapalindromenumber!";
}
else
{
$info=$flag;
}
}
}
echo$info;
函数释义:
strval()函数用于获取变量的字符串值。
intval()函数用于获取变量的整数值。
is_numeric()函数在开始判断前,会先跳过所有空白字符,这是该函数的一个特性。
因此,is_numeirc(" \r\n \t 1.2")返回true。
同理,也会intval(" \r\n \t 12")正常返回12。
trim()过滤空白字符和is_numeric()、intval()这两个函数的跳过空白字符的区别是少了一个“ \ f”。
strrev()函数反转字符串,示例:
is_palindrome_number函数内容如下,意思是需要回文数,回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
代码分析:
1.条件is_numeric($_REQUEST['number'])为假,绕过方法有两种:
1)%00开头绕过,
2)再POST一个number参数把GET中的覆盖掉;
2.要求 $req['number']==strval(intval($req['number']));
3.要求intval($req['number']) == intval(strrev($req['number']);
4.is_palindrome_number()返回False,这个条件只要在一个回文数比如191前面加一个字符即可实现
5.判断语句部分如下:
if(is_numeric($_REQUEST['number']))//is_numeric—检测变量是否为数字或数字字符串
elseif($req['number']!=strval(intval($req['number'])))//intval—获取变量的整数值
intval($req["number"])==intval(strrev($req["number"]))
if(is_palindrome_number($req["number"]))
解题过程:
用\f(也就是%0c)在回文数前面,来绕过is_palindrome_number函数,intval和is_numeric都会忽略这个字符,所以不会影响前面的三个判断。
1.访问原始页面链接
http://localhost:63342/test/2.php
2.获取flag
http://localhost:63342/test/2.php?number=%00%0c191
参考链接:
https://www.leavesongs.com/PENETRATION/some-sangebaimao-ctf-writeups.html
https://github.com/bowu678/php_bugs