Estoy respondiendo a mi propia pregunta porque Pienso Ahora entiendo el INCUMPLIMIENTO y cómo prevenirlo. Me encantaría recibir comentarios.
Cómo funciona BREACH (como yo lo entiendo)
(Ampliando una explicación aquí que me ayudó.)
Supongamos que eres un atacante. Has iniciado sesión en un servicio como a ti mismo. Observa que hay un punto final search
, y si envía el término de búsqueda rabbits
, obtiene una respuesta como esta:
<SearchResponse>
<AuthToken>d2a372efa35aab29028c49d71f56789</AuthToken>
<SearchTerm>rabbits</SearchTerm>
<Results>
<Result>rabbits rock</Result>
<Result>yay rabbits</Result>
</Results>
</SearchResponse>
También observa que la respuesta está comprimida y encriptada (HTTPS).
Intenta buscar una cadena con formato como el valor <AuthToken
, como aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
. La respuesta es:
<SearchResponse>
<AuthToken>d2a372efa35aab29028c49d71f56789</AuthToken>
<SearchTerm>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</SearchTerm>
<Results>
</Results>
</SearchResponse>
No hay resultados para esto. A continuación, modifica ligeramente el término de búsqueda:
<SearchResponse>
<AuthToken>d2a372efa35aab29028c49d71f56789</AuthToken>
<SearchTerm>d2a37aaaaaaaaaaaaaaaaaaaaaaaaaa</SearchTerm>
<Results>
</Results>
</SearchResponse>
Como esperabas, algo interesante está sucediendo. Debido a que el término de búsqueda no tiene sentido, los <Results>
son siempre los mismos: vacío. Lo único que chaging es el <SearchTerm>
. Y debido a la compresión, cuanto más se asemeja el valor <SearchTerm>
al valor <AuthToken>
, menor es la respuesta.
Esto se debe a cómo funciona la compresión gzip: elimina la repetición al comprimir y la restaura al descomprimir. Cuanto más repetitiva sea la entrada, más pequeña se comprime.
Vuelve a buscar, usando el valor exacto de <AuthToken>
.
<SearchResponse>
<AuthToken>d2a372efa35aab29028c49d71f56789</AuthToken>
<SearchTerm>d2a372efa35aab29028c49d71f56789</SearchTerm>
<Results>
</Results>
</SearchResponse>
Esta vez tomas nota de lo pequeña que es la respuesta.
Ahora, debido a que estas son sus solicitudes, ha podido leerlas directamente. Si pudiera realizar un ataque MITM a otro usuario del sitio (por ejemplo, ejecutando un enrutador malicioso), podría ver el tamaño de la respuesta cifrada, pero no el contenido real.
Usted piensa: si puedo engañar a otra persona para que envíe los términos de búsqueda que quiero, y si puedo ver qué tan grande es la respuesta cifrada, puedo modificar el término de búsqueda una y otra vez. Cuanto más cerca esté de adivinar el token de autenticación, menor será la respuesta, y cuando es el tamaño de la respuesta que acabo de ver, lo adiviné correctamente. Una vez que conozca su token de autenticación, puedo iniciar sesión como ellos.
Si de alguna manera puede ejecutar un ataque XSS contra su víctima, puede hacer que realicen las solicitudes necesarias.
Mitigación
Este ataque no funcionaría si:
- El servidor no usó la compresión HTTP (como gzip, en nuestro ejemplo)
- La solicitud no se pudo realizar correctamente sin un token CSRF, que el atacante no pudo saber
- El servidor nunca coloca ambos datos confidenciales (como un token de API) y datos proporcionados por el usuario (como el término de búsqueda) en la misma respuesta
- El servidor nunca devolvió el mismo token de API dos veces (por ejemplo, si los valores de token sin procesar se marcaron y firmaran antes del envío, la marca de tiempo garantizaría que el token en la respuesta cambiara constantemente)
- La respuesta siempre contenía un relleno de longitud aleatoria, como @AndrolGenhald señaló en un comentario (aunque con suficientes solicitudes, un atacante podría separar la señal de este ruido)