- 来源:Root-Me
- 题型:Web-Server
- 题目:Server-side Template Injection
- 分数:30 Points
前置知识
SSTI (服务侧模板注入) 题型,此挑战要用到的相关知识可以参考以下文档:
试错
题目要求是读取文件【SECRET_FLAG.txt】的内容。
开启挑战后只有一个输入框,首先试试能不能 XXS ,输入一个探针 <img src=0 />
,发现原文回显,即被过滤了:
然后尝试直接访问 【http://challenge01.root-me.org/web-serveur/ch41/SECRET_FLAG.txt】,理所当然报错:
SSTI 探针
既然这些方法都被封锁了,题目有提示是要用 SSTI 解题,还是不绕弯子实打实做吧~~
但是要使用 SSTI 攻击,首先需要知道这个页面使用了什么模板引擎。
在 网上 找到了 Burp Sutie 提供的一套 payload探针,用于快速确认模板引擎(其中绿色分支表示探针注入成功时的下一个步骤,红色表示注入失败时的下一个步骤):
根据流程按部就班做就可以了。首先输入探针 ${7*7}
,发现 WEB 计算成了 49
,即注入成功:
继续输入下一个探针 a{*comment*}b
,这次原文回显,即注入失败:
继续输入下一个探针 ${"z".join("ab")}
,这次直接返回异常,即注入失败。
从探针流程上看,我们测试得到的模板引擎是 Unknown
。。。
不过仔细观察返回的异常信息,可以看见信息 freemarker
。
从网上找到 freemarker 是属于 Java 语言的模板引擎,因此可以针对性进行注入。
构造 payload
由于题目目标很明确要我们读取文件【SECRET_FLAG.txt】的内容,因此很自然就想到最直接的方法就是使用 系统命令 读取这个文件,例如:cat SECRET_FLAG.txt
。
接下来只需要找到方法“如何通过 freemarker 调用系统命令”即可。
我稍微找了一下就看到了 这篇文章 ,它提供的 payload 还是很简单的:
<#assign exp="freemarker.template.utility.Execute"?new()>
${exp("any system cmd")}
其中第一行的意思是:利用 assign
标签定义一个全局变量 exp
,这个全局变量是通过 freemarker.template.utility.Execute
类 new
出来的一个实例变量。而在 freemarker 中, freemarker.template.utility.Execute
类的功能是调用系统命令。
第二行的意思就更简单了:利用全局变量 exp
调用任意系统命令。
关于 freemarker 的
assign
标签的功能可以参考 这篇文章 。
我们可以通过一个简单的 Linux 系统命令 id
测试它是否起作用,构造 payload 如下(去掉了换行):
<#assign exp="freemarker.template.utility.Execute"?new()>${exp("id")}
成功获取到了当前 Linux 用户的 id 信息。
完成挑战
于是可以开始解题了,首先查看一下 SECRET_FLAG.txt 文件在哪,构造 payload 如下:
<#assign exp="freemarker.template.utility.Execute"?new()>${exp("ls -al")}
很幸运地,这个文件就在当前目录:
最后我们构造 payload 读取这个文件:
<#assign exp="freemarker.template.utility.Execute"?new()>${exp("cat SECRET_FLAG.txt")}
得到 flag ,完成挑战:
答案下载
flag 下载后的 flagzip 的文件需要手动更改后缀为
*.zip
,然后解压即可(为了避免直接刷答案)