-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathpython-authentication-failures.mdc
More file actions
338 lines (285 loc) · 13.5 KB
/
python-authentication-failures.mdc
File metadata and controls
338 lines (285 loc) · 13.5 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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
---
description: Detect and prevent identification and authentication failures in Python applications as defined in OWASP Top 10:2021-A07
globs: *.py, *.ini, *.cfg, *.yml, *.yaml, *.json, *.toml
alwaysApply: false
---
# Python Identification and Authentication Failures Standards (OWASP A07:2021)
This rule enforces security best practices to prevent identification and authentication failures in Python applications, as defined in OWASP Top 10:2021-A07.
<rule>
name: python_authentication_failures
description: Detect and prevent identification and authentication failures in Python applications as defined in OWASP Top 10:2021-A07
filters:
- type: file_extension
pattern: "\\.(py|ini|cfg|yml|yaml|json|toml)$"
- type: file_path
pattern: ".*"
actions:
- type: enforce
conditions:
# Pattern 1: Weak password validation
- pattern: "password\\s*=\\s*['\"][^'\"]{1,7}['\"]|min_length\\s*=\\s*[1-7]"
message: "Weak password policy detected. Passwords should be at least 8 characters long and include complexity requirements."
# Pattern 2: Hardcoded credentials
- pattern: "(username|user|login|password|passwd|pwd|secret|api_key|apikey|token)\\s*=\\s*['\"][^'\"]+['\"]"
message: "Hardcoded credentials detected. Store sensitive credentials in environment variables or a secure vault."
# Pattern 3: Missing password hashing
- pattern: "password\\s*=\\s*request\\.form\\[\\'password\\'\\]|password\\s*=\\s*request\\.POST\\.get\\(\\'password\\'\\)"
message: "Storing or comparing plain text passwords detected. Always hash passwords before storage or comparison."
# Pattern 4: Insecure password hashing
- pattern: "hashlib\\.md5\\(|hashlib\\.sha1\\(|hashlib\\.sha224\\("
message: "Insecure hashing algorithm detected. Use strong hashing algorithms like bcrypt, Argon2, or PBKDF2."
# Pattern 5: Missing brute force protection
- pattern: "@app\\.route\\(['\"]\\/(login|signin|authenticate)['\"]"
message: "Authentication endpoint detected without rate limiting or brute force protection. Implement account lockout or rate limiting."
# Pattern 6: Insecure session management
- pattern: "session\\[\\'user_id\\'\\]\\s*=|session\\[\\'authenticated\\'\\]\\s*=\\s*True"
message: "Session management detected. Ensure proper session security with secure cookies, proper expiration, and rotation."
# Pattern 7: Missing CSRF protection in authentication
- pattern: "form\\s*=\\s*FlaskForm|class\\s+\\w+Form\\(\\s*FlaskForm\\s*\\)|class\\s+\\w+Form\\(\\s*Form\\s*\\)"
message: "Form handling detected. Ensure CSRF protection is enabled for all authentication forms."
# Pattern 8: Insecure remember me functionality
- pattern: "remember_me|remember_token|stay_logged_in"
message: "Remember me functionality detected. Ensure secure implementation with proper expiration and refresh mechanisms."
# Pattern 9: Insecure password reset
- pattern: "@app\\.route\\(['\"]\\/(reset-password|forgot-password|recover)['\"]"
message: "Password reset functionality detected. Ensure secure implementation with time-limited tokens and proper user verification."
# Pattern 10: Missing multi-factor authentication
- pattern: "def\\s+login|def\\s+authenticate|def\\s+signin"
message: "Authentication function detected. Consider implementing multi-factor authentication for sensitive operations."
# Pattern 11: Insecure direct object reference in user management
- pattern: "User\\.objects\\.get\\(id=|User\\.query\\.get\\(|get_user_by_id\\("
message: "Direct user lookup detected. Ensure proper authorization checks before accessing user data."
# Pattern 12: Insecure JWT implementation
- pattern: "jwt\\.encode\\(|jwt\\.decode\\("
message: "JWT usage detected. Ensure proper signing, validation, expiration, and refresh mechanisms for JWTs."
# Pattern 13: Missing secure flag in cookies
- pattern: "set_cookie\\([^,]+,[^,]+,[^,]*secure=False|set_cookie\\([^,]+,[^,]+(?!,\\s*secure=True)"
message: "Cookie setting without secure flag detected. Set secure=True for all authentication cookies."
# Pattern 14: Missing HTTP-only flag in cookies
- pattern: "set_cookie\\([^,]+,[^,]+,[^,]*httponly=False|set_cookie\\([^,]+,[^,]+(?!,\\s*httponly=True)"
message: "Cookie setting without httponly flag detected. Set httponly=True for all authentication cookies."
# Pattern 15: Insecure default credentials
- pattern: "DEFAULT_USERNAME|DEFAULT_PASSWORD|ADMIN_USERNAME|ADMIN_PASSWORD"
message: "Default credential configuration detected. Remove default credentials from production code."
- type: suggest
message: |
**Python Authentication Security Best Practices:**
1. **Password Storage:**
- Use strong hashing algorithms with salting
- Implement proper work factors
- Example with passlib:
```python
from passlib.hash import argon2
# Hash a password
hashed_password = argon2.hash("user_password")
# Verify a password
is_valid = argon2.verify("user_password", hashed_password)
```
- Example with Django:
```python
from django.contrib.auth.hashers import make_password, check_password
# Hash a password
hashed_password = make_password("user_password")
# Verify a password
is_valid = check_password("user_password", hashed_password)
```
2. **Password Policies:**
- Enforce minimum length (at least 8 characters)
- Require complexity (uppercase, lowercase, numbers, special characters)
- Check against common passwords
- Example with Django:
```python
# settings.py
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'OPTIONS': {'min_length': 12}
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
]
```
3. **Brute Force Protection:**
- Implement account lockout after failed attempts
- Use rate limiting for authentication endpoints
- Example with Flask and Flask-Limiter:
```python
from flask import Flask
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
app = Flask(__name__)
limiter = Limiter(
app,
key_func=get_remote_address,
default_limits=["200 per day", "50 per hour"]
)
@app.route("/login", methods=["POST"])
@limiter.limit("5 per minute")
def login():
# Login logic here
pass
```
4. **Multi-Factor Authentication:**
- Implement MFA for sensitive operations
- Use time-based one-time passwords (TOTP)
- Example with pyotp:
```python
import pyotp
# Generate a secret key for the user
secret = pyotp.random_base32()
# Create a TOTP object
totp = pyotp.TOTP(secret)
# Verify a token
is_valid = totp.verify(user_provided_token)
```
5. **Secure Session Management:**
- Use secure, HTTP-only cookies
- Implement proper session expiration
- Rotate session IDs after login
- Example with Flask:
```python
from flask import Flask, session
app = Flask(__name__)
app.config.update(
SECRET_KEY='your-secret-key',
SESSION_COOKIE_SECURE=True,
SESSION_COOKIE_HTTPONLY=True,
SESSION_COOKIE_SAMESITE='Lax',
PERMANENT_SESSION_LIFETIME=timedelta(hours=1)
)
```
6. **CSRF Protection:**
- Implement CSRF tokens for all forms
- Validate tokens on form submission
- Example with Flask-WTF:
```python
from flask_wtf import FlaskForm, CSRFProtect
from wtforms import StringField, PasswordField, SubmitField
csrf = CSRFProtect(app)
class LoginForm(FlaskForm):
username = StringField('Username')
password = PasswordField('Password')
submit = SubmitField('Login')
```
7. **Secure Password Reset:**
- Use time-limited, single-use tokens
- Send reset links to verified email addresses
- Example implementation:
```python
import secrets
from datetime import datetime, timedelta
def generate_reset_token(user_id):
token = secrets.token_urlsafe(32)
expiry = datetime.utcnow() + timedelta(hours=1)
# Store token and expiry in database with user_id
return token
def verify_reset_token(token):
# Retrieve token from database
# Check if token exists and is not expired
# If valid, return user_id
pass
```
8. **Secure JWT Implementation:**
- Use strong signing keys
- Include expiration claims
- Validate all claims
- Example with PyJWT:
```python
import jwt
from datetime import datetime, timedelta
# Create a JWT
payload = {
'user_id': user.id,
'exp': datetime.utcnow() + timedelta(hours=1),
'iat': datetime.utcnow()
}
token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')
# Verify a JWT
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
user_id = payload['user_id']
except jwt.ExpiredSignatureError:
# Token has expired
pass
except jwt.InvalidTokenError:
# Invalid token
pass
```
9. **Secure Cookie Configuration:**
- Set secure, HTTP-only, and SameSite flags
- Example with Flask:
```python
from flask import Flask, make_response
app = Flask(__name__)
@app.route('/set_cookie')
def set_cookie():
resp = make_response('Cookie set')
resp.set_cookie(
'session_id',
'value',
secure=True,
httponly=True,
samesite='Lax',
max_age=3600
)
return resp
```
10. **Credential Storage:**
- Use environment variables or secure vaults
- Never hardcode credentials
- Example with python-dotenv:
```python
import os
from dotenv import load_dotenv
load_dotenv()
# Access credentials from environment variables
db_user = os.environ.get('DB_USER')
db_password = os.environ.get('DB_PASSWORD')
```
- type: validate
conditions:
# Check 1: Proper password hashing
- pattern: "argon2|bcrypt|pbkdf2|make_password|generate_password_hash"
message: "Using secure password hashing algorithms."
# Check 2: CSRF protection
- pattern: "csrf|CSRFProtect|csrf_token|csrftoken"
message: "CSRF protection is implemented."
# Check 3: Secure cookie settings
- pattern: "SESSION_COOKIE_SECURE\\s*=\\s*True|secure=True|httponly=True|samesite"
message: "Secure cookie settings are configured."
# Check 4: Rate limiting
- pattern: "limiter\\.limit|RateLimitExceeded|rate_limit|throttle"
message: "Rate limiting is implemented for authentication endpoints."
metadata:
priority: high
version: 1.0
tags:
- security
- python
- authentication
- identity
- owasp
- language:python
- framework:django
- framework:flask
- framework:fastapi
- category:security
- subcategory:authentication
- standard:owasp-top10
- risk:a07-identification-authentication-failures
references:
- "https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures/"
- "https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html"
- "https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html"
- "https://cheatsheetseries.owasp.org/cheatsheets/Credential_Stuffing_Prevention_Cheat_Sheet.html"
- "https://docs.djangoproject.com/en/stable/topics/auth/passwords/"
- "https://flask-login.readthedocs.io/en/latest/"
- "https://fastapi.tiangolo.com/tutorial/security/"
</rule>