Propósito del Token CSRF / XSRF de Go y protección de formularios, y la caducidad predeterminada del token del paquete estándar

8 min

language: ja bn en es hi pt ru zh-cn zh-tw

Hola, soy Incompetente.
Tengo un almacenamiento en línea que he creado y uso personalmente:
GitHub - haturatu/puremania: No security, very fast, web UI self-hosted online storage
Pero si quiero superponer la autenticación en la etapa anterior, he creado un proxy de autenticación.
GitHub - haturatu/auth-proxy: An authentication proxy server and frontend for a website without built-in authentication. JavaScript is supported, but it can also work without JS if using PHP-FPM. The backend is written in Go.
En realidad, es casi todo gracias a Gemini...
Solo se proxy aquellos que pasen la autenticación.
El usuario administrador también puede emitir un token Bearer para los puntos finales de la API y usar ese token para que las solicitudes pasen. Sin embargo, en este caso, también hay puntos finales de API que deben ser accesibles desde las sesiones del frontend, por lo que, en realidad, tanto las cookies como los tokens Bearer se permiten.
Si solo se protegen los puntos finales de la API, aislando el frontend (como el inicio de sesión web) en una red privada y exponiendo solo los puntos finales de la API, la creación de usuarios se puede realizar desde la red privada y, utilizando esos usuarios, la emisión de tokens de API y el proxy de API son prácticamente posibles. (Por favor, no digan '¿por qué no usas un OSS tipo API Gateway?')
En realidad, esto haría que los ataques de fuerza bruta dobles con cookies y tokens fueran prácticamente posibles, pero bueno...

Así que, para la seguridad del frontend web durante el inicio de sesión, hablaremos sobre la seguridad de los formularios.
Si se hiciera que la carga de JS fuera obligatoria, la mayoría de los problemas podrían resolverse, pero ¿no es aburrido depender solo de JS? Por lo tanto, decidí mejorar la seguridad de los formularios con métodos que no sean JS.

Token CSRF / XSRF

Este será el foco de hoy, y se trata de qué es esto en primer lugar.

En pocas palabras, es un mecanismo que verifica si la solicitud del servidor y del cliente fue emitida desde mi lado y si el token está dentro de su período de validez, entonces se permite.
Por ejemplo

<input type="hidden" name="xsrf_token" value="BeftikzaR8Oe6npnqXYC7WtBhuo:1760376550660">

Un token como este se incrusta en el lado HTML del frontend. Este value está firmado por la clave secreta del servidor. Así, el servidor sabe que fue emitido desde mi servidor.
1760376550660 es solo una secuencia de caracteres en tiempo UNIX, pero ¿para qué se necesita la hora actual?
xsrftoken package - golang.org/x/net/xsrftoken - Go Packages

func ValidFor(token, key, userID, actionID string, timeout time.Duration) bool

Se utiliza para la configuración de la caducidad mencionada anteriormente.

En realidad, incluyendo el paquete time, se vería así:

if !xsrftoken.ValidFor(clientToken, string(xsrfSecret), sessionID, r.URL.Path, 15*time.Minute) {

El valor predeterminado si no se proporciona este argumento es de 24 horas, lo cual es bastante laxo, pero creo que esta es la forma en que se debe proporcionar un XSRF Token, donde solo se necesita verificar que el token fue emitido por el servidor.

¡¿Cuál es la diferencia entre CSRF y XSRF?!

En realidad, no parece haber mucha.
El propósito es prevenir ataques de sitios cruzados.

En el caso de CSRF
GitHub - gorilla/csrf: Package gorilla/csrf provides Cross Site Request Forgery (CSRF) prevention middleware for Go web applications & services 🔒
Existía esta biblioteca, y me encontré con esto por casualidad.
Demostración de vulnerabilidad CSRF de gorilla/csrf

Una forma de mejorar la implementación de gorilla/csrf es reemplazar el valor aleatorio utilizado en los formularios con un token cifrado vinculado al ID del usuario. Esto evita que un atacante sustituya su propio token CSRF y valores de cookies por los del objetivo del ataque. Esto se debe a que el token CSRF del atacante corresponde a un ID diferente. De hecho, este método está implementado en la biblioteca que utiliza x/net/xsrftokenHMAC para autenticar el ID de usuario, una acción de formulario opcional y la fecha de caducidad.

Así que pensé, 'ah, está en la biblioteca estándar',
xsrftoken/xsrf.go
y me sorprendió ver el código fuente: ¡solo 100 líneas, incluyendo comentarios! Me preocupa un poco que todavía use SHA1, pero ¿quizás se actualizará en el futuro?
Bueno, si la biblioteca estándar es tan simple, entonces esto es suficiente para el propósito, y si se va a realizar la verificación de SameSite, ¿quizás se debería usar gorilla/csrf?

Notas sobre la biblioteca estándar

Como mencioné antes, la caducidad predeterminada del token es de 24H.
En una operación real, existe la posibilidad de que este período de validez del token sea explotado, por lo que podría ser mejor establecer un tiempo más corto. Si se asume que este token se utiliza para enviar una solicitud hasta que se completa un formulario, 24H permitiría que la misma solicitud pase varias veces si no hay otras medidas de seguridad implementadas con el mismo token, por lo que no sería imposible realizar ataques de fuerza bruta enviando solicitudes al formulario con el mismo token en un bucle infinito de curl.

Related Posts