GuardianUnivalle-Benito-Yucra 0.1.69__py3-none-any.whl → 0.1.71__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of GuardianUnivalle-Benito-Yucra might be problematic. Click here for more details.

@@ -1,10 +1,12 @@
1
- # CSRF defense (versión reforzada)
1
+ # csrf_defense.py
2
+ # GuardianUnivalle_Benito_Yucra/detectores/csrf_defense.py
3
+
2
4
  from __future__ import annotations
3
5
  import secrets
4
6
  import logging
5
7
  import re
6
8
  import json
7
- from typing import List
9
+ from typing import List, Dict, Any
8
10
  from urllib.parse import urlparse
9
11
  from django.conf import settings
10
12
  from django.utils.deprecation import MiddlewareMixin
@@ -21,21 +23,42 @@ CSRF_HEADER_NAMES = ("HTTP_X_CSRFTOKEN", "HTTP_X_CSRF_TOKEN")
21
23
  CSRF_COOKIE_NAME = getattr(settings, "CSRF_COOKIE_NAME", "csrftoken")
22
24
  POST_FIELD_NAME = "csrfmiddlewaretoken"
23
25
 
24
- # Patrón de Content-Type sospechoso
26
+ # Patrón de Content-Type sospechoso - EXPANDIDO
25
27
  SUSPICIOUS_CT_PATTERNS = [
26
28
  re.compile(r"text/plain", re.I),
27
29
  re.compile(r"application/x-www-form-urlencoded", re.I),
28
30
  re.compile(r"multipart/form-data", re.I),
31
+ re.compile(r"application/json", re.I),
32
+ re.compile(r"text/html", re.I), # Agregado para HTML CSRF
29
33
  ]
30
34
 
31
- # Parámetros sensibles típicos de CSRF
35
+ # Parámetros sensibles típicos de CSRF - EXPANDIDO
32
36
  SENSITIVE_PARAMS = [
33
- "password", "csrfmiddlewaretoken", "token", "amount", "transfer", "delete", "update"
37
+ "password", "csrfmiddlewaretoken", "token", "amount", "transfer", "delete", "update", "action", "email", "username"
34
38
  ]
35
39
 
40
+ # Campos sensibles: ANALIZAMOS COMPLETAMENTE SIN DESCUENTO PARA ROBUSTEZ MÁXIMA
41
+ SENSITIVE_FIELDS = ["password", "csrfmiddlewaretoken", "token", "auth", "email", "username"]
42
+
36
43
  CSRF_DEFENSE_MIN_SIGNALS = getattr(settings, "CSRF_DEFENSE_MIN_SIGNALS", 1)
37
44
  CSRF_DEFENSE_EXCLUDED_API_PREFIXES = getattr(settings, "CSRF_DEFENSE_EXCLUDED_API_PREFIXES", ["/api/"])
38
45
 
46
+ # PATRONES EXPANDIDOS PARA ANÁLISIS DE PAYLOAD EN TODOS LOS CAMPOS (SIN DESCUENTO)
47
+ CSRF_PAYLOAD_PATTERNS = [
48
+ (re.compile(r"<script[^>]*>.*?</script>", re.I | re.S), "Script tag en payload", 0.9),
49
+ (re.compile(r"javascript\s*:", re.I), "URI javascript: en payload", 0.8),
50
+ (re.compile(r"http[s]?://[^\s]+", re.I), "URL externa en payload", 0.7),
51
+ (re.compile(r"eval\s*\(", re.I), "eval() en payload", 1.0),
52
+ (re.compile(r"document\.cookie", re.I), "Acceso a cookie en payload", 0.9),
53
+ (re.compile(r"innerHTML\s*=", re.I), "Manipulación DOM innerHTML", 0.8),
54
+ (re.compile(r"XMLHttpRequest", re.I), "XHR en payload", 0.7),
55
+ (re.compile(r"fetch\s*\(", re.I), "fetch() en payload", 0.7),
56
+ (re.compile(r"&#x[0-9a-fA-F]+;", re.I), "Entidades HTML en payload", 0.6),
57
+ (re.compile(r"%3Cscript", re.I), "Script URL-encoded en payload", 0.8),
58
+ (re.compile(r"on\w+\s*=", re.I), "Eventos on* en payload", 0.7),
59
+ (re.compile(r"alert\s*\(", re.I), "alert() en payload (prueba)", 0.5),
60
+ ]
61
+
39
62
  def get_client_ip(request):
40
63
  x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR")
41
64
  if x_forwarded_for:
@@ -62,15 +85,15 @@ def origin_matches_host(request) -> bool:
62
85
  host = host_header.split(":")[0]
63
86
  origin = request.META.get("HTTP_ORIGIN", "")
64
87
  referer = request.META.get("HTTP_REFERER", "")
65
- origin_host = host_from_header(origin)
66
- referer_host = host_from_header(referer)
67
88
  # Bloquear obvious javascript: referers
68
89
  if any(re.search(r"(javascript:|<script|data:text/html)", h or "", re.I) for h in [origin, referer]):
69
90
  return False
70
- if origin_host and origin_host == host:
71
- return True
72
- if referer_host and referer_host == host:
73
- return True
91
+ if origin_host := host_from_header(origin):
92
+ if origin_host == host:
93
+ return True
94
+ if referer_host := host_from_header(referer):
95
+ if referer_host == host:
96
+ return True
74
97
  if not origin and not referer:
75
98
  return True
76
99
  return False
@@ -118,6 +141,34 @@ def extract_parameters(request) -> List[str]:
118
141
  pass
119
142
  return params
120
143
 
144
+ # FUNCIÓN ROBUSTA: Analizar payload en TODOS los campos (incluyendo sensibles sin descuento)
145
+ def analyze_payload(value: str) -> float:
146
+ score = 0.0
147
+ for patt, desc, weight in CSRF_PAYLOAD_PATTERNS:
148
+ if patt.search(value):
149
+ score += weight # Score full, sin descuento
150
+ return round(score, 3)
151
+
152
+ # NUEVA FUNCIÓN: Extraer y analizar query string
153
+ def analyze_query_string(request) -> float:
154
+ qs = request.META.get("QUERY_STRING", "")
155
+ if qs:
156
+ return analyze_payload(qs)
157
+ return 0.0
158
+
159
+ # NUEVA FUNCIÓN: Analizar headers adicionales
160
+ def analyze_headers(request) -> List[str]:
161
+ issues = []
162
+ ua = request.META.get("HTTP_USER_AGENT", "")
163
+ if re.search(r"(script|<|eval|bot|crawler)", ua, re.I):
164
+ issues.append("User-Agent sospechoso (posible automatización/bot)")
165
+
166
+ accept_lang = request.META.get("HTTP_ACCEPT_LANGUAGE", "")
167
+ if not accept_lang or len(accept_lang) < 2:
168
+ issues.append("Accept-Language ausente o muy corto (posible bot)")
169
+
170
+ return issues
171
+
121
172
  class CSRFDefenseMiddleware(MiddlewareMixin):
122
173
  def process_request(self, request):
123
174
  # Excluir APIs JSON si se configuró así
@@ -136,7 +187,7 @@ class CSRFDefenseMiddleware(MiddlewareMixin):
136
187
  return None
137
188
 
138
189
  method = (request.method or "").upper()
139
- if method not in STATE_CHANGING_METHODS:
190
+ if method not in STATE_CHANGING_METHODS: # CORREGIDO: Agregado "in"
140
191
  return None
141
192
 
142
193
  descripcion: List[str] = []
