Seguridad

Validar datos no evita XSS ni SQL Injection por sí solo

La Prevención XSS y SQL Injection exige proteger capas distintas: las consultas a base de datos deben usar sentencias preparadas, mientras que los datos mostrados en pantalla deben escaparse según el contexto.

Índice

Anuncio

XSS y SQL injection requieren controles distintos

XSS busca que el navegador de una persona ejecute contenido malicioso, mientras que SQL Injection intenta alterar una consulta contra MySQL o MariaDB. Por ello, se requieren consultas parametrizadas para SQL y escape contextual para XSS.

Vector, impacto y defensa principal

CriterioXSSSQL Injection
Entrada habitualComentarios, perfiles, URL, campos de texto o JavaScriptFiltros, formularios, API, AJAX o consultas personalizadas
Capa afectadaNavegador de quien visita o administraBase de datos y servidor
Impacto típicoRobo de sesión, cambio de contenido o acciones con la cuenta abiertaLectura, cambio o borrado de registros
Control obligatorioEscape de salida según HTML, atributo, URL o JavaScriptConsulta preparada con parámetros separados
Apoyo útilCSP, cookies HttpOnly y límites de HTML permitidoWAF, permisos mínimos y revisión de logs

Una entrada puede necesitar dos defensas

Cuando un valor termina en SQL y también se imprime en una página, ambos controles deben aplicarse de forma independiente.

Si un valor termina en SQL y también se imprime en una página, necesita dos tratamientos independientes: parámetros para la consulta y escape para la salida. Ninguno sustituye al otro.
Validar datos no evita XSS ni SQL Injection por sí solo

Cada dato exige validar, limpiar y codificar

Validar comprueba si un dato cumple una regla permitida, sanitizar lo normaliza o elimina partes no deseadas, parametrizar lo separa del código SQL y escapar lo convierte en texto seguro para un lugar concreto.

Validar antes de aceptar el dato

Los nombres de tablas, columnas y fragmentos como ORDER BY no se parametrizan como un valor normal: deben salir de una lista cerrada controlada por el programa, porque son parte de la estructura de la consulta.

Escapar depende del lugar de salida

esc_html() protege texto dentro de HTML, esc_attr() protege atributos, esc_url() trata direcciones web y wp_json_encode() prepara datos PHP para JavaScript.

Php // Inseguro: el dato modifica el código SQL. $sql = "SELECT * FROM {$wpdb->posts} WHERE ID = " . $_GET['id']; $rows = $wpdb->get_results($sql);

// Seguro: el valor queda separado de la consulta. $id = absint($_GET['id'] ?? 0); $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->posts} WHERE ID = %d", $id ); $rows = $wpdb->get_results($sql);

php // Inseguro si $nombre procede de una entrada externa. Echo '

' . $nombre . '
';

// Seguro: cada salida usa su contexto. Echo '

' . Esc_html($nombre) . '
';

El recorrido seguro de un dato web
1. Entrada
Formulario, URL o API
2. Validar
Tipo, rango y lista permitida
3. Usar
Parámetros si llega a SQL
4. Mostrar
Escape según el contexto

Anuncio

WordPress seguro combina parcheado y APIs

WordPress reduce la exposición a vulnerabilidades cuando el núcleo, los plugins y los temas están al día, y el código propio usa sus APIs seguras.

Wpdb::prepare evita concatenar SQL

wpdb::prepare() inserta marcadores como %d para enteros, %s para texto y %f para decimales, manteniendo el valor separado de la estructura SQL.

Php $estado = sanitize_key($_GET['estado'] ?? 'draft'); $estados = array('draft', 'publish', 'private'); $estado = in_array($estado, $estados, true) ? $estado : 'draft';

$query = $wpdb->prepare( "SELECT ID, post_title FROM {$wpdb->posts} WHERE post_status = %s", $estado );

Roles y permisos limitan el daño

El principio de mínimo privilegio significa que cada cuenta recibe solo los permisos necesarios para su tarea: un editor no necesita administrar plugins, y la cuenta de MySQL no debería tener privilegios globales.

El código PHP y JavaScript necesita doble revisión

Los desarrollos PHP y JavaScript a medida deben validar cada entrada, parametrizar cualquier consulta y codificar toda salida en el punto donde el navegador la interpreta.

innerHTML puede convertir texto en código

XSS basado en DOM aparece cuando JavaScript toma datos de una URL, API o localStorage y los inserta como HTML; si solo necesitas mostrar texto, textContent es la opción más segura.

Javascript // Inseguro: interpreta el valor como HTML. Resultado.innerHTML = new URLSearchParams(location.search).get('q');

// Seguro para mostrar texto. Resultado.textContent = new URLSearchParams(location.search).get('q') || '';

JSON válido no basta al renderizarlo

