Skip to content

Commit 2ee1e88

Browse files
authored
Merge branch 'main' into feature/cyber-challenges-quiz-compiler-clean
2 parents c86bcf3 + 95243c4 commit 2ee1e88

23 files changed

Lines changed: 31816 additions & 27906 deletions

core/middleware.py

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@
77
from django.urls import reverse
88
from django.conf import settings
99
from django.middleware.locale import LocaleMiddleware
10+
from django.http import HttpResponseNotFound
1011
from django.utils import translation
12+
from django.shortcuts import render
13+
1114
logger = logging.getLogger('admin_logout_logger')
15+
Honeypot_logger = logging.getLogger("honeypot_logger")
1216

1317
class AutoLogoutMiddleware(MiddlewareMixin):
1418
"""
@@ -26,10 +30,6 @@ def process_request(self, request):
2630
elif is_admin_page:
2731
request.session['admin_session'] = True
2832

29-
30-
31-
32-
3333
class LogRequestMiddleware:
3434
"""
3535
Middleware to log IP address and accessed URL.
@@ -98,17 +98,11 @@ def __call__(self, request):
9898

9999
return response
100100

101-
# Continue processing the request
102-
return self.get_response(request)
103-
104-
105-
106101
def log_request(self, request):
107102
ip = self.get_client_ip(request)
108103
path = request.path
109-
110-
# Log the information
111104
logger.info(f"IP: {ip} accessed {path}")
105+
112106
def get_client_ip(self, request):
113107
"""
114108
Extracts client IP address from request headers.
@@ -118,11 +112,8 @@ def get_client_ip(self, request):
118112
ip = x_forwarded_for.split(',')[0]
119113
else:
120114
ip = request.META.get('REMOTE_ADDR')
121-
return ip
122-
123-
115+
return ip
124116

125-
126117
try:
127118
from django.utils.translation import LANGUAGE_SESSION_KEY # Django 4+
128119
except Exception:
@@ -148,44 +139,31 @@ def process_request(self, request):
148139
translation.activate(lang)
149140
request.LANGUAGE_CODE = translation.get_language()
150141

151-
152142
class SecurityHeadersMiddleware:
153143
"""
154144
Middleware to add security headers that help mitigate vulnerabilities
155145
in third-party JavaScript libraries and prevent common attacks.
156146
"""
157-
158147
def __init__(self, get_response):
159148
self.get_response = get_response
160149

161150
def __call__(self, request):
162151
response = self.get_response(request)
163-
164152
# Content Security Policy to prevent XSS and code injection
165153
response['Content-Security-Policy'] = (
166154
"default-src 'self'; "
167-
"script-src 'self' 'unsafe-inline' 'unsafe-eval'; " # unsafe-eval needed for some dev tools
155+
"script-src 'self' 'unsafe-inline' 'unsafe-eval'; "
168156
"style-src 'self' 'unsafe-inline'; "
169157
"img-src 'self' data: https:; "
170158
"font-src 'self' https:; "
171159
"connect-src 'self'; "
172160
"frame-ancestors 'none'; "
173161
"base-uri 'self';"
174162
)
175-
176-
# Prevent clickjacking
177163
response['X-Frame-Options'] = 'DENY'
178-
179-
# Prevent MIME type sniffing
180164
response['X-Content-Type-Options'] = 'nosniff'
181-
182-
# Enable XSS protection
183165
response['X-XSS-Protection'] = '1; mode=block'
184-
185-
# Prevent referrer leakage
186166
response['Referrer-Policy'] = 'strict-origin-when-cross-origin'
187-
188-
# Permissions policy
189167
response['Permissions-Policy'] = (
190168
'geolocation=(), '
191169
'microphone=(), '
@@ -196,5 +174,49 @@ def __call__(self, request):
196174
'accelerometer=(), '
197175
'gyroscope=()'
198176
)
199-
200-
return response
177+
return response
178+
179+
class HoneypotMiddleware:
180+
"""
181+
Middleware to detect and log requests to honeypot (fake) paths.
182+
Normal users will never visit these paths.
183+
If triggered, log the attempt and return a 404 page.
184+
"""
185+
HONEYPOT_PATHS = [
186+
"/admin-secret",
187+
"/Main-admin",
188+
"/superuser",
189+
"/dashboard-old",
190+
"/backup.sql",
191+
"/db.dump",
192+
"/config.php",
193+
"/env.bak",
194+
"/administration-login",
195+
"/auth-test",
196+
"/secure-login",
197+
"/test-page",
198+
"/debug/",
199+
"/old-site/"
200+
]
201+
202+
def __init__(self, get_response):
203+
self.get_response = get_response
204+
205+
def __call__(self, request):
206+
path = request.path
207+
if path in self.HONEYPOT_PATHS:
208+
ip = self.get_client_ip(request)
209+
ua = request.META.get("HTTP_USER_AGENT", "unknown")
210+
Honeypot_logger.warning(
211+
f"HONEYPOT TRIGGERED: Path={path}, IP={ip}, User-Agent={ua}"
212+
)
213+
return render(request, "404.html", status=404)
214+
return self.get_response(request)
215+
216+
def get_client_ip(self, request):
217+
x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR")
218+
if x_forwarded_for:
219+
ip = x_forwarded_for.split(",")[0]
220+
else:
221+
ip = request.META.get("REMOTE_ADDR", "")
222+
return ip

core/settings.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@
156156
# 'core.middleware.AutoLogoutMiddleware', # TEMPORARILY DISABLED - causing OAuth redirect issues
157157

158158
"django_user_agents.middleware.UserAgentMiddleware",
159+
"core.middleware.HoneypotMiddleware",
159160
# "core.middleware.LogRequestMiddleware", # TEMPORARILY DISABLED - causing OAuth redirect issues
160161
# "home.views.force_oauth_redirect_middleware", # DISABLED - causing redirect loops
161162

@@ -529,6 +530,11 @@
529530
'level': 'INFO',
530531
'propagate': False,
531532
},
533+
"honeypot_logger": {
534+
"handlers": ["console"],
535+
"level": "WARNING",
536+
"propagate": False,
537+
},
532538
},
533539
}
534540

core/urls.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
1. Import the include() function: from django.urls import include, path
1414
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
1515
"""
16+
from django.conf import settings
17+
from django.conf.urls.static import static
1618
from django.contrib import admin
1719
from django.conf.urls.i18n import i18n_patterns
1820
from django.urls import include, path
@@ -114,11 +116,16 @@
114116
path('', include('home.urls')),
115117
path("api/tip/today/", views.tip_today, name="tip_today"),
116118

117-
118119
]
119120

120121

121122

122123
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + static('/static/assets/', document_root=settings.BASE_DIR / 'custom_static/assets')
123124

125+
]
126+
127+
# Static & media files (served by Django in dev)
128+
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
129+
urlpatterns += static('/static/assets/', document_root=settings.BASE_DIR / 'custom_static/assets')
130+
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
124131

0 commit comments

Comments
 (0)