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

From: Ofir Arkin (ofirat_private)
Date: Sat Apr 13 2002 - 13:30:20 PDT

  • Next message: Matt Conover: "w00w00 on Microsoft IE/Office for Mac OS"

    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: ofirat_private 
    



    This archive was generated by hypermail 2b30 : Tue Apr 16 2002 - 13:49:00 PDT