π CSRF Tutorial β Flask Lab + WebGoat + Docker¶
π What is CSRF?¶
CSRF (Cross-Site Request Forgery) tricks a userβs browser into performing unwanted actions on a web app where they're authenticated.
π§ Example:¶
You're logged into your bank β a malicious site sends a hidden request to transfer money β browser sends the request with your session.
β οΈ Real-World Scenario¶
Victim logs into:
Attacker makes victim visit:
Browser sends this request with victimβs cookies/session, completing the transaction silently.
π§ͺ 1. Build Your Own CSRF Vulnerable Flask App¶
π Project Structure:¶
π app.py¶
from flask import Flask, request, render_template_string, redirect, make_response
app = Flask(__name__)
user_balance = {"yuva": 1000}
@app.route("/", methods=["GET", "POST"])
def home():
msg = ""
if request.method == "POST":
to = request.form.get("to")
amount = int(request.form.get("amount"))
user_balance["yuva"] -= amount
msg = f"πΈ Transferred {amount} to {to}. Remaining: {user_balance['yuva']}"
html = '''
<h2>Welcome Yuva</h2>
<p>Balance: {{ balance }}</p>
<form method="POST" action="/">
<input type="text" name="to" placeholder="Send to">
<input type="number" name="amount" value="100">
<button type="submit">Send</button>
</form>
<p style="color:green">{{ msg }}</p>
'''
return render_template_string(html, balance=user_balance["yuva"], msg=msg)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
π requirements.txt¶
π Dockerfile¶
FROM python:3.11-slim
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
EXPOSE 5000
CMD ["python", "app.py"]
βΆοΈ Build & Run¶
Visit β http://localhost:5000
π§ͺ Simulate CSRF Attack¶
Create an attacker.html file with this code:
<html>
<body>
<h1>π Hacked</h1>
<form action="http://localhost:5000/" method="POST" style="display:none">
<input name="to" value="hacker">
<input name="amount" value="500">
<input type="submit">
</form>
<script>document.forms[0].submit();</script>
</body>
</html>
Open attacker.html while you're logged into localhost:5000.
Boom π₯ β money sent without confirmation.
π‘οΈ 2. Preventing CSRF¶
β Add CSRF Tokens¶
Use Flask-WTF for token-based protection:
Update app.py:
from flask_wtf import FlaskForm
from wtforms import StringField, IntegerField, SubmitField
from wtforms.validators import InputRequired
from flask import Flask, render_template_string
from flask_wtf.csrf import CSRFProtect
app = Flask(__name__)
app.secret_key = "secret"
csrf = CSRFProtect(app)
class TransferForm(FlaskForm):
to = StringField("To", validators=[InputRequired()])
amount = IntegerField("Amount", validators=[InputRequired()])
submit = SubmitField("Send")
Use {{ form.csrf_token }} in the HTML to embed a hidden token input. Now CSRF won't work.
π§ͺ 3. Practice CSRF in WebGoat¶
π³ WebGoat + WebWolf Docker¶
Access lessons:
-
WebGoat: http://localhost:8080/WebGoat
-
Login:
guest / guest
π Go to A1 - Injection β CSRF β Practice real-world examples with step-by-step guidance.
π§ Summary¶
| Concept | Details |
|---|---|
| CSRF | Trick userβs browser into sending unwanted requests |
| Fix 1 | CSRF tokens in forms |
| Fix 2 | SameSite cookies (Lax or Strict) |
| Fix 3 | Check Referer / Origin headers |
| Fix 4 | Use secure frameworks like Flask-WTF, Django, etc. |