Tamaño de trozo HTTP extremadamente grande

2

Estoy trabajando en un proyecto en el que debemos contar el tamaño de respuesta HTTP.

Estoy obteniendo tamaño de trozo como:

 crlf = g_strstr_len(chunkeddata , responceSize - responceHeaderSize, "\r\n")

Y de lo que tenía una comprobación simple, el tamaño de la información de los datos de fragmentos debe ser de 9 bytes más.

Resulta que eso no fue suficiente, al tiempo que consideré mi código comprimido debido al gran tamaño de trozos HTTP (nuestro producto recibe tráfico real de una gran región)

Ahora siento curiosidad por si fue un ataque o simplemente un error del servidor que generó el encabezado de respuesta http.

Mi pregunta: ¿Conoce algún ataque conocido con el uso de información de tamaño de chunkdata en la respuesta de http?

    
pregunta Kadir Erdem Demir 22.08.2013 - 10:11
fuente

1 respuesta

9

A partir de su vaga descripción, supongo que su código reúne lo que el servidor envía como una gran secuencia de bytes, luego interpreta los bytes como si fueran < em> cadena de caracteres terminada en nul , y luego intenta encontrar una secuencia CR + LF en ella.

Esto está mal en muchos niveles. En primer lugar, los bytes no son necesariamente una cadena de caracteres , y en particular pueden carecer de la terminación 0. Además, mientras que el encabezado HTTP consiste en líneas que terminan con CR + LF, y termina en una línea vacía (es decir, un CR + LF inmediatamente después del CR + LF anterior), nada impide que el cuerpo de respuesta contenga también secuencias CR + LF. Finalmente, hay una cosa llamada codificación de contenido que es la forma en que los contenidos de la respuesta se codifican en bytes. Con HTTP , existen principalmente cuatro codificaciones para el cuerpo de respuesta:

  1. Cuerpo sin respuesta. Esto depende del tipo de respuesta. Por ejemplo, los tipos 204 y 304 no tienen un cuerpo.

  2. Longitud explícita. Un encabezado Content-Length especifica la longitud del cuerpo, en bytes .

  3. Longitud implícita. El cuerpo se extiende hasta el final de la conexión de transporte. Cuando se usa la longitud implícita, la respuesta no puede, por definición, seguirse en la misma conexión con otra respuesta para otra solicitud.

  4. Codificación fragmentada. El cuerpo está dividido en partes; Cada fragmento tiene su propio tamaño, dado como un encabezado de fragmento. Esto se describe en sección 3.6.1 . No hay un tamaño máximo estándar en un trozo. La codificación fragmentada también admite un "tráiler", es decir, líneas de encabezado HTTP adicionales después de los datos.

La línea de fondo es que no debes tratar de encontrar secuencias CR + LF directamente en algunos bytes. Lo que debes hacer es lo siguiente:

  • Use una biblioteca HTTP que produzca la respuesta como un flujo; p.ej. LibSoup (Supongo, por tu uso de g_strstr_len() , que usas Glib; LibSoup es una biblioteca de GNOME HTTP diseñada para funcionar bien con Glib).
  • Lea los datos de respuesta, según lo proporciona la biblioteca, como pequeños fragmentos (por ejemplo, mediante fragmentos de un máximo de 8192 bytes, un valor muy tradicional). No se moleste en pensar en "trozos" como se ve en el cable; este es el trabajo de la biblioteca HTTP, no el suyo.
  • Cuenta los bytes a medida que los lees. Supongo que quieres acumular estos bytes en algún lugar de la RAM, por ejemplo. en una matriz, para su posterior procesamiento. Asegúrese de imponer un límite de tamaño: si el cuerpo de la respuesta es mayor que el valor máximo esperado (que depende de lo que desee), descarte otros bytes e informe de un error.

De esta manera, obtendrá la longitud de la respuesta y también la respuesta, mientras se mantiene bajo un tamaño de memoria controlado: una respuesta de gran tamaño no hará que su código asigne una porción de RAM de gran tamaño. Esto también será compatible con los distintos tipos de codificación. En cualquier caso, DEBE leer la respuesta completa en algún momento: a menos que se incluya un encabezado explícito Content-Length , no hay forma de saber la longitud de la respuesta sin leerla toda; y leer la respuesta completa es importante para permitir que una respuesta posterior use la misma conexión TCP.

En ese sentido, los ataques relacionados con el tamaño del fragmento solo funcionan contra software mal escritos que insisten en asignar bloques de RAM en función del tamaño enviado por el par y sin ningún tipo de protección contra datos "absurdos". Si desea implementar un código de red adecuado y no demasiado vulnerable, tiene que ser algo defensivo con respecto a los datos recibidos, que se deben asumir como hostiles por defecto hasta que se demuestre que son benignos. No debe esperar que el servidor le envíe siempre caracteres ASCII agradables en mensajes bien formados. Obtiene bytes y puede obtener cualquier byte, tanto en cantidad como en contenido. El uso de una biblioteca diseñada para HTTP abstraerá los problemas de codificación, por lo que hará la mitad de este trabajo defensivo.

    
respondido por el Tom Leek 22.08.2013 - 15:05
fuente

Lea otras preguntas en las etiquetas