security - solutions - html form without csrf protection
¿Estoy bajo riesgo de ataques CSRF en un formulario POST que no requiere que el usuario esté conectado? (1)
Probablemente estoy siendo un noob total aquí, pero todavía no estoy seguro de lo que es exactamente un ataque CSRF (falsificación de solicitud entre sitios). Así que veamos tres situaciones ...
1) Tengo un formulario POST que utilizo para editar datos en mi sitio. Quiero que esta información sea editada solo por usuarios que han iniciado sesión.
2) Tengo un sitio, que pueden usar tanto los usuarios que han iniciado sesión como los invitados. Algunas partes del sitio son solo para usuarios registrados, pero también hay formularios POST que pueden ser utilizados por todos los usuarios, anónimos y no (por ejemplo, un formulario de contacto estándar). ¿Debería protegerse el formulario de contacto contra ataques CSRF?
3) Tengo un sitio que no tiene ningún sistema de autenticación (bueno, tal vez no sea realista, así que digamos que tiene un sitio de administración que está separado del resto y la parte de administración está debidamente protegida). La parte principal del sitio solo es utilizada por usuarios anónimos. ¿Es necesario salvaguardar los formularios POST?
En el caso de 1) la respuesta es claramente sí. Pero en el caso de 2 y 3, no lo sé (¿y la diferencia entre 2 y 3 es incluso significativa?).
Hay medios de CSRF siempre que el código HTML o JavaScript malicioso que se dirige a su sitio web se incruste en otra página HTML (o mensaje de correo electrónico) que se haya ejecutado correctamente.
Un ejemplo es el siguiente que se colocó en otra página web que pregunta inocentemente por su nombre y edad antes de continuar:
<form action="http://yoursite.com/transferfunds" method="post">
Your name: <input type="text"><br>
Your age: <input type="text"><br>
<input type="submit">
<input type="hidden" name="amount" value="1000">
<input type="hidden" name="toaccount" value="12345678">
</form>
Tenga en cuenta que la acción apunta a su sitio web y que las entradas ocultas contienen la información POST necesaria. Este ejemplo intentará transferir un fondo de 1000 (en cualquier moneda) al número de cuenta 12345678. Si requiere un inicio de sesión en su formulario y también verifica eso, entonces lo anterior, por supuesto, solo se ejecutará con éxito si el usuario inconsciente tiene ha iniciado sesión recientemente en su sitio web, pero aún no ha finalizado su sesión, o la sesión aún no ha caducado.
Para evitar que eso suceda, lo mejor es agregar un token basado en la solicitud al formulario y validarlo en el lado del servidor. Es decir, generar una cadena aleatoria larga, única e imposible de adivinar que almacena en la sesión e incrusta como elemento <input type="hidden">
del formulario. Cuando se envíe el formulario, compare el valor del token enviado con el que ya se encuentra en sesión (y elimínelo inmediatamente en la sesión). Para ir un paso más allá, hacer uso de un CAPTCHA .
En su caso particular, creo que en realidad está más preocupado por XSS , que es lo opuesto a CSRF, pero que a su vez también puede ser una fuente de CSRF. Un ejemplo de XSS es cuando el usuario ingresa lo siguiente en un campo de entrada que se volverá a mostrar tarde o temprano en el mismo sitio web:
<form name="delete" action="admin/deleteusers" method="post"></form>
<script>document.form.delete.submit();</script>
Cuando usted, como administrador, vea la página con el comentario con el formulario y el script (¡invisible!) En su interior, se ejecutará con éxito.
Prevenir el XSS es bastante fácil. Solo HTML-escape de cualquier entrada controlada por el usuario (es decir, solicitar URL, encabezados de solicitud, parámetros de solicitud y cuerpo de solicitud) antes de mostrarlos en la página web. En PHP puede usar htmlspecialchars()
para esto y en Java / JSP el JSTL fn:escapeXml()
. De esta manera, debajo de cada <
se convertirá a <
y >
a >
lo que hará que cualquier HTML / JS ingresado se muestre literalmente tal como está y por lo tanto no se pueda ejecutar.