GuardianUnivalle-Benito-Yucra 0.1.38__py3-none-any.whl → 0.1.40__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.
- GuardianUnivalle_Benito_Yucra/detectores/detector_sql.py +51 -111
- {guardianunivalle_benito_yucra-0.1.38.dist-info → guardianunivalle_benito_yucra-0.1.40.dist-info}/METADATA +1 -1
- {guardianunivalle_benito_yucra-0.1.38.dist-info → guardianunivalle_benito_yucra-0.1.40.dist-info}/RECORD +6 -6
- {guardianunivalle_benito_yucra-0.1.38.dist-info → guardianunivalle_benito_yucra-0.1.40.dist-info}/WHEEL +0 -0
- {guardianunivalle_benito_yucra-0.1.38.dist-info → guardianunivalle_benito_yucra-0.1.40.dist-info}/licenses/LICENSE +0 -0
- {guardianunivalle_benito_yucra-0.1.38.dist-info → guardianunivalle_benito_yucra-0.1.40.dist-info}/top_level.txt +0 -0
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
# sql_defense.py
|
|
2
|
-
|
|
2
|
+
# GuardianUnivalle_Benito_Yucra/detectores/detector_sql.py
|
|
3
|
+
|
|
3
4
|
import json
|
|
4
5
|
import logging
|
|
5
6
|
import re
|
|
6
|
-
from typing import List, Tuple
|
|
7
|
-
from django.conf import settings
|
|
8
7
|
from django.utils.deprecation import MiddlewareMixin
|
|
8
|
+
from django.conf import settings
|
|
9
9
|
|
|
10
|
-
# =====================================================
|
|
11
|
-
# === CONFIGURACIÓN DEL LOGGER ===
|
|
12
|
-
# =====================================================
|
|
13
10
|
logger = logging.getLogger("sqlidefense")
|
|
14
11
|
logger.setLevel(logging.INFO)
|
|
15
12
|
if not logger.handlers:
|
|
@@ -17,50 +14,34 @@ if not logger.handlers:
|
|
|
17
14
|
handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
|
|
18
15
|
logger.addHandler(handler)
|
|
19
16
|
|
|
20
|
-
|
|
21
17
|
# =====================================================
|
|
22
|
-
# === PATRONES DE
|
|
18
|
+
# === PATRONES DE ATAQUE SQL DEFINIDOS ===
|
|
23
19
|
# =====================================================
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
(re.compile(r"\
|
|
27
|
-
|
|
28
|
-
(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
),
|
|
32
|
-
# Comparaciones tautológicas (1=1)
|
|
33
|
-
(
|
|
34
|
-
re.compile(r"\b(or|and)\s+\d+\s*=\s*\d+", re.I),
|
|
35
|
-
"Expresión tautológica OR/AND 1=1",
|
|
36
|
-
),
|
|
37
|
-
# Manipulación de tablas
|
|
38
|
-
(
|
|
39
|
-
re.compile(r"\b(drop|truncate|delete|insert|update)\b", re.I),
|
|
40
|
-
"Comando de manipulación de tabla",
|
|
41
|
-
),
|
|
42
|
-
# Comentarios sospechosos o terminadores
|
|
43
|
-
(re.compile(r"(--|#|;)", re.I), "Comentario o terminador sospechoso"),
|
|
44
|
-
# Ejecución directa de procedimientos
|
|
45
|
-
(re.compile(r"exec\s*\(", re.I), "Ejecución de procedimiento almacenado"),
|
|
46
|
-
# Subconsultas y SELECT anidados sospechosos
|
|
47
|
-
(re.compile(r"\(\s*select\b.*\)", re.I), "Subconsulta sospechosa"),
|
|
20
|
+
SQL_PATTERNS = [
|
|
21
|
+
(re.compile(r"\bunion\b\s+(all\s+)?\bselect\b", re.I), "Uso de UNION SELECT", 0.7),
|
|
22
|
+
(re.compile(r"\bor\b\s+'?\d+'?\s*=\s*'?\d+'?", re.I), "Tautología OR 1=1", 0.6),
|
|
23
|
+
(re.compile(r"\bselect\b.+\bfrom\b", re.I), "Consulta SQL SELECT-FROM", 0.5),
|
|
24
|
+
(re.compile(r"(--|#|/\*|\*/)", re.I), "Comentario SQL sospechoso", 0.4),
|
|
25
|
+
(re.compile(r"\b(drop|truncate|delete|insert|update)\b", re.I), "Manipulación SQL", 0.5),
|
|
26
|
+
(re.compile(r"exec\s*\(", re.I), "Ejecución de procedimiento almacenado", 0.6),
|
|
48
27
|
]
|
|
49
28
|
|
|
29
|
+
IGNORED_FIELDS = ["password", "csrfmiddlewaretoken", "token", "auth"]
|
|
50
30
|
|
|
51
|
-
# =====================================================
|
|
52
|
-
# === FUNCIONES AUXILIARES SQLi ===
|
|
53
|
-
# =====================================================
|
|
54
|
-
def extract_payload_text(request) -> str:
|
|
55
|
-
"""
|
|
56
|
-
Extrae texto de interés desde el cuerpo, querystring,
|
|
57
|
-
encabezados y referencias para analizar posible SQLi.
|
|
58
|
-
"""
|
|
59
|
-
parts: List[str] = []
|
|
60
31
|
|
|
32
|
+
def get_client_ip(request):
|
|
33
|
+
"""Obtiene la IP real del cliente."""
|
|
34
|
+
x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR")
|
|
35
|
+
if x_forwarded_for:
|
|
36
|
+
return x_forwarded_for.split(",")[0].strip()
|
|
37
|
+
return request.META.get("REMOTE_ADDR", "")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def extract_payload(request):
|
|
41
|
+
"""Extrae datos útiles de la solicitud para análisis."""
|
|
42
|
+
parts = []
|
|
61
43
|
try:
|
|
62
|
-
|
|
63
|
-
if "application/json" in content_type:
|
|
44
|
+
if "application/json" in request.META.get("CONTENT_TYPE", ""):
|
|
64
45
|
data = json.loads(request.body.decode("utf-8") or "{}")
|
|
65
46
|
parts.append(json.dumps(data))
|
|
66
47
|
else:
|
|
@@ -74,94 +55,53 @@ def extract_payload_text(request) -> str:
|
|
|
74
55
|
if qs:
|
|
75
56
|
parts.append(qs)
|
|
76
57
|
|
|
77
|
-
|
|
78
|
-
parts.append(request.META.get("HTTP_REFERER", ""))
|
|
79
|
-
|
|
80
|
-
return " ".join([p for p in parts if p])
|
|
58
|
+
return " ".join(parts)
|
|
81
59
|
|
|
82
60
|
|
|
83
|
-
def
|
|
84
|
-
"""
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
61
|
+
def detect_sql_injection(value):
|
|
62
|
+
"""Detecta patrones sospechosos en una cadena."""
|
|
63
|
+
score = 0.0
|
|
64
|
+
descripciones = []
|
|
65
|
+
for pattern, desc, weight in SQL_PATTERNS:
|
|
66
|
+
if pattern.search(value):
|
|
67
|
+
score += weight
|
|
68
|
+
descripciones.append(desc)
|
|
69
|
+
return score, descripciones
|
|
89
70
|
|
|
90
|
-
for patt, msg in SQLI_PATTERNS:
|
|
91
|
-
if patt.search(text):
|
|
92
|
-
descripcion.append(msg)
|
|
93
|
-
|
|
94
|
-
return (len(descripcion) > 0, descripcion)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def get_client_ip(request) -> str:
|
|
98
|
-
"""
|
|
99
|
-
Obtiene la IP real del cliente considerando X-Forwarded-For.
|
|
100
|
-
"""
|
|
101
|
-
x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR")
|
|
102
|
-
if x_forwarded_for:
|
|
103
|
-
return x_forwarded_for.split(",")[0].strip()
|
|
104
|
-
return request.META.get("REMOTE_ADDR", "")
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
# =====================================================
|
|
108
|
-
# === MIDDLEWARE DE DEFENSA SQLi ===
|
|
109
|
-
# =====================================================
|
|
110
71
|
class SQLIDefenseMiddleware(MiddlewareMixin):
|
|
111
|
-
"""
|
|
112
|
-
Middleware profesional de detección de inyección SQL.
|
|
113
|
-
- Detecta patrones en parámetros, cuerpo y cabeceras.
|
|
114
|
-
- No bloquea directamente; marca el intento para auditoría.
|
|
115
|
-
"""
|
|
72
|
+
"""Middleware de detección SQL Injection."""
|
|
116
73
|
|
|
117
74
|
def process_request(self, request):
|
|
118
|
-
# ---------------------------------------------
|
|
119
|
-
# 1. Filtrar IPs confiables
|
|
120
|
-
# ---------------------------------------------
|
|
121
75
|
client_ip = get_client_ip(request)
|
|
122
|
-
trusted_ips
|
|
76
|
+
trusted_ips = getattr(settings, "SQLI_DEFENSE_TRUSTED_IPS", [])
|
|
77
|
+
trusted_urls = getattr(settings, "SQLI_DEFENSE_TRUSTED_URLS", [])
|
|
78
|
+
|
|
79
|
+
# Ignorar si la IP es confiable
|
|
123
80
|
if client_ip in trusted_ips:
|
|
124
81
|
return None
|
|
125
82
|
|
|
126
|
-
#
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if not payload:
|
|
83
|
+
# Ignorar si la URL de referencia (Referer) o Host está en la lista de URLs confiables
|
|
84
|
+
referer = request.META.get("HTTP_REFERER", "")
|
|
85
|
+
host = request.get_host()
|
|
86
|
+
if any(url in referer for url in trusted_urls) or any(url in host for url in trusted_urls):
|
|
131
87
|
return None
|
|
132
88
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
# ---------------------------------------------
|
|
136
|
-
flagged, descripcion = detect_sql_attack(payload)
|
|
137
|
-
if not flagged:
|
|
138
|
-
return None
|
|
89
|
+
payload = extract_payload(request)
|
|
90
|
+
score, descripciones = detect_sql_injection(payload)
|
|
139
91
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
# ---------------------------------------------
|
|
143
|
-
w_sqli = getattr(settings, "SQLI_DEFENSE_WEIGHT", 0.4)
|
|
144
|
-
detecciones_sqli = len(descripcion)
|
|
145
|
-
s_sqli = w_sqli * detecciones_sqli
|
|
92
|
+
if score == 0:
|
|
93
|
+
return None
|
|
146
94
|
|
|
147
|
-
# ---------------------------------------------
|
|
148
|
-
# 5. Registrar e informar el intento
|
|
149
|
-
# ---------------------------------------------
|
|
150
95
|
logger.warning(
|
|
151
|
-
"
|
|
152
|
-
client_ip,
|
|
153
|
-
descripcion,
|
|
154
|
-
payload,
|
|
155
|
-
s_sqli,
|
|
96
|
+
f"[SQLiDetect] IP={client_ip} Score={score:.2f} Desc={descripciones} Payload={payload[:200]}"
|
|
156
97
|
)
|
|
157
98
|
|
|
158
|
-
# Marcar información del ataque para el sistema de auditoría
|
|
159
99
|
request.sql_attack_info = {
|
|
160
100
|
"ip": client_ip,
|
|
161
101
|
"tipos": ["SQLi"],
|
|
162
|
-
"descripcion":
|
|
163
|
-
"payload": payload,
|
|
164
|
-
"score":
|
|
102
|
+
"descripcion": descripciones,
|
|
103
|
+
"payload": payload[:500],
|
|
104
|
+
"score": round(score, 2),
|
|
165
105
|
}
|
|
166
106
|
|
|
167
107
|
return None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GuardianUnivalle-Benito-Yucra
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.40
|
|
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
|
|
@@ -7,14 +7,14 @@ GuardianUnivalle_Benito_Yucra/criptografia/kdf.py,sha256=_sbepEY1qHEKga0ExrX2WRg
|
|
|
7
7
|
GuardianUnivalle_Benito_Yucra/detectores/detector_csrf.py,sha256=wt9LRMG9XK4eSSmW91tlGmsJWfyk445b8-n2oxlXlwo,7893
|
|
8
8
|
GuardianUnivalle_Benito_Yucra/detectores/detector_dos.py,sha256=l_JYCmRYpsXt1ZauNPF_wy5uGJhmunRbtJ_WKpC3Otc,6953
|
|
9
9
|
GuardianUnivalle_Benito_Yucra/detectores/detector_keylogger.py,sha256=L5RQ0Sdgg7hTU1qkZYwt7AcDqtAzT6u-jwBGo7YWfsw,8078
|
|
10
|
-
GuardianUnivalle_Benito_Yucra/detectores/detector_sql.py,sha256=
|
|
10
|
+
GuardianUnivalle_Benito_Yucra/detectores/detector_sql.py,sha256=hdiRuIJy5Dg4Gq8PP7UmsA4eRzIF-J02HFRLCtGLyY8,4391
|
|
11
11
|
GuardianUnivalle_Benito_Yucra/detectores/detector_xss.py,sha256=Ipw1XXBd1-SsOOhhl9joQGduTq0GhSa61TRTyASF3XE,6795
|
|
12
12
|
GuardianUnivalle_Benito_Yucra/middleware_web/middleware_web.py,sha256=23pLLYqliUoMrIC6ZEwz3hKXeDjWfHSm9vYPWGmDDik,495
|
|
13
13
|
GuardianUnivalle_Benito_Yucra/mitigacion/limitador_peticion.py,sha256=ipMOebYhql-6mSyHs0ddYXOcXq9w8P_IXLlpiIqGncw,246
|
|
14
14
|
GuardianUnivalle_Benito_Yucra/mitigacion/lista_bloqueo.py,sha256=6AYWII4mrmwCLHCvGTyoBxR4Oasr4raSHpFbVjqn7d8,193
|
|
15
15
|
GuardianUnivalle_Benito_Yucra/puntuacion/puntuacion_amenaza.py,sha256=Wx5XfcII4oweLvZsTBEJ7kUc9pMpP5-36RfI5C5KJXo,561
|
|
16
|
-
guardianunivalle_benito_yucra-0.1.
|
|
17
|
-
guardianunivalle_benito_yucra-0.1.
|
|
18
|
-
guardianunivalle_benito_yucra-0.1.
|
|
19
|
-
guardianunivalle_benito_yucra-0.1.
|
|
20
|
-
guardianunivalle_benito_yucra-0.1.
|
|
16
|
+
guardianunivalle_benito_yucra-0.1.40.dist-info/licenses/LICENSE,sha256=5e4IdL542v1E8Ft0A24GZjrxZeTsVK7XrS3mZEUhPtM,37
|
|
17
|
+
guardianunivalle_benito_yucra-0.1.40.dist-info/METADATA,sha256=ue2VCRiG_RztWsCO7HprHZegV6iwBeOVDJDnT-mm844,1893
|
|
18
|
+
guardianunivalle_benito_yucra-0.1.40.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
19
|
+
guardianunivalle_benito_yucra-0.1.40.dist-info/top_level.txt,sha256=HTWfZM64WAV_QYr5cnXnLuabQt92dvlxqlR3pCwpbDQ,30
|
|
20
|
+
guardianunivalle_benito_yucra-0.1.40.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|