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

Fernando Gont fgont en si6networks.com
Jue Feb 9 01:56:57 BRST 2012


On 02/08/2012 12:51 PM, Iván Arce wrote:
>>> Es asi: A y B se comunican con datagramas fragmentados, A implemente la 
>>> recomendacion (contador por destino, inicializado random), B no 
>>> implementa la recomendación (contador global), ahora tenés que 
>>> garantizar que B no filtre información a un tercero  (M de Mallory, 
>>> que puede comunicarse con ambos a su antojo) sobre el contador de A con 
>>> B.
>>
>> Como habria de leakear la info del contador de *A con B*? (o es que te
>> referias a "la info del contador de *B* con *A*?)
> 
> No, me refería exactamente a lo que escribí, no querés que B filtre
> información sobre el contador que tiene A para generarle frag IDs a B.

Este ataque no lo habia considerado, así que "buen punto" (valido).

Mas alla de eso, este caso particular es "cuestionable". Lease: la
gracia del idle scan es que al atacante (M) puede escanear un host A,
sin siquiera enviar nada al mismo, utilizando un zombie (B) (lease, un
scanneo "stealth").

En el caso que vos mencionas, M se comunica con B, para "adivinar" los
incrementos de A a B. -- Si, hay un leak de información, es cierto.
Pero... es util?

(de cualquier modo, repito, el punto es bueno)


> Si B filtra información sobre el contador que usa A entonces es posible
> que M ataque las comunicaciones entre A y B, que teoricamente segun la
> recomendación ya no serían susceptibles de ataque porque A ya no genera
> frag IDs predecibles por un tercero offpath.
> 
> Como habría de hacerlo?  y... ya tenes todas las pistas:
> 
> Utilizando los frag ID que M recibe de B como un oraculo, se
> incrementarán mas o menos dependiendo de si B generó frag IDs para otro
> destino (p.e. para A en respuesta a comunicaciones fragmentadas
> recibidas de A).

El leak de arriba es correcto. Pero esto que mencionas me parece que no
lo hacés. En el caso anterior, lo que se leakea son los *incrementos*,
pero no los valores en si.

Si vos generas los Frag ID a partir de un contador que se inicializa de
manera aleatoria, lo que tenes es básicamente una recta/rampa, con un
"offset" aleatorio. Adivinando lso incrementos (en tu ejemplo anterior),
vos podes "identificar" la recta.... pero en ningun caso tenés el valor
de la función (en este caso, el Frag ID).


>> Estamos de acuerdo. Pero el "modelo de ataque" es de proteger la
>> comunicación contra atacantes "off-path". -- Al fin y al cabo, para que
>> quiere B adivinar que Frag IDs va a usar A *con el mismo*, si al fin y
>> al cabo, de todos modos los va a ver?
> 
> Lo que estoy diciendo es que la recomendacion solo atiende parcialmente
> el modelo de ataque que describis. B no quiere adivinar nada porque ya
> sabe pero tampoco quiere que  M lo use para adivinar que Frag ID le va
> a mandar A, porque eso le daría a M, un atacante off-path, la
> posibilidad de interferir en las comunicacioens entre A y B.

Por lo que veo de tu ejemplo, lo unico que puede hacer M es detectar
incrementos en los Frag ID de A a B... pero *no* adivinar el valor en si.


>>> El problema subyacente con el contador por destino es que se esta 
>>> trasfiriendo confianza sobre un secreto (el valor del proximo frag ID) 
>>> a cada destino sin tener garantía de que el destino puede mantener el 
>>> secreto. 
>>
>> No entiendo porqué decís esto. En el caso en cuestión, lo unico que se
>> le transfiere a B es el valor del proximo Frag ID a ser utilizado *con B*
> 
> Si, pero el hecho de que B use un contador global que se incrementa
> predeciblemente crea un canal encubierto que le permitiria a un
> tercero *off path* inferir ese valor sin necesidad de verlo.

Como mencionaba arriba, lo que pueda hacer un tercero off-path es
inferir que (por ej.) A incremento su Frag ID enviado a B... pero *no*
adivinar el valor en si.



> Bueno, no entiendo tu ejemplo... la tabla solo incluye paquetes
> originados por M (el atacante). Pensa un ejemplo en el que A y B se
> comunican entre si y M quiere interferir esa comunicacion. Hay 6 tipos
> de paquetes:
> 
> originado por	   IP origen	   IP destino
> 	A		A		B
> 	B		B		A
> 	B		B		M
> 	M		M		B
> 	M		A (spoof)	B
> 	M		B (spoof)	A
> 
> A genera Frag IDs segun la recomendacion (contador por destino
> inicializado aleatoriamente)
> 
> B genera Frag IDs con un contador global con un incremento fijo por
> paquete fragmentado a enviar
> 
> M genera Frag IDs como le plazca
> 
> Como haría M para interferir la comunicacion entre A y B ?

*Esto* es lo que no me queda en claro. M puede bloquear (DoS) los
paquetes de B a A, ya que los Frag ID de B son predecibles. Pero no veo
como M podria bloquear los paquetes de A a B. Ya que el valor en si de
los Frag ID no lo puede predecir/adivinar.


> Como haría M para hacer un port scan usando datagramas IPv6
> fragmentados? atomicos o no ?

Si te referis a escanear cualquier host (por ej. A) utilizando a B como
zombie, entonces es simple.



>>> Si nos ponemos puristas tambien podríamos decir que hay un problema de 
>>> confusión de tipos: El Frag ID tiene que ser un identificador unico 
>>> pero eso no necesariamente implica que tenga que ser un contador (de 
>>> hecho en el RFC no dice esto es un contador...)
>>
>> Como que no? :-)
[....]
> 
> uy, me perdi eso!
> 
> De todas formas no hace mas que exacerbar la confusion... porque en el
> parrafo anterior a ese dice:
> 
> --- cut here ---
>    For every packet that is to be fragmented, the source node generates
>    an Identification value. The Identification must be different than
>    that of any other fragmented packet sent recently* with the same
>    Source Address and Destination Address.
> --- cut here ---
> 
> El parrafo que yo cito dice "*must* be different"
> El siguiente, que citas vos, "the requirement *can* be met"
> 
> Osea el Frag ID *tiene* que ser un ID unico por tupla (src,dst) y ese
> requerimiento *se puede* satisfacer con un contador, pero nadie
> *requiere* que se satisfaga asi...

