GuardianUnivalle-Benito-Yucra 0.1.46__tar.gz → 0.1.48__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.
- guardianunivalle_benito_yucra-0.1.48/GuardianUnivalle_Benito_Yucra/auditoria/registro_auditoria.py +155 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/GuardianUnivalle_Benito_Yucra.egg-info/PKG-INFO +1 -1
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/PKG-INFO +1 -1
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/pyproject.toml +1 -1
- guardianunivalle_benito_yucra-0.1.46/GuardianUnivalle_Benito_Yucra/auditoria/registro_auditoria.py +0 -40
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/GuardianUnivalle_Benito_Yucra/__init__.py +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/GuardianUnivalle_Benito_Yucra/criptografia/cifrado_aead.py +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/GuardianUnivalle_Benito_Yucra/criptografia/intercambio_claves.py +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/GuardianUnivalle_Benito_Yucra/criptografia/kdf.py +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/GuardianUnivalle_Benito_Yucra/detectores/detector_csrf.py +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/GuardianUnivalle_Benito_Yucra/detectores/detector_dos.py +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/GuardianUnivalle_Benito_Yucra/detectores/detector_keylogger.py +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/GuardianUnivalle_Benito_Yucra/detectores/detector_sql.py +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/GuardianUnivalle_Benito_Yucra/detectores/detector_xss.py +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/GuardianUnivalle_Benito_Yucra/middleware_web/middleware_web.py +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/GuardianUnivalle_Benito_Yucra/mitigacion/limitador_peticion.py +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/GuardianUnivalle_Benito_Yucra/mitigacion/lista_bloqueo.py +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/GuardianUnivalle_Benito_Yucra/puntuacion/puntuacion_amenaza.py +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/GuardianUnivalle_Benito_Yucra/utilidades.py +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/GuardianUnivalle_Benito_Yucra.egg-info/SOURCES.txt +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/GuardianUnivalle_Benito_Yucra.egg-info/dependency_links.txt +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/GuardianUnivalle_Benito_Yucra.egg-info/requires.txt +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/GuardianUnivalle_Benito_Yucra.egg-info/top_level.txt +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/LICENSE +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/README.md +0 -0
- {guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/setup.cfg +0 -0
guardianunivalle_benito_yucra-0.1.48/GuardianUnivalle_Benito_Yucra/auditoria/registro_auditoria.py
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# E:\EcuacionPotosi\GuardianUnivalle-Benito-Yucra\GuardianUnivalle_Benito_Yucra\auditoria\registro_auditoria.py
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import datetime
|
|
5
|
+
import json
|
|
6
|
+
import platform
|
|
7
|
+
import requests
|
|
8
|
+
from django.utils.timezone import now
|
|
9
|
+
from user_agents import parse
|
|
10
|
+
|
|
11
|
+
LOG_FILE = "auditoria_guardian.log"
|
|
12
|
+
|
|
13
|
+
# =====================================================
|
|
14
|
+
# === FUNCIONES DE CAPTURA Y ANÁLISIS DE CLIENTE ===
|
|
15
|
+
# =====================================================
|
|
16
|
+
|
|
17
|
+
def obtener_datos_maquina(request) -> dict:
|
|
18
|
+
"""Obtiene información detallada del cliente desde la petición"""
|
|
19
|
+
try:
|
|
20
|
+
# --- IP real ---
|
|
21
|
+
ip = (
|
|
22
|
+
request.META.get("HTTP_X_FORWARDED_FOR")
|
|
23
|
+
or request.META.get("REMOTE_ADDR")
|
|
24
|
+
or "0.0.0.0"
|
|
25
|
+
)
|
|
26
|
+
ip = ip.split(",")[0].strip()
|
|
27
|
+
|
|
28
|
+
# --- User Agent ---
|
|
29
|
+
user_agent_str = request.META.get("HTTP_USER_AGENT", "Desconocido")
|
|
30
|
+
user_agent = parse(user_agent_str)
|
|
31
|
+
navegador = f"{user_agent.browser.family} {user_agent.browser.version_string}"
|
|
32
|
+
sistema = f"{user_agent.os.family} {user_agent.os.version_string}"
|
|
33
|
+
|
|
34
|
+
# --- Geolocalización (ipinfo.io gratuita) ---
|
|
35
|
+
geo_data = {}
|
|
36
|
+
try:
|
|
37
|
+
r = requests.get(f"https://ipinfo.io/{ip}/json", timeout=2)
|
|
38
|
+
if r.status_code == 200:
|
|
39
|
+
geo_data = r.json()
|
|
40
|
+
except Exception:
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
pais = geo_data.get("country", "Desconocido")
|
|
44
|
+
ciudad = geo_data.get("city", "Desconocida")
|
|
45
|
+
isp = geo_data.get("org", "Desconocido")
|
|
46
|
+
|
|
47
|
+
# --- Usuario autenticado ---
|
|
48
|
+
usuario = "Anónimo"
|
|
49
|
+
if hasattr(request, "user") and request.user.is_authenticated:
|
|
50
|
+
usuario = getattr(request.user, "username", "Desconocido")
|
|
51
|
+
|
|
52
|
+
# --- Construir estructura ---
|
|
53
|
+
datos = {
|
|
54
|
+
"fecha": now().strftime("%Y-%m-%d %H:%M:%S"),
|
|
55
|
+
"ip": ip,
|
|
56
|
+
"pais": pais,
|
|
57
|
+
"ciudad": ciudad,
|
|
58
|
+
"isp": isp,
|
|
59
|
+
"usuario": usuario,
|
|
60
|
+
"user_agent": user_agent_str,
|
|
61
|
+
"navegador": navegador,
|
|
62
|
+
"sistema_operativo": sistema,
|
|
63
|
+
"url": request.path,
|
|
64
|
+
"metodo": request.method,
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return datos
|
|
68
|
+
except Exception as e:
|
|
69
|
+
return {"error": str(e)}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def analizar_comportamiento_cliente(datos_cliente: dict) -> tuple[str, str]:
|
|
73
|
+
"""
|
|
74
|
+
Aplica reglas básicas de detección:
|
|
75
|
+
- IP sospechosa o repetitiva
|
|
76
|
+
- Agente extraño o vacío
|
|
77
|
+
- Peticiones sospechosas (ej: /admin, /etc/passwd)
|
|
78
|
+
Devuelve: (nivel_riesgo, descripcion)
|
|
79
|
+
"""
|
|
80
|
+
descripcion = []
|
|
81
|
+
riesgo = "BAJO"
|
|
82
|
+
|
|
83
|
+
ip = datos_cliente.get("ip", "")
|
|
84
|
+
user_agent = datos_cliente.get("user_agent", "").lower()
|
|
85
|
+
ruta = datos_cliente.get("url", "")
|
|
86
|
+
|
|
87
|
+
# === Reglas simples ===
|
|
88
|
+
if not user_agent or "curl" in user_agent or "python" in user_agent:
|
|
89
|
+
descripcion.append("Agente de usuario anómalo (posible bot o script).")
|
|
90
|
+
riesgo = "MEDIO"
|
|
91
|
+
|
|
92
|
+
if "admin" in ruta or "etc/passwd" in ruta or "../" in ruta:
|
|
93
|
+
descripcion.append("Ruta sospechosa accedida.")
|
|
94
|
+
riesgo = "ALTO"
|
|
95
|
+
|
|
96
|
+
if "Desconocida" in ip or ip.startswith("192.168.") is False:
|
|
97
|
+
descripcion.append(f"IP externa detectada: {ip}")
|
|
98
|
+
riesgo = "MEDIO"
|
|
99
|
+
|
|
100
|
+
if not datos_cliente.get("url"):
|
|
101
|
+
descripcion.append("Petición sin parámetros ni cabeceras útiles.")
|
|
102
|
+
riesgo = "BAJO"
|
|
103
|
+
|
|
104
|
+
if not descripcion:
|
|
105
|
+
descripcion.append("Acceso normal detectado.")
|
|
106
|
+
|
|
107
|
+
return riesgo, " | ".join(descripcion)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
# =====================================================
|
|
111
|
+
# === FUNCIÓN PRINCIPAL DE REGISTRO ===
|
|
112
|
+
# =====================================================
|
|
113
|
+
def registrar_evento(request, tipo: str = "ACCESO", extra: dict | None = None):
|
|
114
|
+
"""
|
|
115
|
+
Registra un evento de auditoría detallado del cliente.
|
|
116
|
+
Incluye login exitoso, acceso normal y detección de ataques.
|
|
117
|
+
"""
|
|
118
|
+
try:
|
|
119
|
+
datos_cliente = obtener_datos_maquina(request)
|
|
120
|
+
severidad, descripcion = analizar_comportamiento_cliente(datos_cliente)
|
|
121
|
+
|
|
122
|
+
evento = {
|
|
123
|
+
"fecha": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
|
124
|
+
"tipo": tipo,
|
|
125
|
+
"descripcion": descripcion,
|
|
126
|
+
"severidad": severidad,
|
|
127
|
+
"cliente": datos_cliente,
|
|
128
|
+
"extra": extra or {},
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
# Crear carpeta solo si hay directorio en la ruta
|
|
132
|
+
log_dir = os.path.dirname(LOG_FILE)
|
|
133
|
+
if log_dir:
|
|
134
|
+
os.makedirs(log_dir, exist_ok=True)
|
|
135
|
+
|
|
136
|
+
# Registrar en archivo
|
|
137
|
+
with open(LOG_FILE, "a", encoding="utf-8") as f:
|
|
138
|
+
f.write(json.dumps(evento, ensure_ascii=False) + "\n")
|
|
139
|
+
|
|
140
|
+
# Log en consola para depuración local
|
|
141
|
+
print(f"[AUDITORÍA] Evento registrado: {evento['descripcion']} (nivel {severidad})")
|
|
142
|
+
|
|
143
|
+
except Exception as e:
|
|
144
|
+
print(f"[AUDITORÍA] Error al registrar evento: {e}")
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
# =====================================================
|
|
148
|
+
# === CONSULTA DE REGISTROS (opcional) ===
|
|
149
|
+
# =====================================================
|
|
150
|
+
def generar_reporte() -> str:
|
|
151
|
+
"""Devuelve todo el contenido del archivo de auditoría."""
|
|
152
|
+
if not os.path.exists(LOG_FILE):
|
|
153
|
+
return "No hay registros aún."
|
|
154
|
+
with open(LOG_FILE, "r", encoding="utf-8") as f:
|
|
155
|
+
return f.read()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GuardianUnivalle-Benito-Yucra
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.48
|
|
4
4
|
Summary: Middleware y detectores de seguridad (SQLi, XSS, CSRF, DoS, Keylogger) para Django/Flask
|
|
5
5
|
Author-email: Andres Benito Calle Yucra <benitoandrescalle035@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GuardianUnivalle-Benito-Yucra
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.48
|
|
4
4
|
Summary: Middleware y detectores de seguridad (SQLi, XSS, CSRF, DoS, Keylogger) para Django/Flask
|
|
5
5
|
Author-email: Andres Benito Calle Yucra <benitoandrescalle035@gmail.com>
|
|
6
6
|
License: MIT
|
{guardianunivalle_benito_yucra-0.1.46 → guardianunivalle_benito_yucra-0.1.48}/pyproject.toml
RENAMED
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "GuardianUnivalle-Benito-Yucra" # usar mayúsculas consistente
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.48"
|
|
8
8
|
description = "Middleware y detectores de seguridad (SQLi, XSS, CSRF, DoS, Keylogger) para Django/Flask"
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "Andres Benito Calle Yucra", email = "benitoandrescalle035@gmail.com" }
|
guardianunivalle_benito_yucra-0.1.46/GuardianUnivalle_Benito_Yucra/auditoria/registro_auditoria.py
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import datetime
|
|
3
|
-
import json
|
|
4
|
-
|
|
5
|
-
LOG_FILE = "auditoria_guardian.log"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def registrar_evento(
|
|
9
|
-
tipo: str,
|
|
10
|
-
descripcion: str = "",
|
|
11
|
-
severidad: str = "MEDIA",
|
|
12
|
-
extra: dict | None = None,
|
|
13
|
-
):
|
|
14
|
-
try:
|
|
15
|
-
evento = {
|
|
16
|
-
"fecha": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
|
17
|
-
"tipo": tipo,
|
|
18
|
-
"descripcion": descripcion,
|
|
19
|
-
"severidad": severidad,
|
|
20
|
-
"extra": extra or {},
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
# ✅ Crear carpeta solo si hay directorio en la ruta
|
|
24
|
-
log_dir = os.path.dirname(LOG_FILE)
|
|
25
|
-
if log_dir:
|
|
26
|
-
os.makedirs(log_dir, exist_ok=True)
|
|
27
|
-
|
|
28
|
-
with open(LOG_FILE, "a", encoding="utf-8") as f:
|
|
29
|
-
f.write(json.dumps(evento, ensure_ascii=False) + "\n")
|
|
30
|
-
|
|
31
|
-
except Exception as e:
|
|
32
|
-
print(f"[Auditoría] Error al registrar evento: {e}")
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def generar_reporte() -> str:
|
|
36
|
-
"""Devuelve todo el contenido del archivo de auditoría."""
|
|
37
|
-
if not os.path.exists(LOG_FILE):
|
|
38
|
-
return "No hay registros aún."
|
|
39
|
-
with open(LOG_FILE, "r", encoding="utf-8") as f:
|
|
40
|
-
return f.read()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|