[LACNIC/Seguridad] Processing of IPv6 "atomic" fragments (Fwd: I-D Action: draft-ietf-6man-ipv6-atomic-fragments-00.txt)

Fernando Gont fgont en si6networks.com
Vie Feb 3 20:24:16 BRST 2012


Hola, Ivan,

Gracias por tus comentarios! Mis respuestas van entre lineas...

(Disclaimer: hace un dia que no duermo, por lo cual puede que haya
alguna falta de luces, como también respuestas tal vez un poco
politicamente incorrectas ;-) )


On 02/03/2012 05:08 PM, Iván Arce wrote:
> Leí ambos documentos y me parece increíble que estas cosas sigan
> sucediendo, particularmente porque dado que el problema de no validar
> adecuadamente las diversas variantes de ICMPv4 "unreachable" es
> ampliamente conocido como resultado del uso común de una serie de
> herramientas de denegación de servicio durante los 90s.

Si. De hecho, yo escribí <http://www.rfc-editor.org/rfc/rfc5927.txt>.

Te doy un poco de background, ya que la razón de lo que (correctamente)
mencionás es politica, y no técnica:

En lo que respecta a la validación de mensajes ICMPv4&v6, la misma debe
hacerse en la capa de transporte, en donde hay info que se puede
chequear (tal como los numeros de secuencia TCP, etc.). Por tal motivo,
el RFC 5927 fue producido por el tcpm Working Group (TCP Maintenance and
minor extensions) de la IETF.

El problema con ese working group es que tradicionalmente ha participado
en ese grupo gente que cree que para actualizar una especificacion de
TCP, hay que estar practicamente santificado.
RFC5927 intentó en un prinncipio (circa 2004) actualizar las
especificaciones, de modo de exigir validación de los mismos. Sin
embargo, en medio de la innumerables discusiones estupidas mantenidas
durante 2004-2010 (si, la IETF tardó 6 años para publicarlo!), se le
bajó la categoria al RFC, y quedó como Informational. -- es decir, las
especificaciones quedaron sin actualizarse.

En su momento, yo implementé todo el RFC 5927 para OpenBSD, y dicho
parte fue luego portado a FreeBSD (Linux implementó la mayoría de él,
pero no todo).

Alrededor de aquella época se estaba revisando la especificación de
ICMPv6. Los involucrados en dicho trabajo eran lo suficientemente
sensatos como para saber que habia que exigir chequeos en los mensahes
ICMPv6 -- pero dado que dicha area era "turf" de tcpm, lo máximo que
logramos hacer fue incluir una referencia a RFC 5927, sin ahondar en
detalles.



> Hubiera esperado
> que los requerimientos para el procesamiento de ICMPv6 de error fueran
> mucho menos ambiguos y mas estrictos que lo que sucedió con v4 y que los
> implementadores fueran menos chapuceros.

Coincido. Diría que, en primero lugar, el error fue de la IETF.

En loq ue respecta a los implementadores, estimo que simplemente las
implementaciones todavia no son lo suficientemente maduras, y que
eventualmente implementaron algo al estilo de RFC5927.

-- tené en cuenta que el mismo tipo de "error" se ha encontrado en los
Fragment ID de IPv6, y demás... -- es decir, estamos con IPv6 como
estabamos con IPv4 en los '90, mas o menos.



> Con respecto a "draft-gont-6man-predictable-fragment-id", la descripción
> del ataque me recordo algo que escribí hace mucho tiempo en relación a
> los query IDs de DNS:
> 
> http://www.openbsd.org/advisories/res_random.txt

Lo cual muestra que pasados quince años, seguimos golpeandonos con la
misma piedra....



> Estoy interesado en entender porque el algoritmo recomendado es de
> mantener un contador por dirección de destino e inicializarlo con un
> numero pseudo  aleatorio y después incrementarlo de a uno en lugar de
> mantener un LCG global que vaya generando Fragment IDs de manera pseudo
> aleatoria. 

Background: Estos I-Ds estan basados en un trabajo mas extenso y
abarcativo sobre seguridad IPv6, sobre el que trabajé durante los
ultimos años. En dicho document, mi propuesta inicial era la que vos
mencionás (no se si necesariamente un LCG, pero algun tipo de PRNG).

