GuardianUnivalle-Benito-Yucra 0.1.29__tar.gz → 0.1.31__tar.gz

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.

Files changed (30) hide show
  1. guardianunivalle_benito_yucra-0.1.31/GuardianUnivalle_Benito_Yucra/detectores/detector_csrf.py +239 -0
  2. guardianunivalle_benito_yucra-0.1.31/GuardianUnivalle_Benito_Yucra/detectores/detector_dos.py +166 -0
  3. guardianunivalle_benito_yucra-0.1.31/GuardianUnivalle_Benito_Yucra/detectores/detector_keylogger.py +214 -0
  4. guardianunivalle_benito_yucra-0.1.31/GuardianUnivalle_Benito_Yucra/detectores/detector_sql.py +187 -0
  5. guardianunivalle_benito_yucra-0.1.31/GuardianUnivalle_Benito_Yucra/detectores/detector_xss.py +197 -0
  6. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/GuardianUnivalle_Benito_Yucra.egg-info/PKG-INFO +1 -1
  7. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/PKG-INFO +1 -1
  8. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/pyproject.toml +1 -1
  9. guardianunivalle_benito_yucra-0.1.29/GuardianUnivalle_Benito_Yucra/detectores/detector_csrf.py +0 -21
  10. guardianunivalle_benito_yucra-0.1.29/GuardianUnivalle_Benito_Yucra/detectores/detector_dos.py +0 -17
  11. guardianunivalle_benito_yucra-0.1.29/GuardianUnivalle_Benito_Yucra/detectores/detector_keylogger.py +0 -21
  12. guardianunivalle_benito_yucra-0.1.29/GuardianUnivalle_Benito_Yucra/detectores/detector_sql.py +0 -88
  13. guardianunivalle_benito_yucra-0.1.29/GuardianUnivalle_Benito_Yucra/detectores/detector_xss.py +0 -139
  14. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/GuardianUnivalle_Benito_Yucra/__init__.py +0 -0
  15. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/GuardianUnivalle_Benito_Yucra/auditoria/registro_auditoria.py +0 -0
  16. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/GuardianUnivalle_Benito_Yucra/criptografia/cifrado_aead.py +0 -0
  17. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/GuardianUnivalle_Benito_Yucra/criptografia/intercambio_claves.py +0 -0
  18. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/GuardianUnivalle_Benito_Yucra/criptografia/kdf.py +0 -0
  19. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/GuardianUnivalle_Benito_Yucra/middleware_web/middleware_web.py +0 -0
  20. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/GuardianUnivalle_Benito_Yucra/mitigacion/limitador_peticion.py +0 -0
  21. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/GuardianUnivalle_Benito_Yucra/mitigacion/lista_bloqueo.py +0 -0
  22. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/GuardianUnivalle_Benito_Yucra/puntuacion/puntuacion_amenaza.py +0 -0
  23. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/GuardianUnivalle_Benito_Yucra/utilidades.py +0 -0
  24. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/GuardianUnivalle_Benito_Yucra.egg-info/SOURCES.txt +0 -0
  25. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/GuardianUnivalle_Benito_Yucra.egg-info/dependency_links.txt +0 -0
  26. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/GuardianUnivalle_Benito_Yucra.egg-info/requires.txt +0 -0
  27. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/GuardianUnivalle_Benito_Yucra.egg-info/top_level.txt +0 -0
  28. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/LICENSE +0 -0
  29. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/README.md +0 -0
  30. {guardianunivalle_benito_yucra-0.1.29 → guardianunivalle_benito_yucra-0.1.31}/setup.cfg +0 -0