@@ -174,33 +225,73 @@ class CSRFDefenseMiddleware(MiddlewareMixin):
174
225
  if origin and host_from_header(origin) != (request.META.get("HTTP_HOST") or "").split(":")[0]:
175
226
  descripcion.append("JSON POST desde origen externo (posible CSRF)")
176
227
 
228
+ # 7) Análisis ROBUSTO de payload en TODOS los campos (sin descuento)
229
+ payload_score = 0.0
230
+ payload_summary: List[Dict[str, Any]] = []
231
+ try:
232
+ # Analizar POST
233
+ if hasattr(request, "POST"):
234
+ for key, value in request.POST.items():
235
+ if isinstance(value, str):
236
+ score = analyze_payload(value)
237
+ payload_score += score
238
+ if score > 0:
239
+ payload_summary.append({"field": key, "snippet": value[:300], "score": score})
240
+ # Analizar JSON
241
+ if "application/json" in content_type:
242
+ data = json.loads(request.body.decode("utf-8") or "{}")
243
+ for key, value in data.items():
244
+ if isinstance(value, str):
245
+ score = analyze_payload(value)
246
+ payload_score += score
247
+ if score > 0:
248
+ payload_summary.append({"field": key, "snippet": value[:300], "score": score})
249
+ except Exception as e:
250
+ logger.debug(f"Error analizando payload: {e}")
251
+
252
+ if payload_score > 0:
253
+ descripcion.append(f"Payload sospechoso detectado (score total: {payload_score})")
254
+
255
+ # 8) Análisis de query string
256
+ qs_score = analyze_query_string(request)
257
+ if qs_score > 0:
258
+ descripcion.append(f"Query string sospechosa (score: {qs_score})")
259
+ payload_score += qs_score
260
+
261
+ # 9) Análisis de headers adicionales
262
+ header_issues = analyze_headers(request)
263
+ descripcion.extend(header_issues)
264
+
177
265
  # Señales >= umbral => marcar
178
- if descripcion and len(descripcion) >= CSRF_DEFENSE_MIN_SIGNALS:
266
+ total_signals = len(descripcion)
267
+ if descripcion and total_signals >= CSRF_DEFENSE_MIN_SIGNALS:
179
268
  w_csrf = getattr(settings, "CSRF_DEFENSE_WEIGHT", 0.2)
180
- s_csrf = w_csrf * len(descripcion)
269
+ s_csrf = w_csrf * total_signals + payload_score # Score full sin descuento
181
270
  request.csrf_attack_info = {
182
271
  "ip": client_ip,
183
272
  "tipos": ["CSRF"],
184
273
  "descripcion": descripcion,
185
- "payload": payload,
274
+ "payload": json.dumps(payload_summary, ensure_ascii=False)[:1000],
186
275
  "score": s_csrf,
187
276
  }
188
277
  logger.warning(
189
- "CSRF detectado desde IP %s: %s ; path=%s ; Content-Type=%s ; score=%.2f",
278
+ "CSRF detectado desde IP %s: %s ; path=%s ; Content-Type=%s ; score=%.2f (Ultra-Robust: nada ignorado)",
190
279
  client_ip, descripcion, request.path, content_type, s_csrf
191
280
  )
192
281
  else:
193
282
  if descripcion:
194
- logger.debug(f"[CSRFDefense] low-signals ({len(descripcion)}) not marking: {descripcion}")
283
+ logger.debug(f"[CSRFDefense] low-signals ({total_signals}) not marking: {descripcion}")
195
284
 
196
285
  return None
197
286
 
198
287
  """
199
- CSRF Defense Middleware - Reforzado
200
- ===================================
288
+ CSRF Defense Middleware - Ultra-Robusto (Nada Ignorado)
289
+ =======================================================
201
290
  - Detecta múltiples categorías de CSRF: clásico, login, logout, password change, file/action, JSON API.
202
- - Escanea payloads POST, GET y JSON.
291
+ - Escanea payloads POST, GET, JSON, query string y headers, incluyendo TODOS los campos (sensibles y no) con score full (sin descuento).
203
292
  - Detecta parámetros sensibles enviados en GET o JSON desde origen externo.
293
+ - Análisis adicional de User-Agent, Accept-Language, y payloads con patrones expandidos.
204
294
  - Scoring configurable y logging detallado.
205
295
  - Fácil integración con auditoría XSS/SQLi.
296
+ - Máxima robustez: no ignora nada para detección óptima.
206
297
  """
@@ -8,7 +8,7 @@ from django.utils.deprecation import MiddlewareMixin
8
8
  from django.conf import settings
9
9
  import urllib.parse
10
10
  import html
11
- from typing import List, Tuple, Dict
11
+ from typing import List, Tuple, Dict, Any
12
12
 
13
13
  # ----------------------------
14
14
  # Configuración del logger
@@ -108,9 +108,23 @@ SQL_PATTERNS: List[Tuple[re.Pattern, str, float]] = [
108
108
  # ------------------ Catch‑all aggressive patterns (usar con cuidado) ------------------
109
109
  (re.compile(r"(['\"]).*?;\s*(drop|truncate|delete|update|insert)\b", re.I | re.S), "Cadena con terminador y DDL/DML (potencial ataque)", 0.9),
110
110
  (re.compile(r"\b(or)\b\s+1\s*=\s*1\b", re.I), "OR 1=1 tautology", 0.85),
111
+
112
+ # ---------- NUEVOS PATRONES PARA ROBUSTEZ ----------
113
+ (re.compile(r"\b(select\s+.*\s+from\s+.*\s+where\s+.*\s+in\s*\()", re.I | re.S), "Subquery anidada (IN subquery)", 0.75),
114
+ (re.compile(r"\bcase\s+when\s+.*\s+then\s+.*\s+else\b", re.I), "CASE WHEN (blind boolean)", 0.78),
115
+ (re.compile(r"/\*\!.+\*\//", re.I), "Comentarios condicionales MySQL (/*!...*/)", 0.7),
116
+ (re.compile(r"\bif\s*\(\s*.*\s*,\s*.*\s*,\s*.*\s*\)", re.I), "IF() MySQL (conditional)", 0.72),
117
+ (re.compile(r"\bgroup_concat\s*\(", re.I), "GROUP_CONCAT() (exfiltración en error)", 0.8),
111
118
  ]
112
119
 
113
- IGNORED_FIELDS = ["password", "csrfmiddlewaretoken", "token", "auth"]
120
+ # Campos sensibles: ANALIZAMOS COMPLETAMENTE SIN DESCUENTO PARA ROBUSTEZ MÁXIMA
121
+ SENSITIVE_FIELDS = ["password", "csrfmiddlewaretoken", "token", "auth", "email", "username"]
122
+
123
+ DEFAULT_THRESHOLDS = {
124
+ "HIGH": 1.8,
125
+ "MEDIUM": 1.0,
126
+ "LOW": 0.5,
127
+ }
114
128
 
115
129
  # ----------------------------
116
130
  # Obtener IP real del cliente
@@ -124,26 +138,34 @@ def get_client_ip(request):
124
138
  return request.META.get("REMOTE_ADDR", "")
125
139
 
126
140
  # ----------------------------
127
- # Extraer payload de la solicitud
141
+ # Extraer payload de la solicitud - MEJORADO PARA ANÁLISIS POR CAMPO
128
142
  # ----------------------------
129
- def extract_payload(request):
130
- parts = []
143
+ def extract_payload_as_map(request) -> Dict[str, Any]:
131
144
  try:
132
- if "application/json" in request.META.get("CONTENT_TYPE", ""):
133
- data = json.loads(request.body.decode("utf-8") or "{}")
134
- parts.append(json.dumps(data))
145
+ ct = request.META.get("CONTENT_TYPE", "")
146
+ if "application/json" in ct:
147
+ raw = request.body.decode("utf-8") or "{}"
148
+ try:
149
+ data = json.loads(raw)
150
+ if isinstance(data, dict):
151
+ return data
152
+ else:
153
+ return {"raw": raw}
154
+ except Exception:
155
+ return {"raw": raw}
135
156
  else:
136
- body = request.body.decode("utf-8", errors="ignore")
137
- if body:
138
- parts.append(body)
157
+ try:
158
+ post = request.POST.dict()
159
+ if post:
160
+ return post
161
+ except Exception:
162
+ pass
163
+ raw = request.body.decode("utf-8", errors="ignore")
164
+ if raw:
165
+ return {"raw": raw}
139
166
  except Exception:
140
167
  pass
141
-
142
- qs = request.META.get("QUERY_STRING", "")
143
- if qs:
144
- parts.append(qs)
145
-
146
- return " ".join(parts)
168
+ return {}
147
169
 
148
170
  # ----------------------------
149
171
  # Normalización / preprocesamiento
@@ -159,13 +181,12 @@ def normalize_input(s: str) -> str:
159
181
  s_dec = html.unescape(s_dec)
160
182
  except Exception:
161
183
  pass
162
- # Reemplazo seguro de secuencias \xNN
163
184
  s_dec = re.sub(r"\\x([0-9a-fA-F]{2})", r"\\x\g<1>", s_dec)
164
185
  s_dec = re.sub(r"\s+", " ", s_dec)
165
186
  return s_dec.strip()
166
187
 
167
188
  # ----------------------------
168
- # Detector SQLi
189
+ # Detector SQLi - ROBUSTO SIN DESCUENTO
169
190
  # ----------------------------
170
191
  def detect_sql_injection(text: str) -> Dict:
171
192
  norm = normalize_input(text or "")
@@ -174,7 +195,7 @@ def detect_sql_injection(text: str) -> Dict:
174
195
  descriptions = []
175
196
  for pattern, desc, weight in SQL_PATTERNS:
176
197
  if pattern.search(norm):
177
- score += weight
198
+ score += weight # Score full, sin descuento
178
199
  matches.append((desc, pattern.pattern, weight))
179
200
  descriptions.append(desc)
180
201
 
@@ -185,14 +206,8 @@ def detect_sql_injection(text: str) -> Dict:
185
206
  "sample": norm[:1200],
186
207
  }
187
208
 
188
- DEFAULT_THRESHOLDS = {
189
- "HIGH": 1.8,
190
- "MEDIUM": 1.0,
191
- "LOW": 0.5,
192
- }
193
-
194
209
  # ----------------------------
195
- # Middleware SQLi
210
+ # Middleware SQLi - ULTRA-ROBUSTO
196
211
  # ----------------------------
197
212
  class SQLIDefenseMiddleware(MiddlewareMixin):
198
213
  def process_request(self, request):
@@ -202,33 +217,65 @@ class SQLIDefenseMiddleware(MiddlewareMixin):
202
217
 
203
218
  if client_ip in trusted_ips:
204
219
  return None
205
-
206
220
  referer = request.META.get("HTTP_REFERER", "")
207
221
  host = request.get_host()
208
222
  if any(url in referer for url in trusted_urls) or any(url in host for url in trusted_urls):
209
223
  return None
210
-
211
- payload = extract_payload(request)
212
- result = detect_sql_injection(payload)
213
- score = result["score"]
214
- descripciones = result["descriptions"]
215
-
216
- if score == 0:
224
+ # Extraer datos como mapa para análisis por campo
225
+ data = extract_payload_as_map(request)
226
+ qs = request.META.get("QUERY_STRING", "")
227
+ if qs:
228
+ data["_query_string"] = qs
229
+ if not data:
230
+ return None
231
+ total_score = 0.0
232
+ all_descriptions = []
233
+ all_matches = []
234
+ payload_summary = []
235
+ # Analizar campo por campo - AHORA SIN DESCUENTO PARA ROBUSTEZ
236
+ if isinstance(data, dict):
237
+ for key, value in data.items():
238
+ if isinstance(value, (dict, list)):
239
+ try:
240
+ vtext = json.dumps(value, ensure_ascii=False)
241
+ except Exception:
242
+ vtext = str(value)
243
+ else:
244
+ vtext = str(value or "")
245
+
246
+ result = detect_sql_injection(vtext)
247
+ total_score += result["score"]
248
+ all_descriptions.extend(result["descriptions"])
249
+ all_matches.extend(result["matches"])
250
+
251
+ if result["score"] > 0:
252
+ is_sensitive = isinstance(key, str) and key.lower() in SENSITIVE_FIELDS
253
+ payload_summary.append({"field": key, "snippet": vtext[:300], "sensitive": is_sensitive})
254
+ else:
255
+ raw = str(data)
256
+ result = detect_sql_injection(raw)
257
+ total_score += result["score"]
258
+ all_descriptions.extend(result["descriptions"])
259
+ all_matches.extend(result["matches"])
260
+ if result["score"] > 0:
261
+ payload_summary.append({"field": "raw", "snippet": raw[:500], "sensitive": False})
262
+
263
+ if total_score == 0:
217
264
  return None
218
265
 
219
266
  # Registrar ataque
220
267
  logger.warning(
221
268
  f"[SQLiDetect] IP={client_ip} Host={host} Referer={referer} "
222
- f"Score={score:.2f} Desc={descripciones} Payload={payload[:500]}"
269
+ f"Score={total_score:.2f} Desc={all_descriptions} Payload={json.dumps(payload_summary, ensure_ascii=False)[:500]}"
223
270
  )
224
271
 
225
272
  # Guardar info en request
226
273
  request.sql_attack_info = {
227
274
  "ip": client_ip,
228
275
  "tipos": ["SQLi"],
229
- "descripcion": descripciones,
230
- "payload": payload[:1000],
231
- "score": round(score, 2),
276
+ "descripcion": all_descriptions,
277
+ "payload": json.dumps(payload_summary, ensure_ascii=False)[:1000],
278
+ "score": round(total_score, 2),
232
279
  "url": request.build_absolute_uri(),
233
280
  }
234
281
 
@@ -29,11 +29,10 @@ except Exception:
29
29
  _BLEACH_AVAILABLE = False
30
30
 
31
31
  # -------------------------------------------------
32
- # Patrones XSS con peso (descripcion, peso)
32
+ # Patrones XSS con peso (descripcion, peso) - EXPANDIDOS PARA ROBUSTEZ
33
33
  # - pesos mayores = más severo (por ejemplo <script> o javascript:)
34
- # - esto permite un scoring acumulativo y menos falsos positivos
34
+ # - Agregados patrones para DOM-based, polyglots y evasiones avanzadas
35
35
  # -------------------------------------------------
