php_bugs学习 02 绕过过滤的空白字符

<?php
 
$info = ""; 
$req = [];
$flag="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
 
ini_set("display_error", false); //为一个配置选项设置值
error_reporting(0); //关闭所有PHP错误报告
 
if(!isset($_GET['number'])){
   header("hint:26966dc52e85af40f59b4fe73d8c323a.txt"); //HTTP头显示hint 26966dc52e85af40f59b4fe73d8c323a.txt
 
   die("have a fun!!"); //die — 等同于 exit()
 
}
 
foreach([$_GET, $_POST] as $global_var) {  //foreach 语法结构提供了遍历数组的简单方式 
    foreach($global_var as $key => $value) { 
        $value = trim($value);  //trim — 去除字符串首尾处的空白字符(或者其他字符)
        is_string($value) && $req[$key] = addslashes($value); // is_string — 检测变量是否是字符串,addslashes — 使用反斜线引用字符串
    } 
} 
 
 
function is_palindrome_number($number) { 
    $number = strval($number); //strval — 获取变量的字符串值
    $i = 0; 
    $j = strlen($number) - 1; //strlen — 获取字符串长度
    while($i < $j) { 
        if($number[$i] !== $number[$j]) { 
            return false; 
        } 
        $i++; 
        $j--; 
    } 
    return true; 
} 
 
 
if(is_numeric($_REQUEST['number'])) //is_numeric — 检测变量是否为数字或数字字符串 
{
 
   $info="sorry, you cann't input a number!";
 
}
elseif($req['number']!=strval(intval($req['number']))) //intval — 获取变量的整数值
{
 
     $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;
          }
     }
 
}

正好代码的注释比较多,一句一句审计一下

代码审计

RfOr8S.png

!isset如果不存在GET请求的number值,就在返回包中的header添加hint
代码结束,返回have_fun

RfOXUx.png

foreach将传入的GET和POST请求遍历赋值给$global_var

RfXdsJ.png

然后将$global_var的值变为键值对应的形式,有点类似于python中的字典?

trim($value) 去除字符串首尾处的空白字符(或者其他字符)

is_string检查value是否为字符串,&&,如果是字符串的话就通过addslashes给字符串加反斜线

这一步相当于把传入的数据清洗了一遍

Rfj4cF.png

is_palindrome_number验证回文数字的意思

如果不是回文的话,直接返回false

RfvHKg.png

判断:
1.传入的number如果数字=>返回sorry, you cann't input a number!
2.传入的number如果能被自身整除,返回number must be equal to it's integer!!

Rfx8II.png

也就是说,传入的number不但要求不是数字,还要求它本身能被自己整除

感觉是个悖论,不是么

RfxMse.png

判断:
1.要求这个字符串是自己本身的反转

RfxNz8.png

2.要求传入的数值是回文

解题

要求:

1.条件is_numeric($_REQUEST['number'])为假,这个绕过的方法很多使用%00开头就行,也可以再POST一个number参数把GET中的覆盖掉也可以,所以这一步很简单。
2.要求 $req['number']==strval(intval($req['number']))
3.要求intval($req['number']) == intval(strrev($req['number']))
4.is_palindrome_number()返回False,这个条件只要在一个回文数比如191前面加一个字符即可实现得到flag

函数对空白字符的特性 is_numeric函数在开始判断前,会先跳过所有空白字符。

也就是说,is_numeirc(” \r\n \t 1.2″)是会返回true的。同理,intval(” \r\n \t 12″),也会正常返回12。

可以引入\f(也就是%0c)在数字前面,来绕过最后那个is_palindrome_number函数,而对于前面的数字判断,因为intval和is_numeric都会忽略这个字符(因为\f也是空白字符),所以不会影响。

payload:

%00%0c191
posted @ 2021-07-05 00:22  MuRKuo  阅读(621)  评论(0编辑  收藏  举报