@@ -0,0 +1,239 @@
1
+ """
2
+ CSRF Defense Middleware
3
+ ========================
4
+ Detecta y registra posibles ataques CSRF (Cross-Site Request Forgery).
5
+
6
+ Algoritmos relacionados:
7
+ * Uso de secreto aleatorio criptográfico (generar_token_csrf).
8
+ * Validación simple por comparación (validar_token_csrf).
9
+ * Contribución a fórmula de amenaza S:
10
+ S_csrf = w_csrf * intentos_csrf
11
+ S_csrf = 0.2 * 1
12
+ """
13
+
14
+ from __future__ import annotations
15
+ import secrets
16
+ import logging
17
+ import re
18
+ import json
19
+ from typing import List
20
+ from urllib.parse import urlparse
21
+ from django.conf import settings
22
+ from django.utils.deprecation import MiddlewareMixin
23
+
24
+ # ======================================================
25
+ # === CONFIGURACIÓN DE LOGGER ===
26
+ # ======================================================
27
+ logger = logging.getLogger("csrfdefense")
28
+ logger.setLevel(logging.INFO)
29
+ if not logger.handlers:
30
+ handler = logging.StreamHandler()
31
+ handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
32
+ logger.addHandler(handler)
33
+
34
+
35
+ # ======================================================
36
+ # === FUNCIONES AUXILIARES DE TOKEN CSRF ===
37
+ # ======================================================
38
+ def registrar_evento(tipo: str, mensaje: str):
39
+ """Registra eventos importantes en los logs."""
40
+ logger.warning(f"[{tipo}] {mensaje}")
41
+
42
+
43
+ def generar_token_csrf() -> str:
44
+ """Genera un token CSRF seguro."""
45
+ token = secrets.token_hex(32)
46
+ registrar_evento("CSRF", "Token CSRF generado")
47
+ return token
48
+
49
+
50
+ def validar_token_csrf(token: str, token_sesion: str) -> bool:
51
+ """Valida que el token recibido coincida con el token en sesión."""
52
+ valido = token == token_sesion
53
+ if not valido:
54
+ registrar_evento("CSRF", "Intento de CSRF detectado (token no coincide)")
55
+ return valido
56
+
57
+
58
+ # ======================================================
59
+ # === CONSTANTES Y CONFIGURACIONES ===
60
+ # ======================================================
61
+ STATE_CHANGING_METHODS = {"POST", "PUT", "PATCH", "DELETE"}
62
+ CSRF_HEADER_NAMES = (
63
+ "HTTP_X_CSRFTOKEN",
64
+ "HTTP_X_CSRF_TOKEN",
65
+ )
66
+ CSRF_COOKIE_NAME = getattr(settings, "CSRF_COOKIE_NAME", "csrftoken")
67
+ POST_FIELD_NAME = "csrfmiddlewaretoken"
68
+
69
+ SUSPICIOUS_CT_PATTERNS = [
70
+ re.compile(r"application/x-www-form-urlencoded", re.I),
71
+ re.compile(r"multipart/form-data", re.I),
72
+ ]
73
+
74
+
75
+ # ======================================================
76
+ # === FUNCIONES DE APOYO ===
77
+ # ======================================================
78
+ def get_client_ip(request):
79
+ x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR")
80
+ if x_forwarded_for:
81
+ return x_forwarded_for.split(",")[0].strip()
82
+ return request.META.get("REMOTE_ADDR", "")
83
+
84
+
85
+ def host_from_header(header_value: str) -> str | None:
86
+ if not header_value:
87
+ return None
88
+ try:
89
+ parsed = urlparse(header_value)
90
+ if parsed.netloc:
91
+ return parsed.netloc.split(":")[0]
92
+ return header_value.split(":")[0]
93
+ except Exception:
94
+ return None
95
+
96
+
97
+ def origin_matches_host(request) -> bool:
98
+ """Verifica si Origin/Referer coinciden con Host."""
99
+ host_header = request.META.get("HTTP_HOST") or request.META.get("SERVER_NAME")
100
+ if not host_header:
101
+ return True
102
+
103
+ host = host_header.split(":")[0]
104
+ origin = request.META.get("HTTP_ORIGIN", "")
105
+ referer = request.META.get("HTTP_REFERER", "")
106
+
107
+ origin_host = host_from_header(origin)
108
+ referer_host = host_from_header(referer)
109
+
110
+ if origin_host and origin_host == host:
111
+ return True
112
+ if referer_host and referer_host == host:
113
+ return True
114
+ if not origin and not referer:
115
+ return True
116
+
117
+ return False
118
+
119
+
120
+ def has_csrf_token(request) -> bool:
121
+ """Comprueba si hay signos de token CSRF presente."""
122
+ for h in CSRF_HEADER_NAMES:
123
+ if request.META.get(h):
124
+ return True
125
+
126
+ cookie_val = request.COOKIES.get(CSRF_COOKIE_NAME)
127
+ if cookie_val:
128
+ return True
129
+
130
+ try:
131
+ if request.method == "POST" and hasattr(request, "POST"):
132
+ if request.POST.get(POST_FIELD_NAME):
133
+ return True
134
+ except Exception:
135
+ pass
136
+
137
+ return False
138
+
139
+
140
+ def extract_payload_text(request) -> str:
141
+ """Extrae contenido útil de la solicitud para análisis."""
142
+ parts: List[str] = []
143
+ try:
144
+ body = request.body.decode("utf-8", errors="ignore")
145
+ if body:
146
+ parts.append(body)
147
+ except Exception:
148
+ pass
149
+ qs = request.META.get("QUERY_STRING", "")
150
+ if qs:
151
+ parts.append(qs)
152
+ parts.append(request.META.get("HTTP_USER_AGENT", ""))
153
+ parts.append(request.META.get("HTTP_REFERER", ""))
154
+ return " ".join([p for p in parts if p])
155
+
156
+
157
+ # ======================================================
158
+ # === MIDDLEWARE DE DEFENSA CSRF ===
159
+ # ======================================================
160
+ class CSRFDefenseMiddleware(MiddlewareMixin):
161
+ """
162
+ Middleware para DETECTAR intentos de CSRF:
163
+ - Marca request.sql_attack_info con 'tipos': ['CSRF'] y 'descripcion' con razones.
164
+ - No bloquea la petición directamente, permite que AuditoriaMiddleware lo maneje.
165
+ """
166
+
167
+ def process_request(self, request):
168
+ client_ip = get_client_ip(request)
169
+ trusted_ips = getattr(settings, "CSRF_DEFENSE_TRUSTED_IPS", [])
170
+ if client_ip in trusted_ips:
171
+ return None
172
+
173
+ excluded_paths = getattr(settings, "CSRF_DEFENSE_EXCLUDED_PATHS", [])
174
+ if any(request.path.startswith(p) for p in excluded_paths):
175
+ return None
176
+
177
+ method = (request.method or "").upper()
178
+ if method not in STATE_CHANGING_METHODS:
179
+ return None
180
+
181
+ descripcion: List[str] = []
182
+ payload = extract_payload_text(request)
183
+
184
+ # 1) Falta token CSRF
185
+ if not has_csrf_token(request):
186
+ descripcion.append("Falta token CSRF en cookie/header/form")
187
+
188
+ # 2) Origin/Referer no coinciden
189
+ if not origin_matches_host(request):
190
+ descripcion.append(
191
+ "Origin/Referer no coinciden con Host (posible cross-site)"
192
+ )
193
+
194
+ # 3) Content-Type sospechoso
195
+ content_type = request.META.get("CONTENT_TYPE", "") or ""
196
+ for patt in SUSPICIOUS_CT_PATTERNS:
197
+ if patt.search(content_type):
198
+ descripcion.append(f"Content-Type sospechoso: {content_type}")
199
+ break
200
+
201
+ # 4) Referer ausente
202
+ referer = request.META.get("HTTP_REFERER", "")
203
+ if not referer and not any(request.META.get(h) for h in CSRF_HEADER_NAMES):
204
+ descripcion.append("Referer ausente y sin X-CSRFToken")
205
+
206
+ # Si hay señales, calculamos puntaje y registramos
207
+ if descripcion:
208
+ w_csrf = getattr(settings, "CSRF_DEFENSE_WEIGHT", 0.2)
209
+ intentos_csrf = len(descripcion)
210
+ s_csrf = w_csrf * intentos_csrf
211
+
212
+ request.csrf_attack_info = {
213
+ "ip": client_ip,
214
+ "tipos": ["CSRF"],
215
+ "descripcion": descripcion,
216
+ "payload": payload,
217
+ "score": s_csrf,
218
+ }
219
+
220
+ logger.warning(
221
+ "CSRF detectado desde IP %s: %s ; payload: %.200s ; score: %.2f",
222
+ client_ip,
223
+ descripcion,
224
+ payload,
225
+ s_csrf,
226
+ )
227
+
228
+ return None
229
+
230
+
231
+ """
232
+ Algoritmos relacionados:
233
+ *Uso de secreto aleatorio criptográfico.
234
+ *Opcionalmente derivación con PBKDF2 / Argon2 para reforzar token.
235
+ Contribución a fórmula de amenaza S:
236
+ S_csrf = w_csrf * intentos_csrf
237
+ S_csrf = 0.2 * 1
238
+ donde w_csrf es peso asignado a CSRF y intentos_csrf es la cantidad de intentos detectados.
239
+ """
@@ -0,0 +1,166 @@
1
+ """
2
+ Detector de ataques de tipo DoS (Denial of Service)
3
+ ====================================================
4
+
5
+ Este módulo forma parte del sistema de detección de amenazas.
6
+ Detecta tasas de petición anómalas en base a límites configurables,
7
+ captura datos del atacante (IP, agente, cabeceras)
8
+ y registra los incidentes para su auditoría.
9
+
10
+ Componentes:
11
+ - DOSDefenseMiddleware: Middleware principal de detección.
12
+ - detectar_dos(): Evalúa si la tasa supera el umbral permitido.
13
+ - calcular_nivel_amenaza_dos(): Calcula la severidad proporcional.
14
+ - registrar_evento(): Registra los incidentes en auditoría.
15
+
16
+ Algoritmos relacionados:
17
+ * Rate Limiting basado en ventana deslizante.
18
+ * Cálculo de score: S_dos = w_dos * (tasa_peticion / limite)
19
+ """
20
+
21
+ from __future__ import annotations
22
+ import time
23
+ import logging
24
+ import json
25
+ from typing import Dict, List
26
+ from django.conf import settings
27
+ from django.utils.deprecation import MiddlewareMixin
28
+ from ..mitigacion.limitador_peticion import limitar_peticion
29
+ from ..auditoria.registro_auditoria import registrar_evento
30
+
31
+ # =====================================================
32
+ # === CONFIGURACIÓN DEL LOGGER ===
33
+ # =====================================================
34
+ logger = logging.getLogger("dosdefense")
35
+ logger.setLevel(logging.INFO)
36
+ if not logger.handlers:
37
+ handler = logging.StreamHandler()
38
+ handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
39
+ logger.addHandler(handler)
40
+
41
+
42
+ # =====================================================
43
+ # === PARÁMETROS DE CONFIGURACIÓN BASE ===
44
+ # =====================================================
45
+ LIMITE_PETICIONES = getattr(settings, "DOS_LIMITE_PETICIONES", 100) # por minuto
46
+ VENTANA_SEGUNDOS = getattr(settings, "DOS_VENTANA_SEGUNDOS", 60)
47
+ PESO_DOS = getattr(settings, "DOS_PESO", 0.6)
48
+
49
+
50
+ # =====================================================
51
+ # === REGISTRO TEMPORAL DE SOLICITUDES POR IP ===
52
+ # =====================================================
53
+ # En producción se recomienda usar Redis o Memcached
54
+ # para este tipo de conteo, aquí usamos una memoria temporal.
55
+ REGISTRO_SOLICITUDES: Dict[str, List[float]] = {}
56
+
57
+
58
+ # =====================================================
59
+ # === FUNCIONES AUXILIARES ===
60
+ # =====================================================
61
+ def get_client_ip(request) -> str:
62
+ """Obtiene la IP real del cliente (considera proxies)."""
63
+ x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR")
64
+ if x_forwarded_for:
65
+ return x_forwarded_for.split(",")[0].strip()
66
+ return request.META.get("REMOTE_ADDR", "")
67
+
68
+
69
+ def limpiar_registro(ip: str):
70
+ """Limpia peticiones antiguas fuera de la ventana de tiempo."""
71
+ ahora = time.time()
72
+ REGISTRO_SOLICITUDES[ip] = [
73
+ t for t in REGISTRO_SOLICITUDES.get(ip, []) if ahora - t < VENTANA_SEGUNDOS
74
+ ]
75
+
76
+
77
+ def calcular_nivel_amenaza_dos(
78
+ tasa_peticion: int, limite: int = LIMITE_PETICIONES
79
+ ) -> float:
80
+ """
81
+ Calcula la puntuación de amenaza DoS basada en el peso configurado.
82
+ Fórmula: S_dos = w_dos * (tasa_peticion / limite)
83
+ """
84
+ proporcion = tasa_peticion / limite
85
+ s_dos = PESO_DOS * proporcion
86
+ return round(min(s_dos, 1.0), 3)
87
+
88
+
89
+ def detectar_dos(ip: str, tasa_peticion: int, limite: int = LIMITE_PETICIONES) -> bool:
90
+ """Evalúa si la tasa de peticiones excede el umbral permitido."""
91
+ if tasa_peticion > limite:
92
+ registrar_evento(
93
+ tipo="DoS",
94
+ descripcion=f"Alta tasa de peticiones desde {ip}: {tasa_peticion} req/min (límite {limite})",
95
+ severidad="ALTA",
96
+ )
97
+ limitar_peticion() # Acción de mitigación
98
+ return True
99
+ return False
100
+
101
+
102
+ # =====================================================
103
+ # === MIDDLEWARE DE DETECCIÓN DE DoS ===
104
+ # =====================================================
105
+ class DOSDefenseMiddleware(MiddlewareMixin):
106
+ """
107
+ Middleware para detección y registro de ataques DoS.
108
+ - Captura IP, agente y cabeceras sospechosas.
109
+ - Evalúa la frecuencia de peticiones por IP.
110
+ - Marca request.sql_attack_info con información del intento.
111
+ """
112
+
113
+ def process_request(self, request):
114
+ client_ip = get_client_ip(request)
115
+ user_agent = request.META.get("HTTP_USER_AGENT", "Desconocido")
116
+ referer = request.META.get("HTTP_REFERER", "")
117
+ path = request.path
118
+
119
+ # Limpieza de registro anterior
120
+ limpiar_registro(client_ip)
121
+
122
+ # Registrar nueva petición
123
+ REGISTRO_SOLICITUDES.setdefault(client_ip, []).append(time.time())
124
+ tasa = len(REGISTRO_SOLICITUDES[client_ip])
125
+ nivel = calcular_nivel_amenaza_dos(tasa)
126
+ es_dos = detectar_dos(client_ip, tasa)
127
+
128
+ if es_dos:
129
+ descripcion = [
130
+ f"Tasa de {tasa} req/min excede límite {LIMITE_PETICIONES}",
131
+ f"User-Agent: {user_agent}",
132
+ f"Referer: {referer or 'N/A'}",
133
+ f"Ruta: {path}",
134
+ ]
135
+
136
+ # Log profesional
137
+ logger.warning(
138
+ "DoS detectado desde IP %s: %s ; nivel: %.2f",
139
+ client_ip,
140
+ descripcion,
141
+ nivel,
142
+ )
143
+
144
+ # Enviar a sistema de auditoría
145
+ request.dos_attack_info = {
146
+ "ip": client_ip,
147
+ "tipos": ["DoS"],
148
+ "descripcion": descripcion,
149
+ "payload": json.dumps(
150
+ {"user_agent": user_agent, "referer": referer, "path": path}
151
+ ),
152
+ "score": nivel,
153
+ }
154
+
155
+ return None
156
+
157
+
158
+ """
159
+ Algoritmos relacionados:
160
+ *Rate Limiting, listas de bloqueo.
161
+ *Opcional: cifrado de logs con ChaCha20-Poly1305.
162
+ Contribución a fórmula de amenaza S:
163
+ S_dos = w_dos * (tasa_peticion / limite)
164
+ S_dos = 0.6 * (150 / 100)
165
+ donde w_dos es peso asignado a DoS y tasa_peticion / limite es la proporción de la tasa actual sobre el límite.
166
+ """
@@ -0,0 +1,214 @@
1
+ """
2
+ Detector extendido de Keyloggers
3
+ ================================
4
+
5
+ Módulo avanzado de detección de keyloggers y software espía en el sistema.
6
+ Incluye revisión de procesos activos, archivos ejecutables sospechosos y
7
+ aplicaciones instaladas en el sistema operativo Windows.
8
+
9
+ Componentes:
10
+ - Escaneo de procesos activos.
11
+ - Detección de archivos con extensiones críticas (.exe, .dll, .scr, .bat, .cmd, .msi).
12
+ - Revisión de aplicaciones instaladas (si se ejecuta en Windows).
13
+ - Cálculo de nivel de amenaza y registro de auditoría.
14
+
15
+ Algoritmos:
16
+ * Revisión de procesos (psutil)
17
+ * Análisis de archivos con extensiones críticas
18
+ * Detección de software instalado
19
+ * Registro cifrado con AES-256 + SHA-512
20
+ * Fórmula: S_keylogger = w_keylogger * (procesos + archivos + instalaciones)
21
+ """
22
+
23
+ from __future__ import annotations
24
+ import psutil
25
+ import os
26
+ import logging
27
+ import platform
28
+ import subprocess
29
+ from typing import List, Dict
30
+ from django.conf import settings
31
+ from ..auditoria.registro_auditoria import registrar_evento
32
+
33
+ # =====================================================
34
+ # === CONFIGURACIÓN DEL LOGGER ===
35
+ # =====================================================
36
+ logger = logging.getLogger("keyloggerdefense")
37
+ logger.setLevel(logging.INFO)
38
+ if not logger.handlers:
39
+ handler = logging.StreamHandler()
40
+ handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
41
+ logger.addHandler(handler)
42
+ # =========================================
43
+ # Middleware de Keylogger para Django
44
+ # =========================================
45
+ from django.utils.deprecation import MiddlewareMixin
46
+
47
+
48
+ class KEYLOGGERDefenseMiddleware(MiddlewareMixin):
49
+ """
50
+ Middleware que ejecuta el escaneo de keyloggers
51
+ en cada request entrante.
52
+ """
53
+
54
+ def __init__(self, get_response=None):
55
+ super().__init__(get_response)
56
+ # Importa tu clase de detección
57
+ from .detector_keylogger import KEYLOGGERDefense
58
+
59
+ self.detector = KEYLOGGERDefense()
60
+
61
+ def process_request(self, request):
62
+ """
63
+ Ejecuta el escaneo antes de procesar la vista.
64
+ Guarda los resultados en el objeto request para uso posterior.
65
+ """
66
+ try:
67
+ resultado = self.detector.ejecutar_escaneo()
68
+ request.keylogger_attack_info = resultado
69
+ except Exception as e:
70
+ # Evita que un error detenga Django
71
+ import logging
72
+
73
+ logger = logging.getLogger("keyloggerdefense")
74
+ logger.error("Error en KEYLOGGERDefenseMiddleware: %s", e)
75
+
76
+
77
+ # =====================================================
78
+ # === CONFIGURACIÓN DE PARÁMETROS ===
79
+ # =====================================================
80
+ PESO_KEYLOGGER = getattr(settings, "KEYLOGGER_PESO", 0.4)
81
+ EXTENSIONES_SOSPECHOSAS = [".exe", ".dll", ".scr", ".bat", ".cmd", ".msi"]
82
+ CARPETAS_CRITICAS = [
83
+ "C:\\Users\\Public",
84
+ "C:\\Users\\%USERNAME%\\AppData\\Roaming",
85
+ "C:\\Users\\%USERNAME%\\AppData\\Local\\Temp",
86
+ "C:\\ProgramData",
87
+ "C:\\Windows\\Temp",
88
+ ]
89
+ PATRONES_NOMBRES = ["keylogger", "spy", "hook", "keyboard", "capture", "stealer"]
90
+
91
+
92
+ # =====================================================
93
+ # === FUNCIONES AUXILIARES ===
94
+ # =====================================================
95
+ def calcular_score_keylogger(total_items: int) -> float:
96
+ """Calcula el nivel de amenaza normalizado."""
97
+ return round(min(PESO_KEYLOGGER * total_items, 1.0), 3)
98
+
99
+
100
+ def detectar_procesos_sospechosos() -> List[Dict]:
101
+ """Escanea procesos activos y detecta posibles keyloggers."""
102
+ hallazgos = []
103
+ for proc in psutil.process_iter(["pid", "name", "exe"]):
104
+ try:
105
+ nombre = proc.info.get("name", "").lower()
106
+ if any(pat in nombre for pat in PATRONES_NOMBRES):
107
+ hallazgos.append(proc.info)
108
+ registrar_evento("Keylogger", f"Proceso sospechoso: {proc.info}")
109
+ except (psutil.NoSuchProcess, psutil.AccessDenied):
110
+ continue
111
+ return hallazgos
112
+
113
+
114
+ def detectar_archivos_sospechosos() -> List[str]:
115
+ """
116
+ Busca archivos con extensiones peligrosas y nombres relacionados
117
+ a keyloggers en carpetas críticas del sistema.
118
+ """
119
+ hallazgos = []
120
+ for base in CARPETAS_CRITICAS:
121
+ base = os.path.expandvars(base) # reemplaza %USERNAME%
122
+ if not os.path.exists(base):
123
+ continue
124
+ for root, _, files in os.walk(base):
125
+ for file in files:
126
+ if any(file.lower().endswith(ext) for ext in EXTENSIONES_SOSPECHOSAS):
127
+ if any(pat in file.lower() for pat in PATRONES_NOMBRES):
128
+ ruta = os.path.join(root, file)
129
+ hallazgos.append(ruta)
130
+ registrar_evento("Keylogger", f"Archivo sospechoso: {ruta}")
131
+ return hallazgos
132
+
133
+
134
+ def detectar_programas_instalados() -> List[str]:
135
+ """
136
+ Analiza programas instalados en el sistema (solo Windows)
137
+ para encontrar software potencialmente malicioso.
138
+ """
139
+ hallazgos = []
140
+ if platform.system() != "Windows":
141
+ return hallazgos
142
+
143
+ try:
144
+ salida = subprocess.check_output(
145
+ ["wmic", "product", "get", "name"], stderr=subprocess.DEVNULL
146
+ ).decode("utf-8", errors="ignore")
147
+
148
+ for linea in salida.splitlines():
149
+ nombre = linea.strip().lower()
150
+ if any(pat in nombre for pat in PATRONES_NOMBRES):
151
+ hallazgos.append(nombre)
152
+ registrar_evento("Keylogger", f"Software sospechoso: {nombre}")
153
+ except Exception as e:
154
+ logger.error("Error al listar programas instalados: %s", e)
155
+
156
+ return hallazgos
157
+
158
+
159
+ # =====================================================
160
+ # === CLASE PRINCIPAL DE DETECCIÓN ===
161
+ # =====================================================
162
+ class KEYLOGGERDefense:
163
+ """
164
+ Escanea procesos, archivos y programas para detectar keyloggers
165
+ o software espía potencialmente malicioso.
166
+ """
167
+
168
+ def ejecutar_escaneo(self):
169
+ procesos = detectar_procesos_sospechosos()
170
+ archivos = detectar_archivos_sospechosos()
171
+ programas = detectar_programas_instalados()
172
+
173
+ total_hallazgos = len(procesos) + len(archivos) + len(programas)
174
+ score = calcular_score_keylogger(total_hallazgos)
175
+
176
+ if total_hallazgos > 0:
177
+ descripcion = [
178
+ f"Procesos sospechosos: {len(procesos)}",
179
+ f"Archivos sospechosos: {len(archivos)}",
180
+ f"Programas sospechosos: {len(programas)}",
181
+ ]
182
+
183
+ logger.warning("Keylogger detectado: %s ; nivel: %.2f", descripcion, score)
184
+
185
+ evento = {
186
+ "tipo": "Keylogger",
187
+ "descripcion": descripcion,
188
+ "procesos": procesos,
189
+ "archivos": archivos,
190
+ "programas": programas,
191
+ "score": score,
192
+ }
193
+
194
+ registrar_evento(
195
+ tipo="Keylogger",
196
+ descripcion=f"Detectados {total_hallazgos} elementos sospechosos.",
197
+ severidad="ALTA" if score >= 0.5 else "MEDIA",
198
+ )
199
+
200
+ return evento
201
+ else:
202
+ logger.info("Sin procesos, archivos o programas sospechosos detectados.")
203
+ return {"tipo": "Keylogger", "descripcion": "Sin hallazgos", "score": 0.0}
204
+
205
+
206
+ """
207
+ Algoritmos relacionados:
208
+ *Guardar registros con AES-256 + hash SHA-512 para integridad.
209
+ Contribución a fórmula de amenaza S:
210
+ S_keylogger = w_keylogger * numero_procesos_sospechosos
211
+ S_keylogger = 0.4 * 2
212
+ donde w_keylogger es peso asignado a keyloggers y numero_procesos_sospechosos es la cantidad de procesos detectados.
213
+
214
+ """