JSON es un formato de datos, no una garantía de seguridad al incrustarlo en HTML; aunque wp_json_encode() prepare datos PHP para JavaScript, el cliente debe usar textContent, nodos DOM o una plantilla que codifique valores.

CSP, cookies y WAF reducen el impacto

CSP, SRI, HTTPS, cookies seguras y un WAF son capas de contención, no sustitutos del código correcto.

Cookies seguras limitan sesiones expuestas

HttpOnly impide que JavaScript lea directamente una cookie, Secure obliga a enviarla solo por HTTPS y SameSite limita en qué peticiones entre sitios se adjunta.

El WAF filtra, pero no entiende todo

Un Web Application Firewall analiza peticiones y bloquea patrones conocidos antes de que lleguen a WordPress, pero puede fallar ante XSS basado en DOM, rutas internas o lógica de negocio defectuosa.

📦 Lo encontrarás en Amazon

Un firewall para WordPress puede añadir una capa de filtrado frente a peticiones maliciosas conocidas. Debe acompañar al parcheado y a la corrección del código, nunca reemplazarlos.

Buscar en Amazon →

Una CSP eficaz debe enviarse como cabecera HTTP y partir de una política restrictiva, por ejemplo, limitando script-src a 'self' y a orígenes concretos que sean imprescindibles. Evita habilitar 'unsafe-inline' y 'unsafe-eval', porque reducen de forma importante la protección frente a ataques XSS; cuando el sitio necesita scripts inline, los nonces por respuesta o los hashes permiten autorizarlos de forma controlada. SRI (integrity) añade otra defensa al cargar scripts o hojas de estilo desde una CDN: el navegador verifica que el archivo recibido coincide con el hash declarado.

Estas capas no sustituyen el escape contextual ni la sanitización de entradas. Asimismo, HttpOnly evita la lectura directa de la cookie desde JavaScript, pero un XSS aún puede realizar acciones con la sesión activa; SameSite mitiga principalmente CSRF y Secure exige HTTPS.

Anuncio

Auditar antes del incidente evita decisiones a ciegas

Una auditoría útil une inventario de plugins, revisión de código, análisis SAST, pruebas DAST, logs, WAF y un plan de respuesta.

Qué debe comprobar una auditoría

Responder en las primeras 72 horas

Ante una explotación confirmada, conserva logs, aísla el vector, revoca sesiones y credenciales afectadas, corrige el código y restaura solo copias verificadas si es necesario.

La mejor decisión preventiva es exigir pruebas de que cada dato se parametriza al llegar a SQL y se escapa al salir al navegador. CSP, nonces, cookies y WAF reducen el alcance de un fallo, pero no sustituyen esas dos comprobaciones.
Si solo gestionas contenido y no modificas plugins, temas ni desarrollos, no intentes cambiar código sin una revisión técnica. Exige a tu proveedor consultas preparadas, escape contextual, actualización de extensiones, copias de seguridad, control de usuarios y pruebas documentadas. Un aviso de escáner tampoco confirma por sí solo una vulnerabilidad explotable: debe validarse sin dañar producción.

Preguntas frecuentes

¿Qué es una inyección SQL y cómo evitarla?

Una inyección SQL ocurre cuando un dato manipulado cambia una consulta a MySQL o MariaDB. Se evita con consultas preparadas como wpdb::prepare() y permisos mínimos para la cuenta de base de datos; validar el dato no sustituye parametrizarlo.

¿Cómo evito ataques XSS en WordPress?

Evita XSS escapando cada salida con esc_html(), esc_attr() o esc_url() según el lugar donde se muestre. Si permites HTML, limita etiquetas con wp_kses() y revisa JavaScript que use innerHTML.

¿Un nonce de WordPress protege contra XSS?

No, un nonce protege sobre todo frente a CSRF y tiene una validez temporal limitada. Debe combinarse con current_user_can(), validación de entradas, escape de salida y consultas preparadas.

¿Cada cuánto debo revisar la seguridad web?

Revisa plugins y temas al menos cada 30 días y tras cada aviso crítico o cambio de código. Una auditoría puede hacerse entre cada 6 y 12 meses en sitios estables, pero una tienda o portal con datos personales necesita controles entre 1 y 3 meses.

Prioridad: corregir origen y comprobar capas

La prioridad práctica es localizar cualquier SQL concatenado y cualquier dato que llegue a HTML o JavaScript sin escape contextual.

RESUMIR CON IA: Extrae lo importante

Comparte este artículo:

Josu Barrios

Josu Barrios

Somos especialistas en mantenimiento WordPress para empresas, profesionales y tiendas online. Contamos con experiencia en seguridad web, optimización de rendimiento, actualizaciones, copias de seguridad y resolución de incidencias técnicas, ayudando a que cada sitio funcione de forma rápida, estable y protegida. Nuestro enfoque combina soporte técnico profesional, buenas prácticas de seguridad y seguimiento continuo para ofrecer un servicio fiable, transparente y orientado a resultados reales.