El otro día me preguntaban algunos mecenas de la Comunidad por qué cuando me enviaban un correo desde la página de contacto y les respondía, su email aparecía con caracteres raros.
Eso mismo lleva ocurriendo en esta página desde hace unos años tanto en el formulario de contacto como en cualquier otro formulario de la web (suscripción y, por supuesto, comentarios de cada artículo), y la razón es con ello evito, en la medida de lo posible, ataques de SQL injection y algunas de las metodologías más utilizadas para comprometer la seguridad de una página web.
A esta estrategia se le suele llamar saneamiento de inputs, y es junto a los honeypots, las dos herramientas más clásicas para segurizar un servicio online con formularios, como es el caso de WordPress y en definitiva de casi todos los blogs, foros y portales que pueblan el tercer entorno.
Así que voy a dar algunas pinceladas de cada uno, poniendo ejemplos y ofreciendo plugins que automatizan este proceso, para que cualquier administrador interesado pueda implementarlo en su página.
Allá vamos.
Saneamiento de Inputs: Qué es y cómo implementarlo
El saneamiento de inputs es una manera de validar formularios que excluye de los mismos cualquier carácter que podamos considerar peligroso para la web y/o la base de datos.
A fin de cuentas, cualquier formulario de una web es un potencial vector de ataque que un cibercriminal puede aprovechar para comprometer el sitio, bien forzando el cierre de ese input acompañado de una petición a la base de datos (un SQL injection), bien de cara a ejecutar javascript o diversos scripts maliciosos en futuros clientes (ataques cross-site scripting).
Existen muchas maneras de validar un formulario.
- Las nativas de los campos de un formulario: Las propias definiciones de inputs en HTML5 ofrecen validaciones que pueden ser interesantes para separar el grano (los usuarios) de la paja (ataques y/o spam). También, por cierto, tendríamos maneras de hacer esto mismo mediante javascript, PHP (if(empty($_POST[«nombre»]…)) o incluso CSS (input:required:valide….).
<input type="email"> //pedirá al usuario una cadena de caracteres que tiene que tener sí o sí el formato [email protected] <input type="password"> //todo lo que el usuario escriba en este input se mostrará por pantalla mediante asteriscos (*). <input type="text" required> //este campo es obligatorio rellenarlo para poder enviar el formulario...<
input
type
=
"text"
pattern
=
"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$"
name
=
"email"
required/> //esta sería una manera de exigir que el contenido que el usuario incluya en el input tenga formato email, es decir, [email protected]
- Escape de caracteres: Sin embargo, de forma nativa no tenemos manera de controlar que, por ejemplo, cuando el usuario vaya a escribir contenido en un input, no incluya caracteres que el sistema reconoce como funcionales (como por ejemplo las dobles comillas o la comilla simple, que quizás sirva para cerrar el propio input), y esto le permita acceder a partes de la web privadas o a contenido de la base de datos. En estos casos se recurre a funciones que permiten sanear el contenido de un input o bien antes de enviarlo o bien justo antes de ejecutarlo en el servidor. Algunos ejemplos serían:
$input1 = "coche"; //el usuario escribió "coche" $input2 = "'or '1'=1"; //el usuario escribió"'or '1'=1" select pass from usuarios where usuario=$input1; //devolvería en SQL la contraseña del usuario "coche", si es que existe select pass from usuarios where usuario=$input2; //devolvería en SQL la contraseña de cada usuario, ya que 1=1 siempre se cumple $peticion = mysqli_real_escape_string($link, $input2); //escapamos el contenido de $input2 select pass from usuarios where usuario=$input2; //devolvería en SQL la contraseña del usuario "'or '1'=1", que seguramente no exista
Y lo mismo puede hacerse con htmlspecialchars (EN) o escapeshellarg (EN). Incluso mediante los propios filtros de PHP (EN).
En mi caso hago uso del plugin NinjaFirewall para WordPress (EN) que, entre otras cosas, permite de forma automática sanear cualquier petición GET y/o POST que se haga en la página.
Honeypots de formularios: Qué son y cómo implementarlos
Aledaño al problema de los XSS y los SQL injection está la proliferación de bots cuyo único cometido es buscar formularios en webs para publicar enlaces hacia páginas fraudulentas (viagra, malvertising y demás compañía). Y puede llegar a ser un verdadero problema, ya que además de gastar recursos del servidor (son peticiones automatizadas que ocupan ancho de banda), pueden llenar la web de contenido inapropiado y causar verdaderos dolores de muelas a los administradores del sitio.
Afortunadamente, hecha la ley hecha la trampa, y basta entender cómo se desarrollan este tipo de bots y qué es lo que buscan en un formulario para encontrar maneras de engañarlos y hacerles creer que o bien no existe tal formulario, o bien han publicado con éxito lo que querían publicar.
A estas técnicas se las llama honeypots, que en este caso están dirigidas al mundo de los formularios, pero que en la práctica competen a cualquier herramienta cuyo cometido sea engañar a los cibercriminales (la creación por ejemplo de ordenadores supuestamente vulnerables en una red corporativa para localizar ataques antes de que afecten al resto de la organización sería otro aplicativo de los honeypots, solo que enfocado a la seguridad de redes).
Y de nuevo, tenemos mil y un maneras de aplicarlos:
- Captchas y listas negras: aunque no sean honeypots al uso, lo cierto es que la obligatoriedad de completar un captcha o el llevar en cuenta una lista negra de IPs con actividades curiosas (es normal que un bot intente realizar varias peticiones al mismo tiempo ahí donde un usuario normal claramente no puede) permite evitar la mayoría de spam en formularios web. En el primer caso, a cambio de molestar al usuario (que debe completar un dichoso captcha), y en el segundo, generalmente haciendo uso de servicios de terceros que son los encargados, en base a todas las páginas donde están instalados, de mantener actualizada la lista. En WordPress a mi me gusta especialmente Anti-spam (EN), que (ojo) solo funciona con los formularios de contacto, pero que elimina prácticamente todo el ruido que podría salpicarnos.
- Honeypots de cliente: La idea pasaría por incluir inputs ocultos al usuario que, de ser completados, no enviasen al servidor la petición. Eso se consigue creando un input de tipo hidden (o bien un input cuyo CSS diga que no debe ser mostrado por pantalla) y cuya petición de envío esté condicionada a que ese input siga vacío. Cosa que ocurrirá con todos los usuarios que lo completen, y que no se cumplirá en el caso de los bots, que necesitan cumplimentar todos los campos para evitar dejarse alguno que sea obligatorio.
<form action="submit.php" onsubmit="return validateMyForm();" method="post"> <input type="email" name="email"> //el input verdadero <input type="text" id="input-totalmente-falso" style="display: none"> //el input falso que no se mostrará por pantalla <input type="submit" value="Submit"> </form> <script type="text/javascript"> //creamos la función validateMyForm function validateMyForm() { if(!document.getElementById("input-totalmente-falso").value) { return true; } //si no existe nada de contenido en el input falso, entonces se envía else { return false; } //si existe, entonces es que es un bot quien intenta completarlo, por lo que no hacemos nada } </script>
- Honeypots de servidor: Tienen la ventaja de funcionar aún cuando JavaScript no está habilitado (puede que el bot esté operando en algún entorno más controlado), y la parte mala es que, como todo de cara al servidor, cada petición consume proceso. El procedimiento, no obstante, es semejante al anterior, creando un input falso, pero la validación la hacemos una vez llega la petición al servidor (si el input está vacío, se realiza exitosamente; si no, no). Esto puede hacerse directamente en el SQL o en el PHP.
<?php if(!$input-totalmente-falso){ mail("[email protected]","Nuevo contacto en la web",$cuerpo-del-email); } ?>
En otros casos lo que creamos son inputs ocultos con un código específico, de manera que si al llegar al servidor ese string ha cambiado, podemos estar seguros de que estamos ante una petición fail.
<input type="hidden" id="input-de-control" value="0324655847"/> <?php if($input-de-control!="0324655847"){} else{ mail("[email protected]","Nuevo contacto en la web",$cuerpo-del-email); } ?>
Existen, como decía, múltiples estrategias para controlar el spam que llega a nuestros servidores. Y como todo, hay que buscar el punto medio en el que lo reduzcamos a la mínima expresión sin molestar en demasía al usuario.
¿Necesitas ayuda par implementarlo profesionalmente?
Y si te has quedado con más dudas o todo lo que te cuento aquí te suena a chino, no dudes en ponerte en contacto con un servidor, comentarme tu caso particular, y ver si puedo ayudarte en algo.
________
Puedes ver más artículos de esta serie en #MundoHacker, donde tratamos en varios tutoriales las medidas para atacar y/o defenderse en el mundo digital.
Y si el contenido que realizo te sirve para estar actualizado en tu día a día, piensa si te merece la pena entrar en el Club Negocios Seguros y aprovecharte de todo el contenido exclusivo que publico para los miembros.
Buenas, he sufrido un ataque
«Detalles del attaque: List of malicious processes:
HACKED
SPAM
……
en un servidor virtual Centos 5 Linux en 1and1, usted lo podría reparar, qué coste tendría y si no, ¿conoce a algún informático o me puede orientar donde buscarlos?
Muchas gracias
Buenas Carlos. Entiendo que te has puesto en contacto con 1AND1. ¿Qué te han dicho ellos? Vale que no suelen dar soporte, pero si es un ataque a ellos también les afecta (y podría llegar a afectarles al resto de sus usuarios).
buen día, últimamente hemos estado recibiendo a diario, duplicados nuestros formularios de información, que se supone llenan lo clientes, tenemos activado captcha y siguen llegando desde nuestro sitio web con este contenido, no podemos identificar este es algún tipo de ataque, puede dar algun indicio para clarificar si es error de la config?? :
First Name CycDQuONm
Last Name XObAmqluU
Nationality RaMXLUYKrQ
Email [email real]
Phone Number iTDHvOXSbdyfmRxn
Desired Start Date 2020-05-03
Number Of Weeks 2
How they found us Recommendation
Accept T&C LOmIqFzWrU
Message : kgzZUVJlFYDjucdy
¿Es muy masivo?
En principio parece una simple campaña de esas automatizadas que está continuamente crawleando potenciales formularios para futuros ataques.
Porque vaya, está claro que mucha información, aunque fuera de spam, no están haciendo (ni un enlace a una página fake han metido).
Si es algo muy habitual yo implementaría un sistema de captcha más potente. Por ejemplo en WordPress a mi el plugin Anti-Spam me ha dado muy buenos resultados, pero todo es probar. Para otros desarrollos tenemos el recaptcha de Google.
Eso o que como decís el formulario esté mal diseñado y esos códigos sean por un mal formateo del texto que han puesto los usuarios lícitos.
¿Habéis probado a poneros en contacto con el email que aparece?
Hola, Pablo.
Las pocas veces que comenté algo, me di cuenta de que el texto enviado que espera moderación, se ve con los caracteres de escape de espacios y saltos de línea ¿Es esta la razón de eso?
Por otra parte, intuyo entonces que el e-mail se pide para filtrar aquellos sospechosos que causan problemas. Interesante.
Saludos!
Así es Joaquín.
Yo luego os lo quito para que no quede raro en la lectura, pero sí, a mi me llega como ves, con los «/n» y /r» precisamente para evitar que un usuario escape algún carácter que aproveche alguna vulnerabilidad.
Y lo del email es una configuración básica de seguridad de WordPress. También te digo que es poco fiable, ya que a fin de cuentas puedes poner el email que quieras… Si no te interesa recibir notificación, pues por poder puedes poner cualquier email, exista o no.