36
-
37
36
  XSS_PATTERNS: List[Tuple[re.Pattern, str, float]] = [
38
37
  # ---------- Máxima severidad / ejecución directa ----------
39
38
  (re.compile(r"<\s*script\b", re.I), "Etiqueta <script> (directa)", 0.95),
@@ -94,20 +93,30 @@ XSS_PATTERNS: List[Tuple[re.Pattern, str, float]] = [
94
93
  # ---------- Heurísticos de baja severidad (informativo) ----------
95
94
  (re.compile(r"<\s*form\b", re.I), "Form (posible vector de ataque relacionado)", 0.25),
96
95
  (re.compile(r"(onmouseover|onfocus|onmouseenter|onmouseleave)\b", re.I), "Eventos UI (mouseover/focus)", 0.45),
96
+
97
+ # ---------- NUEVOS PATRONES PARA ROBUSTEZ ----------
98
+ (re.compile(r"\binnerHTML\s*=\s*.*[<>\"']", re.I), "Asignación a innerHTML con tags", 0.85), # DOM-based
99
+ (re.compile(r"\bdocument\.getElementById\s*\(\s*.*\)\.innerHTML", re.I), "Manipulación DOM innerHTML", 0.80),
100
+ (re.compile(r"<script[^>]*src\s*=\s*['\"][^'\"]*['\"][^>]*>", re.I), "Script externo (posible carga remota)", 0.75),
101
+ (re.compile(r"\bXMLHttpRequest\s*\(\s*\)\.open\s*\(\s*['\"](GET|POST)['\"]", re.I), "XHR manipulado (posible exfiltración)", 0.70),
102
+ (re.compile(r"<\s*link\b[^>]*\bhref\s*=\s*['\"][^'\"]*javascript\s*:", re.I), "Link con href javascript:", 0.78),
103
+ (re.compile(r"\bwindow\.open\s*\(\s*['\"]*javascript\s*:", re.I), "window.open con javascript:", 0.82),
97
104
  ]
98
105
 
99
106
  # -------------------------------------------------
100
- # Campos que NO queremos analizar (contraseñas, tokens, etc.)
107
+ # Campos sensibles: NO LOS IGNORAMOS COMPLETAMENTE, PERO LES DAMOS DESCUENTO EN SCORE
108
+ # Para robustez, los analizamos pero reducimos el peso para evitar falsos positivos.
101
109
  # -------------------------------------------------
102
- IGNORED_FIELDS = getattr(settings, "XSS_DEFENSE_IGNORED_FIELDS", ["password", "csrfmiddlewaretoken", "token", "auth"])
110
+ SENSITIVE_FIELDS = ["password", "csrfmiddlewaretoken", "token", "auth"]
111
+ SENSITIVE_DISCOUNT = 0.5 # Multiplicador para campos sensibles
103
112
 
104
113
  # Umbral por defecto para considerar "alto riesgo" (Auditoria puede bloquear según su lógica)
105
114
  XSS_DEFENSE_THRESHOLD = getattr(settings, "XSS_DEFENSE_THRESHOLD", 0.6)
106
115
 
107
-
108
116
  # -------------------------------------------------
109
117
  # Util: validación / extracción de IP (robusta)
110
118
  # -------------------------------------------------
119
+
111
120
  def _is_valid_ip(ip: str) -> bool:
112
121
  """Verifica que la cadena sea una IP válida (v4 o v6)."""
113
122
  try:
@@ -117,7 +126,6 @@ def _is_valid_ip(ip: str) -> bool:
117
126
  except Exception:
118
127
  return False
119
128
 
120
-
121
129
  def get_client_ip(request) -> str:
122
130
  """
123
131
  Obtiene la mejor estimación de la IP del cliente:
@@ -143,7 +151,6 @@ def get_client_ip(request) -> str:
143
151
  remote = request.META.get("REMOTE_ADDR")
144
152
  return remote or ""
145
153
 
146
-
147
154
  # -------------------------------------------------
148
155
  # Extraer payload pero evitando cabeceras (para reducir falsos positivos)
149
156
  # - Devuelve dict si es JSON, o dict con 'raw' para otros cuerpos
@@ -185,15 +192,14 @@ def extract_body_as_map(request) -> Dict[str, Any]:
185
192
  pass
186
193
  return {}
187
194
 
188
-
189
195
  # -------------------------------------------------
190
196
  # Analizar un solo valor (string) en busca de XSS usando patrones
191
197
  # Devuelve (score, descripciones, matches_patterns)
192
198
  # -------------------------------------------------
193
- def detect_xss_in_value(value: str) -> Tuple[float, List[str], List[str]]:
199
+ def detect_xss_in_value(value: str, is_sensitive: bool = False) -> Tuple[float, List[str], List[str]]:
194
200
  """
195
201
  Analiza una cadena y devuelve:
196
- - score acumulado (sum pesos)
202
+ - score acumulado (sum pesos, con descuento si es campo sensible)
197
203
  - lista de descripciones activadas
198
204
  - lista de patrones (regex.pattern) que matchearon
199
205
  """
@@ -204,28 +210,26 @@ def detect_xss_in_value(value: str) -> Tuple[float, List[str], List[str]]:
204
210
  descripcion = []
205
211
  matches = []
206
212
 
207
- # Si bleach está disponible, podemos "limpiar" y comparar; pero aquí solo detectamos
213
+ # Si bleach está disponible, sanitizar y comparar para detección adicional
214
+ if _BLEACH_AVAILABLE:
215
+ cleaned = bleach.clean(value, strip=True)
216
+ if cleaned != value:
217
+ score_total += 0.5 # Penalización por cambios en sanitización
218
+ descripcion.append("Contenido alterado por sanitización (bleach)")
219
+
208
220
  for patt, msg, weight in XSS_PATTERNS:
209
221
  if patt.search(value):
210
- score_total += weight
222
+ adjusted_weight = weight * SENSITIVE_DISCOUNT if is_sensitive else weight
223
+ score_total += adjusted_weight
211
224
  descripcion.append(msg)
212
225
  matches.append(patt.pattern)
213
226
 
214
227
  return round(score_total, 3), descripcion, matches
215
228
 
216
-
217
229
  # -------------------------------------------------
218
- # Middleware principal XSS
230
+ # Middleware principal XSS - MEJORADO PARA ROBUSTEZ
219
231
  # -------------------------------------------------
220
232
  class XSSDefenseMiddleware(MiddlewareMixin):
221
- """
222
- Middleware para detección XSS.
223
- - Analiza el body (campo por campo) y querystring si aplica.
224
- - Ignora campos sensibles (password, token).
225
- - No incluye User-Agent/Referer en el texto analizado (evita falsos positivos).
226
- - Añade request.xss_attack_info con: ip, tipos, descripcion, payload, score, url.
227
- """
228
-
229
233
  def process_request(self, request):
230
234
  # 1) IP y exclusiones
231
235
  client_ip = get_client_ip(request)
@@ -251,15 +255,12 @@ class XSSDefenseMiddleware(MiddlewareMixin):
251
255
  total_score = 0.0
252
256
  all_descriptions: List[str] = []
253
257
  all_matches: List[str] = []
254
- # payload_for_storage: guardamos un resumen/truncado para auditoría
255
258
  payload_summary = []
256
259
 
257
- # 3) Analizar campo por campo (si es dict) o el raw
260
+ # 3) Analizar campo por campo (si es dict) o el raw - AHORA ANALIZA TODO, CON DESCUENTO PARA SENSIBLES
258
261
  if isinstance(data, dict):
259
262
  for key, value in data.items():
260
- # evitar analizar campos sensibles
261
- if isinstance(key, str) and key.lower() in [f.lower() for f in IGNORED_FIELDS]:
262
- continue
263
+ is_sensitive = isinstance(key, str) and key.lower() in SENSITIVE_FIELDS
263
264
 
264
265
  # convertir a string si es otro tipo (list, int...)
265
266
  if isinstance(value, (dict, list)):
@@ -270,20 +271,13 @@ class XSSDefenseMiddleware(MiddlewareMixin):
270
271
  else:
271
272
  vtext = str(value or "")
272
273
 
273
- # salto rápido: si el valor parece ser un email o password muy corto y sin signos,
274
- # las probabilidades de XSS son muy bajas; continúa (reduce falsos positivos).
275
- if key.lower() in ("email", "username") and len(vtext) < 256:
276
- # aún así pasar por patrones (no lo ignoramos completamente), pero podemos bajar sensibilidad
277
- pass
278
-
279
- s, descs, matches = detect_xss_in_value(vtext)
274
+ s, descs, matches = detect_xss_in_value(vtext, is_sensitive)
280
275
  total_score += s
281
276
  all_descriptions.extend(descs)
282
277
  all_matches.extend(matches)
283
278
 
284
279
  if s > 0:
285
- # almacenar fragmento del campo para auditoría (truncado)
286
- payload_summary.append({ "field": key, "snippet": vtext[:300] })
280
+ payload_summary.append({"field": key, "snippet": vtext[:300], "sensitive": is_sensitive})
287
281
 
288
282
  else:
289
283
  # si no es dict, analizar el raw como texto
@@ -293,7 +287,7 @@ class XSSDefenseMiddleware(MiddlewareMixin):
293
287
  all_descriptions.extend(descs)
294
288
  all_matches.extend(matches)
295
289
  if s > 0:
296
- payload_summary.append({"field":"raw","snippet": raw[:500]})
290
+ payload_summary.append({"field": "raw", "snippet": raw[:500], "sensitive": False})
297
291
 
298
292
  # 4) si no detectó nada, continuar
299
293
  if total_score == 0:
@@ -305,7 +299,7 @@ class XSSDefenseMiddleware(MiddlewareMixin):
305
299
  payload_for_request = json.dumps(payload_summary, ensure_ascii=False)[:2000]
306
300
 
307
301
  logger.warning(
308
- "XSS detectado desde IP %s URL=%s Score=%.3f Desc=%s",
302
+ "XSS detectado desde IP %s URL=%s Score=%.3f Desc=%s (Robust: incluye sensibles con descuento)",
309
303
  client_ip,
310
304
  url,
311
305
  score_rounded,
@@ -320,8 +314,7 @@ class XSSDefenseMiddleware(MiddlewareMixin):
320
314
  "payload": payload_for_request,
321
315
  "score": score_rounded,
322
316
  "url": url,
323
- }
324
-
317
+ }
325
318
  # 7) NO bloquear aquí — lo hace AuditoriaMiddleware según su política
326
319
  return None
327
320
 
@@ -0,0 +1,265 @@
1
+ Metadata-Version: 2.4
2
+ Name: GuardianUnivalle-Benito-Yucra
3
+ Version: 0.1.71
4
+ Summary: Middleware y detectores de seguridad (SQLi, XSS, CSRF, DoS) para Django/Flask
5
+ Author-email: Andres Benito Calle Yucra <benitoandrescalle035@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://pypi.org/project/guardianunivalle-benito-yucra/
8
+ Project-URL: Bug_Tracker, https://github.com/Andyyupy/guardianunivalle-benito-yucra/issues
9
+ Keywords: security,django,flask,sqli,xss,csrf,middleware
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Topic :: Security
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Framework :: Django
16
+ Classifier: Framework :: Flask
17
+ Requires-Python: >=3.8
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: redis>=4.0
21
+ Requires-Dist: django>=3.2
22
+ Dynamic: license-file
23
+
24
+ <!-- Información de la librería -->
25
+ <table align="center" style="width: 100%; text-align: center; border-collapse: collapse; background-color: #f4f4f9; border-radius: 15px; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); padding: 20px;">
26
+ <tr>
27
+ <td style="border: none; padding: 10px 20px;">
28
+ <img src="https://res.cloudinary.com/dsbgmboh1/image/upload/v1761866594/Andres_Benito_Calle_Yucra_nxyqee.png"
29
+ alt="Univalle Logo" width="300"
30
+ style="transition: transform 0.3s ease-in-out;"
31
+ onmouseover="this.style.transform='scale(1.1)'"
32
+ onmouseout="this.style.transform='scale(1)'">
33
+ </td>
34
+ <td style="border: none; padding: 10px 20px; text-align: center;">
35
+ <h1 style="font-size: 50px; margin: 0; color: #c62828; font-family: 'Arial', sans-serif; text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);">
36
+ Guardian Univalle Benito Yucra
37
+ </h1>
38
+ <p style="margin: 5px 0 0 0; font-size: 18px; color: #444; font-family: 'Segoe UI', sans-serif;">
39
+ Framework de detección y defensa de amenazas web para Django.
40
+ </p>
41
+ </td>
42
+ <td style="border: none; padding: 10px 20px;">
43
+ <img src="https://res.cloudinary.com/dsbgmboh1/image/upload/v1761864884/GuardianUnivalle_imeegq.png"
44
+ alt="Django Logo" width="300"
45
+ style="transition: transform 0.3s ease-in-out;"
46
+ onmouseover="this.style.transform='scale(1.1)'"
47
+ onmouseout="this.style.transform='scale(1)'">
48
+ </td>
49
+ </tr>
50
+ </table>
51
+
52
+
53
+ `Guardian Univalle` es un sistema de seguridad modular desarrollado para fortalecer aplicaciones Django frente a ataques web comunes como **XSS**, **CSRF**, **inyección SQL**, **ataques DoS** y **scraping automatizado**.
54
+ Cada módulo opera mediante **middlewares independientes** que analizan el tráfico HTTP en tiempo real, aplican heurísticas inteligentes y registran eventos sospechosos para auditoría y bloqueo adaptativo.
55
+
56
+ ---
57
+ ## Arquitectura general
58
+
59
+ Guardian Univalle está diseñado bajo una **arquitectura modular y extensible**, donde cada tipo de amenaza se gestiona mediante un middleware especializado.
60
+ Cada middleware:
61
+
62
+ - Se ejecuta en la fase inicial del request (`process_request`).
63
+ - Analiza cabeceras, cuerpo y metadatos de la petición.
64
+ - Evalúa indicadores de ataque según patrones heurísticos y reglas configurables.
65
+ - Calcula una puntuación de riesgo (score) para cada evento.
66
+ - Anexa la información al objeto `request` (por ejemplo, `request.xss_attack_info`) para que otros módulos (como el de auditoría) la procesen.
67
+
68
+ ---
69
+
70
+ ## Módulos de defensa incluidos
71
+
72
+ ### 1. CSRFDefenseMiddleware
73
+ **Defensa contra Cross-Site Request Forgery (CSRF)**
74
+
75
+ Este módulo detecta intentos de falsificación de peticiones mediante:
76
+
77
+ - Verificación de cabeceras **Origin** y **Referer** contra el host real.
78
+ - Validación de **tokens CSRF** en cookies, cabeceras o formularios.
79
+ - Análisis del **tipo de contenido** (`Content-Type`) y parámetros sensibles.
80
+ - Detección de peticiones JSON o formularios enviados desde dominios externos.
81
+ - Asignación de un **score de riesgo** proporcional al número y severidad de señales encontradas.
82
+
83
+ **Algoritmos utilizados:** heurísticas basadas en cabeceras HTTP, validación semántica de origen y detección de anomalías en métodos `POST`, `PUT`, `DELETE` y `PATCH`.
84
+
85
+ ---
86
+
87
+ ### 2. XSSDefenseMiddleware
88
+ **Defensa contra Cross-Site Scripting (XSS)**
89
+
90
+ Analiza los datos enviados en el cuerpo y querystring, detectando vectores de inyección HTML/JS mediante:
91
+
92
+ - Patrones de alto riesgo (`<script>`, `javascript:`, `onload=`, `eval()`).
93
+ - Ofuscaciones con entidades (`&#x3C;`, `%3Cscript`).
94
+ - Detección de atributos de eventos (`onmouseover`, `onfocus`, etc.).
95
+ - Análisis de URIs maliciosas (`data:text/html`, `vbscript:`).
96
+ - Scoring ponderado por severidad (de 0.3 a 0.95).
97
+
98
+ **Algoritmos utilizados:** expresiones regulares avanzadas con pesos heurísticos y uso opcional de la librería **Bleach** para sanitización comparativa.
99
+
100
+ **Salida:** agrega `request.xss_attack_info` con los detalles de detección, IP de origen, descripción, payload y score total.
101
+
102
+ ---
103
+
104
+ ### 3. SQLIDefenseMiddleware
105
+ **Defensa contra Inyección SQL (SQLi)**
106
+
107
+ Identifica intentos de inyección SQL en parámetros enviados a través de:
108
+
109
+ - Palabras clave peligrosas (`UNION`, `SELECT`, `DROP`, `INSERT`, `UPDATE`).
110
+ - Uso de comentarios (`--`, `#`, `/* ... */`).
111
+ - Concatenaciones o subconsultas sospechosas.
112
+ - Comportamientos anómalos en parámetros GET, POST o JSON.
113
+
114
+ **Algoritmos utilizados:** heurísticas sintácticas + patrones combinados con contextos.
115
+ Evalúa combinaciones de operadores y palabras reservadas para minimizar falsos positivos.
116
+
117
+ **Resultado:** registra el intento en `request.sql_injection_info` con score calculado y parámetros comprometidos.
118
+
119
+ ---
120
+
121
+ ### 4. DOSDefenseMiddleware
122
+ **Detección de ataques de Denegación de Servicio (DoS)**
123
+
124
+ Monitorea la frecuencia de peticiones por IP y calcula una métrica adaptativa:
125
+
126
+ - Detecta exceso de solicitudes en intervalos cortos.
127
+ - Analiza `User-Agent`, patrones repetitivos y tamaño de payloads.
128
+ - Aplica límites configurables (`MAX_REQUESTS_PER_WINDOW`).
129
+ - Marca IPs sospechosas para registro y bloqueo temporal.
130
+
131
+ **Algoritmos utilizados:** Sliding Window con conteo adaptativo, controlado por señales de frecuencia e intensidad.
132
+
133
+ ---
134
+
135
+ ### 5. ScrapingDefenseMiddleware (opcional)
136
+ **Detección de scraping y bots automatizados**
137
+
138
+ Evalúa características típicas de scraping:
139
+
140
+ - User-Agent anómalo o ausente.
141
+ - Patrón de navegación repetitivo o excesivamente rápido.
142
+ - Ausencia de cabeceras humanas como `Accept-Language` o `Referer`.
143
+ - Combinación con heurísticas de DoS para detectar scrapers agresivos.
144
+
145
+ **Algoritmos utilizados:** análisis estadístico de cabeceras + patrones de comportamiento a corto plazo.
146
+
147
+ ---
148
+
149
+ ## Integración y uso
150
+
151
+ ### Instalación
152
+
153
+ ```bash
154
+ pip install guardian-univalle
155
+ ```
156
+ ### Configuración en settings.py
157
+
158
+ ```bash
159
+ MIDDLEWARE = [
160
+ # Middlewares personalizados
161
+ "GuardianUnivalle_Benito_Yucra.detectores.detector_dos.DOSDefenseMiddleware",
162
+ "GuardianUnivalle_Benito_Yucra.detectores.detector_sql.SQLIDefenseMiddleware",
163
+ "GuardianUnivalle_Benito_Yucra.detectores.detector_xss.XSSDefenseMiddleware",
164
+ "GuardianUnivalle_Benito_Yucra.detectores.detector_csrf.CSRFDefenseMiddleware",
165
+ "users.middleware.AuditoriaMiddleware",
166
+ "users.auditoria_servidor.AuditoriaServidorMiddleware",
167
+ ]
168
+
169
+ ```
170
+
171
+ ```bash
172
+ ALLOWED_HOSTS = [
173
+ "192.168.0.3",
174
+ "127.0.0.1",
175
+ "localhost",
176
+ ]
177
+
178
+ ```
179
+ ### Parámetros de defensa avanzada
180
+
181
+ ```bash
182
+ # --- DoS Defense ---
183
+ DOS_LIMITE_PETICIONES = 120
184
+ DOS_VENTANA_SEGUNDOS = 60
185
+ DOS_PESO = 0.6
186
+ DOS_LIMITE_ENDPOINTS = 80
187
+ DOS_TIEMPO_BLOQUEO = 300
188
+ DOS_TRUSTED_IPS = ["127.0.0.1", "192.168.0.3"]
189
+
190
+ # Score total de bloqueo
191
+ DOS_PESO_BLACKLIST = 0.3
192
+ DOS_PESO_HEURISTICA = 0.1
193
+ DOS_UMBRAL_BLOQUEO = 0.8
194
+
195
+ # Configuración general
196
+ DOS_DEFENSE_MAX_REQUESTS = 100
197
+ DOS_DEFENSE_BLOCK_TIME = 300
198
+ DOS_DEFENSE_TRUSTED_IPS = ["127.0.0.1", "192.168.0.3"]
199
+
200
+ ```
201
+
202
+ ```bash
203
+ # --- SQL Injection Defense ---
204
+ SQLI_DEFENSE_TRUSTED_IPS = ["127.0.0.1", "192.168.0.3"]
205
+
206
+ # --- XSS Defense ---
207
+ XSS_DEFENSE_TRUSTED_IPS = ["127.0.0.1", "192.168.0.3"]
208
+ XSS_DEFENSE_SANITIZE_INPUT = False
209
+ XSS_DEFENSE_BLOCK = True
210
+ XSS_DEFENSE_EXCLUDED_PATHS = ["/health", "/internal"]
211
+
212
+ # --- CSRF Defense ---
213
+ CSRF_DEFENSE_TRUSTED_IPS = ["127.0.0.1", "192.168.0.3"]
214
+ CSRF_DEFENSE_BLOCK = True
215
+ CSRF_DEFENSE_LOG = True
216
+
217
+ ```
218
+ ### Auditoría y correlación de eventos
219
+ ```bash
220
+ request.xss_attack_info = {
221
+ "ip": "192.168.1.10",
222
+ "tipos": ["XSS"],
223
+ "descripcion": ["Etiqueta <script> detectada"],
224
+ "payload": {"field": "comentario", "snippet": "<script>alert(1)</script>"},
225
+ "score": 0.92,
226
+ "url": "/comentarios/enviar/",
227
+ }
228
+
229
+ ```
230
+ ### Filosofía del proyecto
231
+ Guardian Univalle – Benito & Junkrat busca proporcionar una capa de defensa proactiva para entornos Django universitarios y empresariales, combinando:
232
+
233
+ #Detección heurística.
234
+
235
+ #Análisis semántico de cabeceras y payloads.
236
+
237
+ #Escalamiento de score basado en señales múltiples.
238
+
239
+ Su diseño es didáctico y extensible, ideal tanto para proyectos reales como para enseñanza de ciberseguridad aplicada.
240
+ ---
241
+ ### Estructura del paquete
242
+ ```bash
243
+ guardian_univalle/
244
+
245
+ ├── detectores/
246
+ │ ├── csrf_defense.py
247
+ │ ├── xss_defense.py
248
+ │ ├── sql_defense.py
249
+ │ ├── dos_defense.py
250
+ │ ├── scraping_defense.py
251
+
252
+ ├── auditoria/
253
+ │ └── auditoria_middleware.py
254
+
255
+ └── __init__.py
256
+
257
+ ```
258
+ ### Licencia
259
+ Este proyecto se distribuye bajo la licencia MIT, permitiendo libre uso y modificación con atribución.
260
+
261
+ 📘 Universidad Privada del Valle – Sede La Paz
262
+
263
+ 👨‍💻 Desarrollado por: Benito Yucra
264
+
265
+ 📅 Año: 2025
@@ -4,16 +4,16 @@ GuardianUnivalle_Benito_Yucra/auditoria/registro_auditoria.py,sha256=NnKBOeRWkXV
4
4
  GuardianUnivalle_Benito_Yucra/criptografia/cifrado_aead.py,sha256=wfoRpaKvOqPbollNQsDNUNWClYJlXYTKTYvv0qcR6aI,962
5
5
  GuardianUnivalle_Benito_Yucra/criptografia/intercambio_claves.py,sha256=9djnlzb022hUhrDbQyWz7lWLbkn_vQZ4K7qar1FXYmo,829
6
6
  GuardianUnivalle_Benito_Yucra/criptografia/kdf.py,sha256=_sbepEY1qHEKga0ExrX2WRg1HeCPY5MC5CfXZWYyl-A,709
7
- GuardianUnivalle_Benito_Yucra/detectores/detector_csrf.py,sha256=VASJJztJtKwYpjuEUXc-biHSVbIYXhwCzOPrLNXu3qY,7832
7
+ GuardianUnivalle_Benito_Yucra/detectores/detector_csrf.py,sha256=cVc5-rIwgOuFkov1tHtUR2PnyFdF3Ns6RvJMq4hkuOU,12486
8
8
  GuardianUnivalle_Benito_Yucra/detectores/detector_dos.py,sha256=Jy4fhI-6n9wQR0quzpondcUyCA2447lDq4fmOFeM1jA,14989
9
- GuardianUnivalle_Benito_Yucra/detectores/detector_sql.py,sha256=toYXgxLo1Wy_QCnqcboD7_qYbgudPtP4kEzci7GoDkA,12089
10
- GuardianUnivalle_Benito_Yucra/detectores/detector_xss.py,sha256=Cirjf1fo0j-wOO2baG8GFehAvjPy5JUF9krUg5AtofU,14452
9
+ GuardianUnivalle_Benito_Yucra/detectores/detector_sql.py,sha256=9UZFr68WqzZ7LxouY-4fPkzNWJGcrrB8HDEKUqwP_KQ,14765
10
+ GuardianUnivalle_Benito_Yucra/detectores/detector_xss.py,sha256=azK7pTnO7fxcClEEDoLVBdvWF-hQAvM5KElg9O6Ohkc,14963
11
11
  GuardianUnivalle_Benito_Yucra/middleware_web/middleware_web.py,sha256=23pLLYqliUoMrIC6ZEwz3hKXeDjWfHSm9vYPWGmDDik,495
12
12
  GuardianUnivalle_Benito_Yucra/mitigacion/limitador_peticion.py,sha256=ipMOebYhql-6mSyHs0ddYXOcXq9w8P_IXLlpiIqGncw,246
13
13
  GuardianUnivalle_Benito_Yucra/mitigacion/lista_bloqueo.py,sha256=6AYWII4mrmwCLHCvGTyoBxR4Oasr4raSHpFbVjqn7d8,193
14
14
  GuardianUnivalle_Benito_Yucra/puntuacion/puntuacion_amenaza.py,sha256=Wx5XfcII4oweLvZsTBEJ7kUc9pMpP5-36RfI5C5KJXo,561
15
- guardianunivalle_benito_yucra-0.1.69.dist-info/licenses/LICENSE,sha256=5e4IdL542v1E8Ft0A24GZjrxZeTsVK7XrS3mZEUhPtM,37
16
- guardianunivalle_benito_yucra-0.1.69.dist-info/METADATA,sha256=EnImanXF-rGOrfmdT8Cl7APWzSVHbppYJMIXLJMAWiY,7534
17
- guardianunivalle_benito_yucra-0.1.69.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
18
- guardianunivalle_benito_yucra-0.1.69.dist-info/top_level.txt,sha256=HTWfZM64WAV_QYr5cnXnLuabQt92dvlxqlR3pCwpbDQ,30
19
- guardianunivalle_benito_yucra-0.1.69.dist-info/RECORD,,
15
+ guardianunivalle_benito_yucra-0.1.71.dist-info/licenses/LICENSE,sha256=5e4IdL542v1E8Ft0A24GZjrxZeTsVK7XrS3mZEUhPtM,37
16
+ guardianunivalle_benito_yucra-0.1.71.dist-info/METADATA,sha256=62MKAtQZZ5gi7qyui4-rDZ5sLXyHaS12MvmLWnWBZlQ,9984
17
+ guardianunivalle_benito_yucra-0.1.71.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
18
+ guardianunivalle_benito_yucra-0.1.71.dist-info/top_level.txt,sha256=HTWfZM64WAV_QYr5cnXnLuabQt92dvlxqlR3pCwpbDQ,30
19
+ guardianunivalle_benito_yucra-0.1.71.dist-info/RECORD,,
@@ -1,192 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: GuardianUnivalle-Benito-Yucra
3
- Version: 0.1.69
4
- Summary: Middleware y detectores de seguridad (SQLi, XSS, CSRF, DoS) para Django/Flask
5
- Author-email: Andres Benito Calle Yucra <benitoandrescalle035@gmail.com>
6
- License: MIT
7
- Project-URL: Homepage, https://pypi.org/project/guardianunivalle-benito-yucra/
8
- Project-URL: Bug_Tracker, https://github.com/Andyyupy/guardianunivalle-benito-yucra/issues
9
- Keywords: security,django,flask,sqli,xss,csrf,middleware
10
- Classifier: Development Status :: 3 - Alpha
11
- Classifier: Intended Audience :: Developers
12
- Classifier: Topic :: Security
13
- Classifier: License :: OSI Approved :: MIT License
14
- Classifier: Programming Language :: Python :: 3
15
- Classifier: Framework :: Django
16
- Classifier: Framework :: Flask
17
- Requires-Python: >=3.8
18
- Description-Content-Type: text/markdown
19
- License-File: LICENSE
20
- Requires-Dist: redis>=4.0
21
- Requires-Dist: django>=3.2
22
- Dynamic: license-file
23
-
24
- <!-- Información de la librería -->
25
-
26
- # 🛡️ Guardian Univalle – Benito & Junkrat
27
-
28
- Framework de detección y defensa de amenazas web para Django y Flask
29
-
30
- Guardian Univalle es un sistema de seguridad modular desarrollado para fortalecer aplicaciones Django frente a ataques web comunes como XSS, CSRF, inyección SQL, ataques DoS y scraping automatizado.
31
- Cada módulo opera mediante middleware independientes que analizan el tráfico HTTP en tiempo real, aplican heurísticas inteligentes y registran eventos sospechosos para auditoría y bloqueo adaptativo.
32
-
33
- ⚙️ Arquitectura general
34
-
35
- Guardian Univalle está diseñado bajo una arquitectura modular y extensible, donde cada tipo de amenaza se gestiona mediante un middleware especializado.
36
- Cada middleware:
37
-
38
- - Se ejecuta en la fase inicial del request (process_request).
39
- - Analiza cabeceras, cuerpo y metadatos de la petición.
40
- - Evalúa indicadores de ataque según patrones heurísticos y reglas configurables.
41
- - Calcula una puntuación de riesgo (score) para cada evento.
42
- - Anexa la información al objeto request (por ejemplo, request.xss_attack_info) para que otros módulos (como el de auditoría) la procesen.
43
-
44
- 🧩 Módulos de defensa incluidos
45
-
46
- 1. 🔐 CSRFDefenseMiddleware
47
-
48
- Defensa contra Cross-Site Request Forgery (CSRF).
49
-
50
- Este módulo detecta intentos de falsificación de peticiones mediante:
51
-
52
- - Verificación de cabeceras Origin y Referer contra el host real.
53
- - Validación de tokens CSRF en cookies, cabeceras o formularios.
54
- - Análisis del tipo de contenido (Content-Type) y parámetros sensibles.
55
- - Detección de peticiones JSON o formularios enviados desde dominios externos.
56
- - Asignación de un score de riesgo proporcional al número y severidad de señales encontradas.
57
-
58
- Algoritmos utilizados:
59
- Heurísticas basadas en cabeceras HTTP, validación semántica de origen, y detección de anomalías en métodos POST, PUT, DELETE y PATCH.
60
-
61
- 2. 🧬 XSSDefenseMiddleware
62
-
63
- Defensa contra Cross-Site Scripting (XSS).
64
-
65
- Analiza en profundidad los datos enviados en el cuerpo y querystring, detectando vectores de inyección HTML/JS mediante:
66
-
67
- - Patrones de alto riesgo (<script>, javascript:, onload=, eval()).
68
- - Ofuscaciones con entidades (&#x3C;, %3Cscript).
69
- - Detección de atributos de eventos (onmouseover, onfocus, etc.).
70
- - Análisis de URIs maliciosas (data:text/html, vbscript:).
71
- - Scoring ponderado por severidad (de 0.3 a 0.95).
72
-
73
- Algoritmos utilizados:
74
- Detección basada en expresiones regulares avanzadas con pesos heurísticos y uso opcional de la librería Bleach para sanitización comparativa.
75
-
76
- Salida:
77
- Agrega request.xss_attack_info con los detalles de detección, la IP de origen, descripción, payload y score total.
78
-
79
- 3. 💾 SQLIDefenseMiddleware
80
-
81
- Defensa contra Inyección SQL (SQLi).
82
-
83
- Identifica intentos de inyección SQL en los parámetros enviados a través de:
84
-
85
- - Palabras clave peligrosas (UNION, SELECT, DROP, INSERT, UPDATE).
86
- - Uso de comentarios (--, #, /_ ... _/).
87
- - Concatenaciones o subconsultas sospechosas.
88
- - Comportamientos anómalos en parámetros GET, POST o JSON.
89
-
90
- Algoritmos utilizados:
91
- Heurísticas sintácticas + patrones combinados con contextos.
92
- Evalúa combinaciones de operadores y palabras reservadas para minimizar falsos positivos.
93
-
94
- Resultado:
95
- Registra el intento en request.sql_injection_info con score calculado y parámetros comprometidos.
96
-
97
- 4. 🌐 DOSDefenseMiddleware
98
-
99
- Detección de ataques de Denegación de Servicio (DoS).
100
-
101
- Monitorea la frecuencia de peticiones por IP y calcula una métrica adaptativa de comportamiento:
102
-
103
- - Detecta exceso de solicitudes en intervalos cortos.
104
- - Analiza User-Agent, patrones repetitivos y tamaño de payloads.
105
- - Aplica límites configurables (MAX_REQUESTS_PER_WINDOW).
106
- - Marca IPs sospechosas para registro y bloqueo temporal.
107
-
108
- Algoritmos utilizados:
109
- Sliding Window con conteo adaptativo en memoria, controlado por señales de frecuencia e intensidad.
110
-
111
- 5. 🕷️ ScrapingDefenseMiddleware (opcional)
112
-
113
- Detección de scraping y bots automatizados.
114
-
115
- Evalúa características típicas de scraping:
116
-
117
- - User-Agent anómalo o ausente.
118
- - Patrón de navegación repetitivo o excesivamente rápido.
119
- - Ausencia de cabeceras humanas (como Accept-Language o Referer).
120
- - Combinación con heurísticas de DoS para detectar scrapers agresivos.
121
-
122
- Algoritmos utilizados:
123
- Análisis estadístico de cabeceras + patrones de comportamiento a corto plazo.
124
-
125
- 🧠 Integración y uso
126
-
127
- Instalar la librería:
128
-
129
- pip install guardian-univalle
130
-
131
- En tu archivo settings.py de Django, añadir los middlewares:
132
-
133
- MIDDLEWARE = [
134
- "guardian_univalle.detectores.csrf_defense.CSRFDefenseMiddleware",
135
- "guardian_univalle.detectores.xss_defense.XSSDefenseMiddleware",
136
- "guardian_univalle.detectores.sql_defense.SQLIDefenseMiddleware",
137
- "guardian_univalle.detectores.dos_defense.DOSDefenseMiddleware",
138
- "guardian_univalle.detectores.scraping_defense.ScrapingDefenseMiddleware", # opcional
139
- ]
140
-
141
- (Opcional) Configurar umbrales en settings.py:
142
-
143
- XSS_DEFENSE_THRESHOLD = 0.6
144
- CSRF_DEFENSE_MIN_SIGNALS = 1
145
- DOS_DEFENSE_MAX_REQUESTS = 100
146
- SQLI_DEFENSE_THRESHOLD = 0.5
147
-
148
- 🧾 Auditoría y correlación de eventos
149
-
150
- Cada middleware genera un diccionario con detalles de detección:
151
-
152
- request.xss_attack_info = {
153
- "ip": "192.168.1.10",
154
- "tipos": ["XSS"],
155
- "descripcion": ["Etiqueta <script> detectada"],
156
- "payload": "{'field': 'comentario', 'snippet': '<script>alert(1)</script>'}",
157
- "score": 0.92,
158
- "url": "/comentarios/enviar/",
159
- }
160
-
161
- Estos datos pueden ser almacenados por un AuditoriaMiddleware o enviados a un sistema SIEM para correlación y respuesta automatizada.
162
-
163
- 🧩 Filosofía del proyecto
164
-
165
- Guardian Univalle – Benito & Junkrat busca proporcionar una capa de defensa proactiva para entornos Django universitarios y empresariales, combinando:
166
-
167
- Detección heurística,
168
-
169
- Análisis semántico de cabeceras y payloads, y
170
-
171
- Escalamiento de score basado en señales múltiples.
172
-
173
- Su diseño es didáctico y extensible, ideal tanto para proyectos reales como para enseñanza de ciberseguridad aplicada.
174
-
175
- 🧱 Estructura del paquete
176
- guardian_univalle/
177
-
178
- ├── detectores/
179
- │ ├── csrf_defense.py
180
- │ ├── xss_defense.py
181
- │ ├── sql_defense.py
182
- │ ├── dos_defense.py
183
- │ ├── scraping_defense.py
184
-
185
- ├── auditoria/
186
- │ └── auditoria_middleware.py
187
-
188
- └── **init**.py
189
-
190
- 🧾 Licencia
191
-
192
- Este proyecto se distribuye bajo la licencia MIT, permitiendo libre uso y modificación con atribución.