-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
152 lines (121 loc) · 4.61 KB
/
app.py
File metadata and controls
152 lines (121 loc) · 4.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import os
from flask import Flask
from dotenv import load_dotenv
from flask import request, redirect, url_for, session
from db import get_db
from db import init_db
load_dotenv() # loads variables from .env into environment
def create_app():
app = Flask(__name__)
# Secret key for sessions (Week 1+)
app.secret_key = os.getenv("FLASK_SECRET_KEY", "dev-secret-change-me")
# Our lab mode toggle
app.config["APP_MODE"] = os.getenv("APP_MODE", "vulnerable").lower()
if app.config["APP_MODE"] not in {"vulnerable","secure"}:
app.config["APP_MODE"] = "vulnerable"
@app.route("/")
def home():
mode = app.config["APP_MODE"]
return f"""
<h2>Python Vulnerable Web Lab is running 🚀 | mode={mode}</h2>
<p><a href="/logout">Logout</a></p>
"""
@app.route("/health")
def health():
return {"status": "ok", "mode": app.config["APP_MODE"]}
@app.route("/login", methods=["GET","POST"])
def login():
if request.method == "GET":
return """
<h2>Login</h2>
<form method="POST">
<input name="email" placeholder="Email"><br><br>
<input name="password" type="password" placeholder="Password"><br><br>
<button type="submit">Login</button>
</form>
"""
email = (request.form.get("email") or "").strip().lower()
password = request.form.get("password") or ""
if not email or not password:
return "Email and password are required.", 400
conn = get_db()
cursor = conn.cursor()
cursor.execute(
"SELECT * FROM users WHERE email = ?",
(email,)
)
user = cursor.fetchone()
conn.close()
if not user:
return "Invalid email or password", 401
if app.config["APP_MODE"] == "vulnerable":
if password != user["password"]:
return "Invalid Password", 401
session["user_id"] = user["id"]
session["role"] = user["role"]
return redirect(url_for("home"))
@app.route("/register", methods=["GET", "POST"])
def register():
# 1) If user is just visiting the page, show the form
if request.method == "GET":
return """
<h2>Register</h2>
<form method="POST">
<input name="email" placeholder="Email"><br><br>
<input name="password" type="password" placeholder="Password"><br><br>
<button type="submit">Create Account</button>
</form>
<p>Already have an account? <a href="/login">Login</a></p>
"""
#2) If user submitted the form (POST), read their input
email = (request.form.get("email") or "").strip().lower()
password = request.form.get("password") or ""
# 3) Basic validation (keep it simple)
if not email or not password:
return "Email and password are required.", 400
# 4) Insert into DB
conn = get_db()
cursor = conn.cursor()
try:
# In vulnerable mode we store plaintext password (INTENTIONALLY INSECURE for learning)
cursor.execute(
"INSERT INTO users (email, password, role) VALUES (?, ?, ?)",
(email,password,"user")
)
conn.commit()
new_user_id = cursor.lastrowid
except Exception as e:
conn.close()
# Most common error here is email already exists (UNIQUE constraint)
return f"Registration failed: {e}", 400
@app.route("/logout")
def logout():
session.pop("user_id", None)
session.pop("role", None)
return redirect(url_for("login"))
@app.route("/me")
def me():
user_id = session.get("user_id")
if not user_id:
return {"error": "Not log in"}, 401
conn = get_db()
cursor = conn.cursor()
cursor.execute(
"SELECT id, email, role FROM users WHERE id = ?",
(user_id,)
)
user = cursor.fetchone()
conn.close()
if not user:
return {"error": "User not found"}, 404
# sqlite3.Row -> dict conversion
return {"id": user["id"], "email": user["email"], "role": user["role"]}
conn.close()
session["user_id"] = new_user_id
session["role"] = "user"
return redirect(url_for("home"))
return app
if __name__ == "__main__":
init_db()
app = create_app()
app.run(host="127.0.0.1", port=5000, debug=True)