GuardianUnivalle-Benito-Yucra 0.1.60__py3-none-any.whl → 0.1.62__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.

@@ -6,7 +6,13 @@ import logging
6
6
  import re
7
7
  from django.utils.deprecation import MiddlewareMixin
8
8
  from django.conf import settings
9
+ import urllib.parse
10
+ import html
11
+ from typing import List, Tuple, Dict
9
12
 
13
+ # ----------------------------
14
+ # Configuración del logger
15
+ # ----------------------------
10
16
  logger = logging.getLogger("sqlidefense")
11
17
  logger.setLevel(logging.INFO)
12
18
  if not logger.handlers:
@@ -15,47 +21,112 @@ if not logger.handlers:
15
21
  logger.addHandler(handler)
16
22
 
17
23
  # =====================================================
18
- # ===        PATRONES DE ATAQUE SQL DEFINIDOS       ===
24
+ # === PATRONES DE ATAQUE SQL DEFINIDOS ===
19
25
  # =====================================================
20
- SQL_PATTERNS = [
21
- # Patrones de Extracción de Datos y Evasión (Alto Peso)
22
- (re.compile(r"\bunion\b\s+(all\s+)?\bselect\b", re.I), "Uso de UNION SELECT", 0.7),
23
- (re.compile(r"\bor\b\s+['\"]?\d+['\"]?\s*=\s*['\"]?\d+['\"]?", re.I), "Tautología OR X=X", 0.6), # Mejorado
24
- (re.compile(r"\b(sleep|benchmark|waitfor\s+delay)\b\s*\(", re.I), "Función de Tiempo (SQL Ciega)", 0.8), # Muy peligroso
25
- (re.compile(r"\b(extractvalue|updatexml|convert)\b\s*\(", re.I), "Extracción Basada en Errores/Funciones", 0.75),
26
-
27
- # Patrones de Control y Destrucción (Peso Medio)
28
- (re.compile(r"\b(drop\s+table|truncate\s+table|delete\s+from|insert\s+into|update\s+set)\b", re.I), "Manipulación DML/DDL", 0.5),
29
- (re.compile(r"\b(exec|execute|xp_cmdshell)\b", re.I), "Ejecución de Comando (OS o Stored Proc)", 0.6),
30
- (re.compile(r";\s*(select|drop|insert|update)\b", re.I), "Apilamiento de Consultas (Separador ;)", 0.55), # Nuevo
31
-
32
- # Patrones de Detección e Información (Bajo Peso)
33
- (re.compile(r"(--|#|/\*|;)", re.I), "Comentario SQL o Separador de Consulta", 0.4),
34
- (re.compile(r"\b(substring|substr|mid)\b\s*\(", re.I), "Función de Cadena (SQL Ciega Booleana)", 0.45), # Nuevo
35
- (re.compile(r"\b(select)\b.+\b(from|where)\b", re.I), "Estructura SELECT-FROM-WHERE", 0.4), # Más específico
26
+ SQL_PATTERNS: List[Tuple[re.Pattern, str, float]] = [
27
+ # ------------------ In‑Band / Exfiltration (muy alto) ------------------
28
+ (re.compile(r"\bunion\b\s+(all\s+)?\bselect\b", re.I), "UNION SELECT (exfiltración)", 0.95),
29
+ (re.compile(r"\bselect\b\s+.*\bfrom\b\s+.+\bwhere\b", re.I | re.S), "SELECT ... FROM ... WHERE (consulta completa)", 0.7),
30
+ (re.compile(r"\binto\s+outfile\b|\binto\s+dumpfile\b", re.I), "INTO OUTFILE / INTO DUMPFILE (volcado a fichero)", 0.98),
31
+ (re.compile(r"\bload_file\s*\(", re.I), "LOAD_FILE() (lectura fichero MySQL)", 0.95),
32
+ (re.compile(r"\b(pg_read_file|pg_read_binary_file|pg_ls_dir)\s*\(", re.I), "pg_read_file / funciones lectura Postgres", 0.95),
33
+ (re.compile(r"\bfile_read\b|\bfile_get_contents\b", re.I), "Indicadores de lectura de fichero en código", 0.85),
34
+
35
+ # ------------------ Time‑based / Blind (muy alto) ------------------
36
+ (re.compile(r"\b(sleep|benchmark|pg_sleep|dbms_lock\.sleep|waitfor\s+delay)\b\s*\(", re.I), "SLEEP/pg_sleep/WAITFOR DELAY (time‑based blind)", 0.98),
37
+ (re.compile(r"\bbenchmark\s*\(", re.I), "BENCHMARK() MySQL (time/DoS)", 0.9),
38
+
39
+ # ------------------ Error‑based extraction (muy alto) ------------------
40
+ (re.compile(r"\b(updatexml|extractvalue|xmltype|utl_http\.request|dbms_xmlquery)\b\s*\(", re.I), "Funciones que devuelven errores con contenido (error‑based)", 0.95),
41
+ (re.compile(r"\bconvert\(\s*.*\s+using\s+.*\)", re.I), "CONVERT ... USING (encoding conversions potenciales)", 0.7),
42
+
43
+ # ------------------ OOB / Callbacks / Exfiltration (muy alto) ------------------
44
+ (re.compile(r"\b(nslookup|dnslookup|xp_dirtree|xp_dirtree\(|xp_regread|xp\w+)\b", re.I),
45
+ "Funciones/procs que pueden generar exfiltración OOB (DNS/SMB/SMB callbacks)", 0.95),
46
+ (re.compile(r"\b(utl_http\.request|utl_tcp\.socket|http_client|apex_web_service\.make_rest_request)\b", re.I),
47
+ "UTL_HTTP/HTTP callbacks (Oracle/PLSQL HTTP OOB)", 0.95),
48
+
49
+ # ------------------ Execution / OS commands (muy alto) ------------------
50
+ (re.compile(r"\bxp_cmdshell\b|\bexec\s+xp\w+|\bsp_oacreate\b", re.I), "xp_cmdshell / sp_oacreate (ejecución OS MSSQL/Oracle)", 0.98),
51
+ (re.compile(r"\b(exec\s+master\..*xp\w+|sp_executesql|execute\s+immediate|EXEC\s+UTE)\b", re.I), "Ejecución dinámica / sp_executesql / EXECUTE IMMEDIATE", 0.95),
52
+
53
+ # ------------------ Metadata / Recon (alto) ------------------
54
+ (re.compile(r"\binformation_schema\b", re.I), "INFORMATION_SCHEMA (recon meta‑datos)", 0.92),
55
+ (re.compile(r"\b(information_schema\.tables|information_schema\.columns)\b", re.I), "INFORMATION_SCHEMA.tables/columns", 0.92),
56
+ (re.compile(r"\b(sys\.tables|sys\.objects|sys\.databases|pg_catalog|pg_tables|pg_user)\b", re.I), "Catálogos del sistema (MSSQL/Postgres)", 0.9),
57
+
58
+ # ------------------ DML/DDL Destructivo (alto) ------------------
59
+ (re.compile(r"\b(drop\s+table|truncate\s+table|drop\s+database|drop\s+schema)\b", re.I), "DROP/TRUNCATE (DDL destructivo)", 0.95),
60
+ (re.compile(r"\b(delete\s+from|update\s+.+\s+set|insert\s+into)\b", re.I), "DML (DELETE/UPDATE/INSERT potencialmente destructivo)", 0.85),
61
+
62
+ # ------------------ Stacked queries (medio‑alto) ------------------
63
+ (re.compile(r";\s*(select|insert|update|delete|drop|create|truncate)\b", re.I), "Stacked queries (uso de ';' para apilar)", 0.88),
64
+
65
+ # ------------------ Tautologías / Boolean Blind (medio‑alto) ------------------
66
+ (re.compile(r"\b(or|and)\b\s+(['\"]?\d+['\"]?)\s*=\s*\1", re.I), "Tautología OR/AND 'x'='x' o 1=1", 0.85),
67
+ (re.compile(r"(['\"]).{0,10}\1\s*or\s*['\"][^']*['\"]\s*=\s*['\"][^']*['\"]", re.I), "Tautología clásica en cadenas (OR '1'='1')", 0.8),
68
+
69
+ # ------------------ Blind‑boolean extraction functions (medio) ------------------
70
+ (re.compile(r"\b(substring|substr|mid|left|right)\b\s*\(", re.I), "SUBSTRING/SUBSTR/LEFT/RIGHT (blind extraction)", 0.82),
71
+ (re.compile(r"\b(ascii|char|chr|nchr)\b\s*\(", re.I), "ASCII/CHAR/CHR (byte/char extraction)", 0.8),
72
+
73
+ # ------------------ Error / XPATH / XML (alto) ------------------
74
+ (re.compile(r"\b(updatexml|extractvalue|xmltype|xmlelement)\b\s*\(", re.I), "updatexml/extractvalue/xmltype (error/XPath leaks)", 0.93),
75
+
76
+ # ------------------ File system / I/O (alto) ------------------
77
+ (re.compile(r"\binto\s+outfile\b|\binto\s+dumpfile\b", re.I), "INTO OUTFILE / DUMPFILE (escritura en servidor)", 0.97),
78
+ (re.compile(r"\bopenrowset\b|\bbulk\s+insert\b|\bcopy\s+to\b", re.I), "OPENROWSET / BULK INSERT / COPY TO (exportación)", 0.92),
79
+
80
+ # ------------------ Encoding / Obfuscation (medio) ------------------
81
+ (re.compile(r"0x[0-9a-fA-F]+", re.I), "Hex literal (0x...) (ofuscación)", 0.6),
82
+ (re.compile(r"\\x[0-9a-fA-F]{2}", re.I), "Escapes hex tipo \\xNN (ofuscación)", 0.6),
83
+ (re.compile(r"&#x[0-9a-fA-F]+;|&#\d+;", re.I), "Entidades HTML / entidades numéricas (ofuscación)", 0.6),
84
+ (re.compile(r"\bchar\s*\(\s*\d+\s*\)", re.I), "CHAR(n) usado para construir cadenas (ofuscación)", 0.65),
85
+ (re.compile(r"\bconcat\(", re.I), "CONCAT() (construcción dinámica de strings)", 0.6),
86
+
87
+ # ------------------ SQL in attributes / URL encoded (medio) ------------------
88
+ (re.compile(r"%3[dD]|%27|%22|%3C|%3E|%3B", re.I), "URL encoding típico (%27, %3C, etc.)", 0.4),
89
+
90
+ # ------------------ Comments / terminators (informativo) ------------------
91
+ (re.compile(r"(--\s|#\s|/\*[\s\S]*\*/)", re.I), "Comentarios SQL (--) o /* */ o #", 0.45),
92
+
93
+ # ------------------ ORM / NonSQL indicators (informativo) ------------------
94
+ (re.compile(r"\b\$where\b|\b\$ne\b|\b\$regex\b", re.I), "NoSQL / MongoDB indicators ($where/$ne/$regex)", 0.5),
95
+
96
+ # ------------------ Tool fingerprints (informativo) ------------------
97
+ (re.compile(r"sqlmap", re.I), "Indicador de herramienta sqlmap en payload", 0.5),
98
+ (re.compile(r"hydra|nmap|nikto", re.I), "Indicador de herramientas de auditoría/scan", 0.3),
99
+
100
+ # ------------------ Misc risky tokens (informativo) ------------------
101
+ (re.compile(r"\bexecute\b\s*\(", re.I), "execute(...) (ejecución dinámica)", 0.7),
102
+ (re.compile(r"\bdeclare\b\s+@?\w+", re.I), "DECLARE variable (MSSQL/PLSQL declarations)", 0.7),
103
+
104
+ # ------------------ Low‑level heuristics (bajo) ------------------
105
+ (re.compile(r"\bselect\b\s+.*\bfrom\b", re.I), "Estructura SELECT FROM (heurístico)", 0.25),
106
+ (re.compile(r"\binsert\b\s+into\b", re.I), "INSERT INTO (heurístico)", 0.3),
107
+
108
+ # ------------------ Catch‑all aggressive patterns (usar con cuidado) ------------------
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
+ (re.compile(r"\b(or)\b\s+1\s*=\s*1\b", re.I), "OR 1=1 tautology", 0.85),
36
111
  ]
37
112
 
38
113
  IGNORED_FIELDS = ["password", "csrfmiddlewaretoken", "token", "auth"]
39
114
 
40
-
115
+ # ----------------------------
116
+ # Obtener IP real del cliente
117
+ # ----------------------------
41
118
  def get_client_ip(request):
42
- """
43
- Obtiene la IP real del cliente.
44
- Primero revisa 'X-Forwarded-For', luego 'REMOTE_ADDR'.
45
- """
46
119
  x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR")
47
120
  if x_forwarded_for:
48
- # Render y otros proxies envían múltiples IPs separados por coma
49
121
  ips = [ip.strip() for ip in x_forwarded_for.split(",") if ip.strip()]
50
122
  if ips:
51
- return ips[0] # la primera IP es la IP real del cliente
52
- # Si no hay X-Forwarded-For, tomar REMOTE_ADDR
123
+ return ips[0]
53
124
  return request.META.get("REMOTE_ADDR", "")
54
125
 
55
-
56
-
126
+ # ----------------------------
127
+ # Extraer payload de la solicitud
128
+ # ----------------------------
57
129
  def extract_payload(request):
58
- """Extrae datos útiles de la solicitud para análisis."""
59
130
  parts = []
60
131
  try:
61
132
  if "application/json" in request.META.get("CONTENT_TYPE", ""):
@@ -74,20 +145,56 @@ def extract_payload(request):
74
145
 
75
146
  return " ".join(parts)
76
147
 
77
-
78
- def detect_sql_injection(value):
79
- """Detecta patrones sospechosos en una cadena."""
148
+ # ----------------------------
149
+ # Normalización / preprocesamiento
150
+ # ----------------------------
151
+ def normalize_input(s: str) -> str:
152
+ if not s:
153
+ return ""
154
+ try:
155
+ s_dec = urllib.parse.unquote_plus(s)
156
+ except Exception:
157
+ s_dec = s
158
+ try:
159
+ s_dec = html.unescape(s_dec)
160
+ except Exception:
161
+ pass
162
+ # Reemplazo seguro de secuencias \xNN
163
+ s_dec = re.sub(r"\\x([0-9a-fA-F]{2})", r"\\x\g<1>", s_dec)
164
+ s_dec = re.sub(r"\s+", " ", s_dec)
165
+ return s_dec.strip()
166
+
167
+ # ----------------------------
168
+ # Detector SQLi
169
+ # ----------------------------
170
+ def detect_sql_injection(text: str) -> Dict:
171
+ norm = normalize_input(text or "")
80
172
  score = 0.0
81
- descripciones = []
173
+ matches = []
174
+ descriptions = []
82
175
  for pattern, desc, weight in SQL_PATTERNS:
83
- if pattern.search(value):
176
+ if pattern.search(norm):
84
177
  score += weight
85
- descripciones.append(desc)
86
- return score, descripciones
87
-
178
+ matches.append((desc, pattern.pattern, weight))
179
+ descriptions.append(desc)
180
+
181
+ return {
182
+ "score": round(score, 3),
183
+ "matches": matches,
184
+ "descriptions": list(dict.fromkeys(descriptions)),
185
+ "sample": norm[:1200],
186
+ }
187
+
188
+ DEFAULT_THRESHOLDS = {
189
+ "HIGH": 1.8,
190
+ "MEDIUM": 1.0,
191
+ "LOW": 0.5,
192
+ }
193
+
194
+ # ----------------------------
195
+ # Middleware SQLi
196
+ # ----------------------------
88
197
  class SQLIDefenseMiddleware(MiddlewareMixin):
89
- """Middleware de detección SQL Injection."""
90
-
91
198
  def process_request(self, request):
92
199
  client_ip = get_client_ip(request)
93
200
  trusted_ips = getattr(settings, "SQLI_DEFENSE_TRUSTED_IPS", [])
@@ -102,35 +209,35 @@ class SQLIDefenseMiddleware(MiddlewareMixin):
102
209
  return None
103
210
 
104
211
  payload = extract_payload(request)
105
- score, descripciones = detect_sql_injection(payload)
212
+ result = detect_sql_injection(payload)
213
+ score = result["score"]
214
+ descripciones = result["descriptions"]
106
215
 
107
216
  if score == 0:
108
217
  return None
109
218
 
110
- # Registrar ataque completo
219
+ # Registrar ataque
111
220
  logger.warning(
112
221
  f"[SQLiDetect] IP={client_ip} Host={host} Referer={referer} "
113
222
  f"Score={score:.2f} Desc={descripciones} Payload={payload[:500]}"
114
223
  )
115
224
 
116
- # Guardar información del ataque en el request
225
+ # Guardar info en request
117
226
  request.sql_attack_info = {
118
227
  "ip": client_ip,
119
228
  "tipos": ["SQLi"],
120
229
  "descripcion": descripciones,
121
- "payload": payload[:1000], # guardar hasta 1000 caracteres
230
+ "payload": payload[:1000],
122
231
  "score": round(score, 2),
123
- "url": request.build_absolute_uri(), # registrar URL completa
232
+ "url": request.build_absolute_uri(),
124
233
  }
125
234
 
126
235
  return None
127
236
 
128
-
129
-
130
237
  # =====================================================
131
238
  # === INFORMACIÓN EXTRA ===
132
239
  # =====================================================
133
- """
240
+ r"""
134
241
  Algoritmos relacionados:
135
242
  - Se recomienda almacenar logs SQLi cifrados (AES-GCM)
136
243
  para proteger evidencia de intentos maliciosos.
@@ -33,17 +33,67 @@ except Exception:
33
33
  # - pesos mayores = más severo (por ejemplo <script> o javascript:)
34
34
  # - esto permite un scoring acumulativo y menos falsos positivos
35
35
  # -------------------------------------------------
36
+
36
37
  XSS_PATTERNS: List[Tuple[re.Pattern, str, float]] = [
37
- (re.compile(r"<\s*script\b", re.I), "Etiqueta <script>", 0.8),
38
- (re.compile(r"javascript\s*:", re.I), "URI javascript:", 0.7),
39
- (re.compile(r"<\s*iframe\b", re.I), "Etiqueta <iframe>", 0.7),
40
- (re.compile(r"<\s*embed\b", re.I), "Etiqueta <embed>", 0.7),
41
- (re.compile(r"<\s*object\b", re.I), "Etiqueta <object>", 0.7),
42
- (re.compile(r"on\w+\s*=", re.I), "Atributo de evento (on*)", 0.5),
43
- (re.compile(r"document\.cookie", re.I), "Acceso a document.cookie", 0.6),
44
- (re.compile(r"alert\s*\(", re.I), "Uso de alert() potencial", 0.4),
45
- # patrón para imágenes con onerror u onload (caso común)
46
- (re.compile(r"<\s*img\b[^>]*on\w+\s*=", re.I), "Imagen con evento on*", 0.6),
38
+ # ---------- Máxima severidad / ejecución directa ----------
39
+ (re.compile(r"<\s*script\b", re.I), "Etiqueta <script> (directa)", 0.95),
40
+ (re.compile(r"<\s*s\s*c\s*r\s*i\s*p\s*t\b", re.I), "Etiqueta <script> ofuscada", 0.90),
41
+ (re.compile(r"\b(document\.cookie|document\.write|document\.location|location\.href|window\.location)\b", re.I),
42
+ "Acceso a document / location (cookie/location/write)", 0.90),
43
+ (re.compile(r"\b(eval|setTimeout|setInterval|Function|new Function)\s*\(", re.I),
44
+ "Ejecución dinámica (eval/Function/setTimeout)", 0.88),
45
+
46
+ # ---------- URIs peligrosas ----------
47
+ (re.compile(r"\bjavascript\s*:", re.I), "URI javascript:", 0.85),
48
+ (re.compile(r"\bdata\s*:\s*text\/html\b", re.I), "URI data:text/html", 0.82),
49
+ (re.compile(r"\bdata\s*:\s*text\/html;base64\b", re.I), "URI data:text/html;base64", 0.82),
50
+ (re.compile(r"\bvbscript\s*:", re.I), "URI vbscript:", 0.7),
51
+
52
+ # ---------- Etiquetas y vectores alternativos ----------
53
+ (re.compile(r"<\s*(iframe|embed|object|svg|math|meta)\b", re.I), "IFrame/Embed/Object/SVG/Meta", 0.88),
54
+ (re.compile(r"<\s*img\b[^>]*\bonerror\b", re.I), "<img ... onerror>", 0.86),
55
+ (re.compile(r"<\s*svg\b[^>]*\bonload\b", re.I), "SVG con onload/on* (SVG vector)", 0.84),
56
+
57
+ # ---------- Atributos de evento (on*) ----------
58
+ (re.compile(r"\s+on[a-zA-Z]+\s*=", re.I), "Atributo de evento (on*)", 0.80),
59
+ (re.compile(r"<\s*(a|img|body|div|span|form|input|button)\b[^>]*on[a-zA-Z]+\s*=", re.I),
60
+ "Elemento con evento on* (a,img,body,...)", 0.82),
61
+
62
+ # ---------- Inyección en contextos JS / JSON / script ----------
63
+ (re.compile(r"<\s*script[^>]*>.*?</\s*script\s*>", re.I | re.S), "Script inline completo", 0.92),
64
+ (re.compile(r"'\s*;\s*alert\s*\(|\"\s*;\s*alert\s*\(", re.I), "Inyección en cadenas JS (breakout + alert)", 0.78),
65
+ (re.compile(r"\bJSON\.parse\(|\beval\(\s*JSON", re.I), "JSON parse/eval inseguro", 0.75),
66
+
67
+ # ---------- Encodings, entidades y mutaciones ----------
68
+ (re.compile(r"&#x[0-9a-fA-F]+;|&#\d+;", re.I), "Entidades HTML / encoding (posible bypass)", 0.70),
69
+ (re.compile(r"%3C\s*script|%3Cscript%3E", re.I), "Tags URL-encoded (%3Cscript)", 0.68),
70
+ (re.compile(r"(?:\\x3C|\\u003C)\s*script", re.I), "Escapes JS/Unicode que forman <script>", 0.68),
71
+
72
+ # ---------- DOM clobbering / nombres reservados ----------
73
+ (re.compile(r'\bid\s*=\s*"(?:form|image|submit|action|location|name)"', re.I), "IDs que causan DOM clobbering", 0.65),
74
+ (re.compile(r'\bname\s*=\s*"(?:form|submit|action|location)"', re.I), "Names que pueden clobber", 0.65),
75
+
76
+ # ---------- Atributos URI en tags (href/src) ----------
77
+ (re.compile(r'<\s*a\b[^>]*\bhref\s*=\s*[\'"]\s*javascript\s*:', re.I), "<a href=\"javascript:...\">", 0.84),
78
+ (re.compile(r'<\s*(img|script|iframe)\b[^>]*\bsrc\s*=\s*[\'"]\s*javascript\s*:', re.I),
79
+ "src=javascript: en tags", 0.84),
80
+
81
+ # ---------- Vectores en CSS / style ----------
82
+ (re.compile(r"\bstyle\s*=\s*[\"'][^\"']*(expression\s*\(|url\s*\(\s*javascript:)", re.I), "Estilo con expression() o url(javascript:)", 0.66),
83
+ (re.compile(r"@import\s+url\s*\(", re.I), "CSS @import posibles vectores", 0.45),
84
+
85
+ # ---------- Comentarios y CDATA para evasión ----------
86
+ (re.compile(r"<!\[CDATA\[|\/\/\s*<\s*!\s*\[CDATA\[", re.I), "CDATA o comentarios para evasión", 0.48),
87
+ (re.compile(r"<!--|-->", re.I), "Comentarios HTML (posible ofuscación/evitación)", 0.30),
88
+
89
+ # ---------- Polyglot / mutation / browser quirks ----------
90
+ (re.compile(r"(?:<\s*svg[^>]*>.*?<\s*/\s*svg\s*>)|(?:<\s*math[^>]*>)", re.I | re.S),
91
+ "SVG/MathML polyglot (vectores mutables)", 0.75),
92
+ (re.compile(r"(?:\balert\s*\(|\bconsole\.log\s*\()", re.I), "Indicadores de prueba (alert/console.log)", 0.40),
93
+
94
+ # ---------- Heurísticos de baja severidad (informativo) ----------
95
+ (re.compile(r"<\s*form\b", re.I), "Form (posible vector de ataque relacionado)", 0.25),
96
+ (re.compile(r"(onmouseover|onfocus|onmouseenter|onmouseleave)\b", re.I), "Eventos UI (mouseover/focus)", 0.45),
47
97
  ]
48
98
 
49
99
  # -------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GuardianUnivalle-Benito-Yucra
3
- Version: 0.1.60
3
+ Version: 0.1.62
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=q7-UsVseTtIYZz4bbpx2X0kzpDmu2Cetm7eYPJtsruA,7608
8
8
  GuardianUnivalle_Benito_Yucra/detectores/detector_dos.py,sha256=Jy4fhI-6n9wQR0quzpondcUyCA2447lDq4fmOFeM1jA,14989
9
9
  GuardianUnivalle_Benito_Yucra/detectores/detector_keylogger.py,sha256=L5RQ0Sdgg7hTU1qkZYwt7AcDqtAzT6u-jwBGo7YWfsw,8078
10
- GuardianUnivalle_Benito_Yucra/detectores/detector_sql.py,sha256=mwRu7MsFZm76k4K07R0kJF6xM2h2fbyCUQAXUmUwHSU,5624
11
- GuardianUnivalle_Benito_Yucra/detectores/detector_xss.py,sha256=EDxGDaOosFJCyWTS_HkB300qL30ArxAEi-i0cVrzXyU,11027
10
+ GuardianUnivalle_Benito_Yucra/detectores/detector_sql.py,sha256=toYXgxLo1Wy_QCnqcboD7_qYbgudPtP4kEzci7GoDkA,12089
11
+ GuardianUnivalle_Benito_Yucra/detectores/detector_xss.py,sha256=Cirjf1fo0j-wOO2baG8GFehAvjPy5JUF9krUg5AtofU,14452
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.60.dist-info/licenses/LICENSE,sha256=5e4IdL542v1E8Ft0A24GZjrxZeTsVK7XrS3mZEUhPtM,37
17
- guardianunivalle_benito_yucra-0.1.60.dist-info/METADATA,sha256=Gneg44zqE93yDBB4-ebTkvXUgSvuAkrp9Am12w2rxdI,1893
18
- guardianunivalle_benito_yucra-0.1.60.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
- guardianunivalle_benito_yucra-0.1.60.dist-info/top_level.txt,sha256=HTWfZM64WAV_QYr5cnXnLuabQt92dvlxqlR3pCwpbDQ,30
20
- guardianunivalle_benito_yucra-0.1.60.dist-info/RECORD,,
16
+ guardianunivalle_benito_yucra-0.1.62.dist-info/licenses/LICENSE,sha256=5e4IdL542v1E8Ft0A24GZjrxZeTsVK7XrS3mZEUhPtM,37
17
+ guardianunivalle_benito_yucra-0.1.62.dist-info/METADATA,sha256=AqWlHPn2dsr38Y7CJkFFtreVNtHMpsR9JBuNlqJ2qaY,1893
18
+ guardianunivalle_benito_yucra-0.1.62.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
+ guardianunivalle_benito_yucra-0.1.62.dist-info/top_level.txt,sha256=HTWfZM64WAV_QYr5cnXnLuabQt92dvlxqlR3pCwpbDQ,30
20
+ guardianunivalle_benito_yucra-0.1.62.dist-info/RECORD,,