Sin embargo, cuando se envío al documento a varios vendors, varios
expresaron preocupación por las "colisiones" de Fragment IDs -- lease,
que si justo tenes la mala suerte que en un mismo instante se fragmentan
dos paquetes con el mismo grupo de valores (src IP, dst IP, Frag ID), el
proceso de reensamblado falle, y los paquetes se descarten.

De ahi que se llegó a la alternativa incluida finalmente en el ID que
publiqué.

Un a alternativa (que no descarto, es que el I-D proponga alternativas,
del mismo modo que lo hicimos para los tansport ports en
<http://www.rfc-editor.org/rfc/rfc6056.txt>).

(FWIW, yo, personalmente, no creo que pueda causar rpoblemas seleccionar
el Frag ID con un PRNG... especialmente teniendo en cuenta que es de
32-bits, y no de 16-bits como en IPv4. Obviamente, cuan problematico
puede ser esto depende del ancho de banda en juego, probabilidad de
pérdidas, etc... En <http://www.rfc-editor.org/rfc/rfc4963.txt> hay
algunos números y ensayos, para el caso de IPv4).



> Creo que ambas soluciones serian viables pero que la
> recomendada podría crear la dependencia de que otros hosts también la
> implementen (y no tengan un contador global incrementado de a uno) para
> evitar ataques similares al idles scan con fragmentos ipv6. 

No entendí lo de la "dependencia". Te referis a que algunas
implementaciones podrían caer en el error de utilizar un contador
global, o te referis a otra cosa?

Otra alternativa posible es generar los I-Ds asi:

Frag_ID = F(src IP, dst IP, secret1)  +
          counter[G(src IP, dst IP, secret2)]

Donde:
F(): hash
G(): hash
counter[]: array de contadores, inicializados al bootear con valores
aleatorios.


Esta alternativa es un "termino medio" entre "un contador global" y "un
contador por destino".


> Estoy seguro
> que esto lo discutieron y analizaron bien antes de terminar con el
> algoritmo recomendado, nos contás un  poco como fue esa discusión?

Como dato adicional, la "discusion" anterior, hasta donde recuerdo, fue
principalmente con los developers de Linux.

Solaris ya tenia implementado "un contador por destino", pero los
inicializaban todos con el mismo valor -- por lo que lo unico que
tuvieron que hacer fue parchear para que cuando se "crea" un contador
para un destino, se lo inicialize con un valor aleatorio.


> Por otro lado, lei la parte correspondiente al Fragment Header del RFC
> 2460 (http://tools.ietf.org/html/rfc2460#section-4.5) y me llamo la
> atención esto:
> 
>> The number and content of the headers preceding the Fragment
>> header of different fragments of the same original packet may
>> differ.  Whatever headers are present, preceding the Fragment
>> header in each fragment packet, are processed when the packets
>> arrive, prior to queueing the fragments for reassembly.  Only
>> those headers in the Offset zero fragment packet are retained in
>> the reassembled packet.
>>
>> The Next Header values in the Fragment headers of different
>> fragments of the same original packet may differ.  Only the value
>> from the Offset zero fragment packet is used for reassembly.
> 
> Parecería que eso abre la puerta a la "inserción y/o solapamiento de
> headers" que incluso se procesarían silenciosamente ?! No entiendo del
> todo las implicancias de eso en un escenario en el que se usan Fragment
> IDs predecibles pero sospecho que no son buenas...

Coincido. *En principio* ("en teoría"), al menos desde la parte
fragmentada en adelante esto se evitaría gracias a lo especificado por
RFC 5722. En lo que hace a la parte anterior al fragmento... dejame
pensarlo un poco, ya que no habia evaluado el tema.

Nota al margen: Tanto RFC 2460 como otras tantas especificaciones
necesitan, a mi entender, "ajuestes". En muchos casos existe una
flexibilidad que a la practica es inutilizable para fines legitimos,
peroq ue convierte en una pesadilla cualquier intento de monitoreo (por
ejemplo, mirá los ejemplos referidos al uso de extension headers en este
I-D:
<http://tools.ietf.org/id/draft-gont-v6ops-ra-guard-implementation-01.txt>)


> por ejemplo, un datagrama con un routing header espurio y un fragment
> header con un ID adivinado podría ser procesado antes del reemsamblado y
> posteriormente al momento del reemsamblado darse cuenta que como hay
> fragmentos solapados hay que descartar todos los fragmentos, y sin
> embargo el routing header espurio ya se proceso...? 

Si, la especificaciones exigen que los extension headers se procesen en
el orden que se encuentran en el paquete. De hehco, fijate que cuando
existe fragmentación, es legitimo usar dos "Destination Options"
headers: uno antes del Frag Header, y uno despues. EL primero se procesa
ni bien llega el paquete, y el otro una vez reensamblado el mismo.


> Incluso creo que no
> es estrictamente necesario que los fragmentos se solapen... se podría
> mandar un routing header espurio con un fragment header con id
> adivinado, MF=1 y un Fragment Offset >0.  En este caso la recomendación
> de tu draft no sería  contraproducente?:

No.

Fijate que si envias un paquete con Fragment Offset != 0 y MF=1, eso no
constituye un "atomic fragment", y por ende se almacena el en "fragment
reassembly queue". Si tiempo mas tarde llega un "atomic fragment"
*legitimo* (incluso con los mismos valores de (src IP, dst ip, Frag
ID)), dicho fragmento legitimo *no* se mezclaria con el fragmento
malicioso que está en el queue.

La idea básica detrás de "draft-ietf-6man-ipv6-atomic-fragments-00.txt"
es que lso atomic fragments no necesitan mezclarse con ningun otro
paquete, ya que pese a tener Fragment Header, en realidad posee toda la
info (es decir, el FO==0 te dice que es el primer fragmento, y el MF==0
te dice que es el ultimo... ergo, es el paquete completo).

Si uno no implementara "draft-ietf-6man-ipv6-atomic-fragments-00.txt",
entonces el trafico que utilice fragment headers es vulnerable a
cualquier ataque de fragmentacion.

* Intencionalmente* el I-D no menciona con detalles el siguiente escenario:
               Conexion TCP
           A <--------------> B


Un atacante (en cualquier otro punto de la red) podria spoofear un
ICMPv6 "Packet Too Big" a A, con un "MTU" < 1280. Tal como lo menciona
RFC 2460, "A" deberia empezar a enviar todos sus paquetes con un frag
header (serían "ataomic fragments"). Si los Frag ID utilizados por "A"
son predecibles, entonces el atacante podria enviar fragmentos
spoofeados a "B", de modo que colisionen con los fragmento legitimos
enviados por "A". Resultado: DoS.

La propuesta en cuestion previene dicho ataque, ya que al ser los
paquetes legitimos de tipo "atomic fragments", nunca se mezclarian con
los fragmentos maliciosos enviados por el atacante.



>> Additionally, any fragments already queued with the
>> same set {IPV6 Source Address, IPv6 Destination Address, Fragment
>> Identification} should not be discarded upon receipt of the
>> "colliding" IPv6 atomic fragment, since IPv6 atomic fragments do
>>  not really interfere with "normal" fragmented traffic.
> 
> Por otro lado, la seccion 4 del mismo RFC 2460 dice:
>> The contents and semantics of each extension header determine whether or
>> not to proceed to the next header.  Therefore, extension headers must
>> be processed strictly in the order they appear in the packet; a
>> receiver must not, for example, scan through a packet looking for a
>> particular kind of extension header and process that header prior to
>> processing all preceding ones.
> 
> La posibilidad de adivinar un fragment ID y mandar un paquete spoofeado
> con un header espurio invalida la presunción de que todos los headers se
> procesan en orden no?

Me perdi en esta ultima...

Adivines o no el Frag ID, todo lo que se encuentra previo al Frag header
va a ser procesado por el destinatario. Sin embargo, del frag header en
adelante, pueden ocurrir varias cosas:

1) Si la implementacion todavia no se updateo con RFC 5722
  1) a) Se peude procesar la "primer copia" de los datos
  1) b) Se puede procesar la segunda copia de los datos
  (ambas son el resultado de lo descripto por Ptaceck en su momento)

2) Si el hsot *implementa* RFC 5722, y hay fragmentos solapados, se
descartarian.

A esto te referias?

Saludos,
-- 
Fernando Gont
SI6 Networks
e-mail: fgont en si6networks.com
PGP Fingerprint: 6666 31C6 D484 63B2 8FB1 E3C4 AE25 0D55 1D4E 7492






Más información sobre la lista de distribución Seguridad