2022网鼎杯Web799题涉及SSTI漏洞,通过过滤关键字的Jinja2模板引擎实现命令执行。
前言
本篇考点:ssti注入
本系列为“2022网鼎杯Web真题复现合集”的第6篇,全合集预计10余篇(至少10篇),部分包含Docker可复现环境及WriteUp合集(所有的可复现环境及附件链接均会放在最后),定价为998微信豆,约为99人民币。
适合对象:
-
刚入门CTF想看看历史真题、对大量历史资料无从下手的师傅 -
已学习1-2年Web安全领域的师傅学习 -
适合一些身在网络安全培训前线的讲师们,大可以付费合集之后将赛题放在一些CTFd、GZCTF等平台,将“网络安全奥运会”的真题传递给更多非安全主业的学员们,供学员们学习
购买须知:
-
因所有的Docker复现环境都是赛后自行制作,与2022年实际赛题环境可能有部分出入,但不影响核心考点 -
2022年网鼎杯赛题基本都是以web123这种数字命名,详细考点可以看上方题目清单 -
部分SQL注入、SSTI等内容因为是黑盒,所以不在上方题目清单中,到时视情况放出一些WriteUp -
不提供无偿赛题疑难解答等服务~(只卖艺不卖身) -
部分赛题较为简单,比如PHP反序列化,不会写的太详细 -
不提供在线实时运行的环境,每篇文章文末都会给出附件、Docker环境地址,可以自行启动
web799
这题没有附件,但是直接给了源码:
import osfrom flask import Flask, render_template, request, make_response, redirect, Response, sessionimport flaskapp = flask.Flask(__name__)BLACK_LIST = ['session','config', '__', "'", '"','system', 'os', 'eval', 'exec', 'popen', 'subprocess', 'posix', 'builtins', 'commands', 'open', 'read','select','+','.','\x','\u','arg','session','class','%','self','mro','base','class','flag','global','init','/','decode','00','chr','value','get', 'subclasses', 'form', 'cookies', 'headers','{','}','set','app','config', 'builtins', 'get_flashed_messages']defmake_safe(s):for word in BLACK_LIST:if word in s:assertFalsereturn s@app.route('/', methods=['GET', 'POST'])defindex(): base_dir = os.path.dirname(__file__) resp = make_response(open(os.path.join(base_dir, __file__)).read()) resp.headers["Content-type"] = "text/plain;charset=UTF-8"return resp@app.route("""/'''''' bbbbbbbb 1111111'::::' VVVVVVVV VVVVVVVV lllllll 333333333333333444444444 b::::::b 11111113333333333333331::::::1'::::' V::::::V V::::::V l:::::l 3:::::::::::::::334::::::::4 b::::::b 1::::::13:::::::::::::::331:::::::1':::'' V::::::V V::::::V l:::::l 3::::::33333::::::3 4:::::::::4 b::::::b 1:::::::1 3::::::33333::::::3111:::::1 ':::' V::::::V V::::::V l:::::l 3333333 3:::::3 4::::44::::4 b:::::b 111:::::1 3333333 3:::::3 1::::1 '''' mmmmmmm mmmmmmm V:::::V V:::::Vuuuuuu uuuuuu l::::lnnnn nnnnnnnn 3:::::3rrrrr rrrrrrrrr 4::::4 4::::4 b:::::bbbbbbbbb 1::::1 3:::::3 1::::1 mm:::::::m m:::::::mm V:::::V V:::::V u::::u u::::u l::::ln:::nn::::::::nn 3:::::3r::::rrr:::::::::r 4::::4 4::::4 b::::::::::::::bb 1::::1 3:::::3 1::::1 m::::::::::mm::::::::::m V:::::V V:::::V u::::u u::::u l::::ln::::::::::::::nn 33333333:::::3 r:::::::::::::::::r 4::::4 4::::4 b::::::::::::::::b 1::::1 33333333:::::3 1::::l m::::::::::::::::::::::m V:::::V V:::::V u::::u u::::u l::::lnn:::::::::::::::n 3:::::::::::3 rr::::::rrrrr::::::r4::::444444::::444b:::::bbbbb:::::::b 1::::l 3:::::::::::3 1::::l m:::::mmm::::::mmm:::::m V:::::V V:::::V u::::u u::::u l::::l n:::::nnnn:::::n 33333333:::::3 r:::::r r:::::r4::::::::::::::::4b:::::b b::::::b 1::::l 33333333:::::3 1::::l m::::m m::::m m::::m V:::::V V:::::V u::::u u::::u l::::l n::::n n::::n 3:::::3 r:::::r rrrrrrr4444444444:::::444b:::::b b:::::b 1::::l 3:::::3 1::::l m::::m m::::m m::::m V:::::V:::::V u::::u u::::u l::::l n::::n n::::n 3:::::3 r:::::r 4::::4 b:::::b b:::::b 1::::l 3:::::3 1::::l m::::m m::::m m::::m V:::::::::V u:::::uuuu:::::u l::::l n::::n n::::n 3:::::3 r:::::r 4::::4 b:::::b b:::::b 1::::l 3:::::3111::::::111 m::::m m::::m m::::m V:::::::V u:::::::::::::::uul::::::l n::::n n::::n3333333 3:::::3 r:::::r 4::::4 b:::::bbbbbb::::::b111::::::1113333333 3:::::31::::::::::1 m::::m m::::m m::::m V:::::V u:::::::::::::::ul::::::l n::::n n::::n3::::::33333::::::3 r:::::r 44::::::44b::::::::::::::::b 1::::::::::13::::::33333::::::31::::::::::1 m::::m m::::m m::::m V:::V uu::::::::uu:::ul::::::l n::::n n::::n3:::::::::::::::33 r:::::r 4::::::::4b:::::::::::::::b 1::::::::::13:::::::::::::::33 111111111111 mmmmmm mmmmmm mmmmmm VVV uuuuuuuu uuuullllllll nnnnnn nnnnnn 333333333333333 rrrrrrr 4444444444bbbbbbbbbbbbbbbb 111111111111 333333333333333""", methods=['GET', 'POST'])def calc(): expression = flask.request.args.get("expression") if expression == None: expression = flask.request.form.get("expression") try: return flask.render_template_string("{{" + make_safe(expression) + "}}") except: return 'hackkkkkk'if __name__ == '__main__': app.run(host='0.0.0.0', port=80)
很明显该路由存在SSTI漏洞:

过滤了一大堆关键字

经过测试后,可以利用(request|string)获取URL里的内容,用~进行字符串拼接,利用Jinja2里的lipsum的__globals__键实现命令执行
原文始发于微信公众号(大头SEC):2022网鼎杯 web799
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-


评论