8297503 2002-04-13 21:30 +0100  /137 rader/ Ofir Arkin <ofir@atstake.com>
Sänt av: joel@lysator.liu.se
Importerad: 2002-04-16  22:49  av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <21854>
Ärende: A crash course with Linux Kernel 2.4.x, IP ID values & RFC 791
------------------------------------------------------------
From: Ofir Arkin <ofir@atstake.com>
To: bugtraq@securityfocus.com
Message-ID: <3CB8955C.10407@atstake.com>

This is an update of my original postings about the IP ID handling in 
the ICMP and UDP protocols with Linux Kernel 2.4.x.


RFC 791 defines the IP Identification field as:
"An identifying value assigned by the sender to aid in assembling the 
fragments of a datagram."

RFC 791 identifies the role of the Identification field as: "The
internet fragmentation and reassembly procedure needs to be able to
break a datagram into an almost arbitrary number of pieces that can
be  later reassembled.  The receiver of the fragments uses the
identification field to ensure that fragments of different datagrams
are  not mixed."

and

"The identification field is used to distinguish the fragments of one 
datagram from those of another."

While the IP identification value is only used for IP fragment 
reassembly and is not used in cases where the DF flag is set, the RFC 
states that

"... the identification field to a value that must be unique for that 
source-destination pair and protocol for the time the datagram will be 
active in the internet system."

Some may argue that when the packet is not to be fragmented there is
no  room for an IP identification value, since its usage is futile in
this  case.  While this does not impact the normal operations of the
IP  protocol, it does violate the RFC and might prove harmful by
allowing  simplified OS fingerprinting.

If we have an exploit targeting only Linux 2.4.x kernel-based
machines,  for example, and our problem is to identify those
machines, we will need  only 1 extra packet to send to questionable
IP addresses before deciding  on a match.


The Linux Kernel 2.4.x way:
Linux Kernel 2.4.x is using IP ID values of zero in several 
circumstances, whenever the DF is set:

ICMP: Kernel 2.4.0-2.4.4 will use the value of zero (0) for the IP ID
field  value whenever sending an ICMP query messages or producing
ICMP replies.

This behavior was changed with Kernel 2.4.5 and above, and now only
when  generating ICMP query messages the IP ID field value will be
set to zero.

If the Linux Kernel 2.4.x IP stack implementation is to comply with
the  same rule regarding the DF bit and the IP identification field
value  (0), why the IP ID field value was changed when the DF bit is
set with  ICMP replies with Kernel 2.4.5 and after?


UDP: Whenever sending or answering for a UDP datagram the IP ID will
be zero  when the DF bit will be set.

Sending:
03/16-11:49:41.531642 192.168.1.200:1024 -> x.x.x.x:53 UDP TTL:64 
TOS:0x0 ID:0 IpLen:20 DgmLen:63 DF
Len: 43
BC 0D 01 00 00 01 00 00 00 00 00 00 03 77 77 77  .............www
03 63 6E 6E 03 63 6F 6D 05 6C 6F 63 61 6C 00 00  .cnn.com.local..
01 00 01 

Replying:
03/16-12:13:17.388211 192.168.1.200:1775 -> y.y.y.y:7
UDP TTL:64 TOS:0x0 ID:28256 IpLen:20 DgmLen:28
Len: 8

03/16-12:13:17.547636 y.y.y.y:7 -> 192.168.1.200:1775
UDP TTL:50 TOS:0x0 ID:0 IpLen:20 DgmLen:28 DF
Len: 8


TCP:
In several circumstances, like a SYN-ACK answer for a SYN, the IP ID 
will be zero when the DF bit will be set.

21:45:36.779241 192.168.1.5.31682 > 192.168.1.25.ssh: S [tcp sum ok]
2372425889:2372425889(0) win 16384 <mss 1460,nop,nop,sackOK,nop,wscale 
0,nop,nop,timestamp 329650873 0> (DF) (ttl 64, id 12445, len 64)
0x0000     4500 0040 309d 4000 4006 86ac c0a8 0105    E..@0.@.@.......
0x0010     c0a8 0119 7bc2 0016 8d68 58a1 0000 0000    ....{....hX.....
0x0020     b002 4000 ea50 0000 0204 05b4 0101 0402    ..@..P..........
0x0030     0103 0300 0101 080a 13a6 12b9 0000 0000    ................

21:45:36.779241 192.168.1.25.ssh > 192.168.1.5.31682: S [tcp sum ok]
3107930066:3107930066(0) ack 2372425890 win 5792 <mss 
1460,sackOK,timestamp 101376 329650873,nop,wscale 0> (DF) (ttl 64, id 0, 
len 60)
0x0000     4500 003c 0000 4000 4006 b74d c0a8 0119    E..<..@.@..M....
0x0010     c0a8 0105 0016 7bc2 b93f 3fd2 8d68 58a2    ......{..??..hX.
0x0020     a012 16a0 a092 0000 0204 05b4 0402 080a    ................
0x0030     0001 8c00 13a6 12b9 0103 0300              ............



The bottom line is that this behavior will allow a _very_ easy
identification of _any_ Kernel 2.4.x based Linux machine. I do not
need  to go over again why having predictable IP ID values is wrong
in the  first place.

Using a random value for the IP ID not only enhances security but also 
reduces the ability to accurately fingerprint the IP stack using this 
parameter.


Related Previous Bugtraq Posts:
Fingerprinting Linux Kernel 2.4.x based machines using ICMP
http://www.sys-security.com/archive/bugtraq/ofirarkin2001-03.txt

Fun with IP Identification Field Values (Identifying Older MS Based
OSs) http://www.sys-security.com/archive/bugtraq/ofirarkin2001-02.txt

Several Misbehaviors with the ICMP implementation (and the 'ping' 
utility) with MS based operating systems
http://www.sys-security.com/archive/bugtraq/ofirarkin2001-01.txt

-- 
Ofir Arkin
Managing Security Architect
@stake, Inc.
http://www.atstake.com
email: ofir@atstake.com
(8297503) /Ofir Arkin <ofir@atstake.com>/-(Ombruten)