Completamente de acuerdo con tu analisis. -- Pero convengamos que el
"hint" que da es a implementar el Frag ID como un contador. -- De hecho,
incluso chequeando la implementacion de KAME (*BSDs) -- que hoy en dia
genera los Frag ID con un PRNG --  veo que en versiones "viejas" (circa
FreeBSD 4.x), utilizaban un Frag ID global, totalmente predecible.


> Igual lo que tenia en mente cuando cuanto escribi que "el RFC no dice
> esto es un contador" es la definición similar y ahora creo que menos
> confusa de IP ID en IPv4 (RFC791).

Vos decis? Yo acabo de pasar por encima de RFC791, y en tal sentido ni
siquiera sugiera que el IP ID se pueda implementar como un contador....
-- o sea, en tal sentido, RFC2460 creo que guia en peor direccion que
RFC791 (que no guia demasiado en nngun sentido :-) ).


> Pero despues de relear esa parte reitero, el RFC 2460 incluso con el
> parrafo que citas *no dice* "este campo es un contador"

De acuerdo con ello.



> En el RFC 5722 que habla de que hacer con el reesamblado de fragmentos
> solapados no se distinguen los atomicos de los no-atomicos.

Correcto. Por ello mi I-D updatea formalmente no solo a RFC2460, sino
también a RFC5722.



> De hecho, dos fragmentos con el mismo Frag ID y con Offset=0
> calificarían como solapados en ese contexto (por mas que uno tenga MF=1
> y otro MF=0).

Tal cual. Se supone que el I-D que yo escribi "actua primero" que RFC
5722. -- Lease, que si un fragmento es atomico, no lo consideras
realmente un fragmento... y entonces simplemente removes el Frag Header,
y listo..



> Por otro lado, el RFC 5722 tampoco habla de solapamiento de headers
> antes de la parte fragmentada, algo que yo creo talvez tambíen debería
> considerar como un problema.

