PHP的一些另类用法

今天来讨论一道php代码审计的题,这是一道实验吧的题,链接: http://ctf5.shiyanbar.com/web/PHP/index.php 。
首先我们点开链接,并且查看源代码,

发现什么都没有,这时候我们想,我们想源码可能在服务器端,我们用burpsuit抓个包,发给Reapeater。

从服务器响应的文件,我们可以发现以下对我们有用的信息。
1.服务器的系统是32位的系统。
2.响应的文件是6c525af4059b4fe7d8c33a.txt
接下来我们访问一下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); //trim() 函数移除字符串两侧的空白字符或其他预定义字符。
is_string($value) && $req[$key] = addslashes($value);
}
}
//global $var是外部$var的同名引用或者指针。
//函数
function is_palindrome_number($number) {
$number = strval($number); //本函数可将数组及类之外的变量类型转换成字符串类型。
$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'])){

$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"])); //strrev() 函数反转字符串。

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;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
经过审计我们可以发现如果我们要拿到flag,POST的number需要满足以下条件:
1.不为空,且不能是一个数值型数字,包括小数。(由is_numeric函数判断)
2.不能是一个回文数。(is_palindrome_number判断)
3.该数的反转的整数值应该和它本身的整数值相等。即:

intval($req["number"])=intval(strrev($req["number"]))
1
回文数就是类似于121这样的数。从上面可以看出2,3条件似乎是冲突滴!

下面给出两种解法:

1.利用intval函数溢出绕过
Intval函数获取变量整数值。
函数介绍清点这里
Intval最大的值取决于操作系统。 32 位系统最大带符号的 integer 范围是 -2147483648 到 2147483647。举例,在这样的系统上, intval(‘1000000000000’) 会返回 2147483647。64 位系统上,最大带符号的 integer 值是 9223372036854775807。

通过上面我们知道服务器的操作系统是32位的,所以我们构造2147483647就可以同时满足2,3条件。通过把空字符可以绕过is_numeric的判断(如%00,%20),所以我们构造以下poc,number=2147483647%00 和number=2147483647%20都可。

对于第一个条件,我们需要构造是让我们的poc被函数判断为非数值,但又不影响它值的构造,理所当然想到空格字符和空字符。

而经过测试我发现is_numeric函数对于空字符%00,无论是%00放在前后都可以判断为非数值,而%20空格字符只能放在数值后。所以,查看函数发现该函数对对于第一个空格字符会跳过空格字符判断,接着后面的判断!!


2.用科学计数法构造0=0
因为要求不能为回文数,但又要满足intval($req["number"])=intval(strrev($req["number"])),所以我们采用科学计数法构造poc为number=0e-0%00,这样的话我们就可以绕过。

不积硅步无以至千里,希望大家在进步的阶梯里不断前行!
---------------------
作者:JBlock
来源:CSDN
原文:https://blog.csdn.net/JBlock/article/details/78745513
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自www.cnblogs.com/chenchen599/p/9845415.html