BUUCTF | easy_tornado
第一次遇到模板注入的题,赶紧记笔记,此篇相当于对大佬的做法的复现Orz,师傅太强了https://blog.csdn.net/weixin_44255856/article/details/97687299,这道题出自
2018的护网杯
在hints里看到条件,猜测 ” filename=/fllllllllllllag&filehash=?“,只要构造出这个就行了,但是现在还缺一个cookie_secret
一开始还以为是自己的cookie,构造好提交出现了一个新的界面
菜鸡无奈开始寻求wp,才知道这个error界面就是注入点!!!当然也怪自己,没有留一个心眼,查一下 "render" ,“tornado”这两个关键字(;´д`)ゞ
1 | ?msg={{handler.settings}} |
1 | ?filename=/fllllllllllllag&filehash=78862cd633ce3a864d49ee092d06262d |
资料:
SSTI模板注入:这一篇作者详细的介绍了什么是模板,为什么要用模板,相当的扫盲,强推
Twig 模板引擎注入原理:
12345678<?php
require_once
dirname(
__FILE__
).
'/../lib/Twig/Autoloader.php'
;
Twig_Autoloader::register(true);
$twig
=
new
Twig_Environment(
new
Twig_Loader_String());
$output
=
$twig
->render(
"Hello {{name}}"
,
array
(
"name"
=>
$_GET
[
"name"
]));
// 将用户输入作为模版变量的值
echo
$output
;
?>
使用 Twig 模版引擎渲染页面,其中模版含有 {{name}} 变量,其模版变量值来自于 GET 请求参数 $_GET["name"]。显然这段代码并没有什么问题,即使你想通过 name 参数传递一段 JavaScript 代码给服务端进行渲染,也许你会认为这里可以进行 XSS,但是由于模版引擎一般都默认对渲染的变量值进行编码和转义,所以并不会造成跨站脚本攻击:
但是,如果渲染的模版内容受到用户的控制,情况就不一样了。修改代码为:
1 2 3 4 5 6 7 | <?php require_once dirname( __FILE__ ). '/../lib/Twig/Autoloader.php' Twig_Autoloader::register(true); $twig = new Twig_Environment( new Twig_Loader_String()); $output = $twig ->render( "Hello {$_GET['name']}" ); // 将用户输入作为模版内容的一部分 echo $output ; ?> |
上面这段代码在构建模版时,拼接了用户输入作为模板的内容,现在如果再向服务端直接传递 JavaScript 代码,用户输入会原样输出,测试结果显而易见。在 Twig 模板引擎里, {{var}} 除了可以输出传递的变量以外,还能执行一些基本的表达式然后将其结果作为该模板变量的值,例如这里用户输入 name={{2*10}} ,则在服务端拼接的模版内容为:
这里简单分析一下,由于 {# comment #} 作为 Twig 模板引擎的默认注释形式,所以在前端输出的时候并不会显示,而 {{2*8}} 作为模板变量最终会返回 16 作为其值进行显示,因此前端最终会返回内容 Hello IsVuln16OK ,如下图:
作者:帅猪佩奇链接:https://www.jianshu.com/p/aef2ae0498df 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Python神级框架框架Tornado入门体验:详细的介绍了tornado框架
一个普通的tornado web服务器通常由四大组件组成。
- ioloop实例,它是全局的tornado事件循环,是服务器的引擎核心,示例中
tornado.ioloop.IOLoop.current()
就是默认的tornado ioloop实例。- app实例,它代表着一个完成的后端app,它会挂接一个服务端套接字端口对外提供服务。一个ioloop实例里面可以有多个app实例,示例中只有1个,实际上可以允许多个,不过一般几乎不会使用多个。
- handler类,它代表着业务逻辑,我们进行服务端开发时就是编写一堆一堆的handler用来服务客户端请求。
- 路由表,它将指定的url规则和handler挂接起来,形成一个路由映射表。当请求到来时,根据请求的访问url查询路由映射表来找到相应的业务handler。
这四大组件的关系是,一个ioloop包含多个app(管理多个服务端口),一个app包含一个路由表,一个路由表包含多个handler。ioloop是服务的引擎核心,它是发动机,负责接收和响应客户端请求,负责驱动业务handler的运行,负责服务器内部定时任务的执行。
当一个请求到来时,ioloop读取这个请求解包成一个http请求对象,找到该套接字上对应app的路由表,通过请求对象的url查询路由表中挂接的handler,然后执行handler。handler方法执行后一般会返回一个对象,ioloop负责将对象包装成http响应对象序列化发送给客户端。
作者:Python小老弟 链接:https://www.jianshu.com/p/d1085dbf321f 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Python中从服务端模板注入到沙盒逃逸的源码探索 (一):介绍了python的两个模板引擎——Tornado,Flask
因此,通过
handler.application
即可访问整个Tornado。简单而言通过{{handler.application.settings}}
或者{{handler.settings}}
就可获得settings
中的cookie_secret。
12345678910111213141516class
ErrorHandler(tornado.web.RequestHandler):
def
get(
self
):
msg
=
self
.get_argument(
'msg'
,
'Error'
)
bans
=
[
"\""
,
"'"
,
"["
,
"]"
,
"_"
,
"|"
,
"import"
,
"os"
,
"("
,
")"
,
"+"
,
"-"
,
"*"
,
"/"
,
"\\", "
%
", "
=
"]
for
ban
in
bans:
if
ban
in
msg:
self
.finish(
"ORZ"
)
with
open
(
"error.html"
,
'w'
) as f:
f.write(
"""<html>
<head>
<style>body{font-size: 30px;}</style>
</head>
<body>%s</body>
</html>\n"""
%
msg)
f.flush()
self
.render(
"error.html"
)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异