Si, aunque... como habrías de chequear esto?

O sea, e el caso legitimo, cada uno de los fragmentos tiene todos los
mismo ext headers. Si vos queres prevenir que distinos fragmentos puedan
tener un set de fragmentos y opciones (pervio a la parte fragmentada),
entonces no te quedaria otra que comparar byte-a-byte dicha parte de
cada fragmento con el de los demas. -- y esto sería "overkill".

O sea, comparto en principio tu planteo, pero... es "realizable"?



>> Con "fragmentadas de forma distinta" te referis a "con fragmentos
>> solapados" o a "una instancia con fragmentos atomicos y otra con
>> fragmentos comunes"?
>>
>> En principio, todo depende de como generes el Frag ID. 
> 
> ok, pero entonces, por definicion, los problemas de generacion de Frag
> IDs y de procesamiento de datagramas fragmentados (ya sean atomicos o
> no) no son ortogonales...

Lo que yo digo es: draft-ietf-6man-ipv6-atomic-fragments-00.txt propone
un procesamiento de los fragmentos atomicos, que impide que puedas
realizar ataques de fragmentacion contra dicho tráfico. -- a eso es a lo
que apunta. Y esa recomendacion la podes aplicar sin importar si los
algoritmos que se estan utilizando apra generar los Frag IDs son buenos
o malos. (lease, draft-ietf-6man-ipv6-atomic-fragments-00 te beneficia
incluso si tu algoritmo (o el de tu peer) para generar Frag IDs es
horrible).

Por otro lado, tener Frag IDs predecibles, o también tener *incrementos*
predecibles, tiene implicancias de seguridad. En el primer caso, podes
ser objeto de un ataque de DoS, En el segundo, podes ser utilizado como
zombie para un idle-scan. Pero no ahce falta que implementes
draft-ietf-6man-ipv6-atomic-fragments-00.txt para solucionar el tema de
los Frag ID/incrementos predecibles.

Por eso digo que son ortogonales. Ambos temas apuntan a cosas distintas.
Y el uno no depende del otro.



>> Si, aunque el "riesgo extra"/peligro implica que uno pueda "lograr algo
>> mas" por hacer que un extension header se procese como parte de un
>> fragmento aceptado, que como parte de un paquete cualquiera.
> 
> Si, salvo una pequeña correción: Como parte de un fragmento *rechazado*
> Es decir, se procesa el extension header, se encola el fragmento que lo
> traía y despues cuando llega otro fragmento (potencialmente con otro
> extension header) del mismo datagama original (porque tiene el mismo
> Frag ID) se detecta un error (solapamiento, atomicidad, etc) y se
> descartan todos los fragmentos, pero los headers que traian
> (potencialmente contradictorios entre si) ya fueron procesados...
> 
> En que situación normal podría un host generar, a partir de un datagrama
> original, dos datagramas fragmentados y con solapamiento cada uno de
> ellos con extension headers distintos antes de la parte fragmentada? 

-- En ninguno.



> No
> se... me parece rarisimo y sin embargo es un condición aceptable por
> todos los RFC.

Coincido con vos. Ahora bien: existe alguna manera razonable de prevenirlo?

Porque en este caso no alcanza con chequear la existencia de
determinados extension headers, sino tambieén su contenido. (COmo
atacante, obviamente te enviaria fragmentos con toneladas de extension
headers delante de la parte fragmentada).

Y si apra cada fragmento vas a hacer semejante procesamiento, la
"solución" termina siendo peor que el problema.



>> Al menos sin pensarlo demasiado, no se me ocurre un escenario en el cual
>> "puedas hacer algo mas" 
> 
> ... famosas ultimas palabras... :)

Si, si, obvio. :-) O sea, mi argumento no fue "no se me ocurre nada ->
está todo bien".



>> en un extension header que es parte de un
>> fragmento, que en un extension header que es parte de un paquete cualquiera.
>>
> 
> Bueno creo que ya aburrimos lo suficiente a los lectores de la lista asi
> que a menos que a alguien mas le interese este asunto te propongo que si
> hace falta sigamos por fuera de la lista.

Aparentemente, no. :-)

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