[25074] in bugtraq

home help back first fref pref prev next nref lref last post

A crash course with Linux Kernel 2.4.x, IP ID values & RFC 791

daemon@ATHENA.MIT.EDU (Ofir Arkin)
Tue Apr 16 16:51:19 2002

Message-ID: <3CB8955C.10407@atstake.com>
Date: Sat, 13 Apr 2002 21:30:20 +0100
From: Ofir Arkin <ofir@atstake.com>
MIME-Version: 1.0
To: bugtraq@securityfocus.com
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

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 




home help back first fref pref prev next nref lref last post