Date: Tue, 8 May 2001 03:24:33 -0700 From: Kris Kennaway <kris@obsecurity.org> To: audit@FreeBSD.org Subject: ping security fixes Message-ID: <20010508032432.A91836@xor.obsecurity.org>
next in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
This patch is taken from OpenBSD. I don't know if the IP option stuff
is exploitable in theory -- we merged some option-parsing fixes a few
years ago, but missed the rest which were committed to OpenBSD a few
weeks later. The other buffer sizing issue doesn't seem to be
exploitable on FreeBSD for two reasons:
a) The receive buffer size is artificially limited to 48K
b) The send buffer size is not resized from the default value, and
ping limits the length of ICMP_ECHOREPLY packets it reads to 112 bytes
longer than the packet it sent out (I don't know if this is a bug or
not).
OpenBSD had removed both of these limitations which allowed them to
overflow that buffer by 68 bytes or so; even then I couldn't get it to
do anything nasty because of where the buffer sits in memory. Anyway.
Kris
Index: ping.c
===================================================================
RCS file: /mnt/ncvs/src/sbin/ping/ping.c,v
retrieving revision 1.55
diff -u -r1.55 ping.c
--- ping.c 2001/03/09 13:20:23 1.55
+++ ping.c 2001/05/08 10:18:22
@@ -102,7 +102,7 @@
/* runs out of buffer space */
#define MAXIPLEN 60
#define MAXICMPLEN 76
-#define MAXPACKET (65536 - 60 - 8)/* max packet size */
+#define MAXPAYLOAD (IP_MAXPACKET - MAXIPLEN - 8) /* max ICMP payload size */
#define MAXWAIT 10 /* max seconds to wait for response */
#define MAXALARM (60 * 60) /* max seconds for alarm timeout */
#define NROUTES 9 /* number of record route slots */
@@ -148,7 +148,7 @@
struct sockaddr whereto; /* who to ping */
int datalen = DEFDATALEN;
int s; /* socket file descriptor */
-u_char outpack[MAXPACKET];
+u_char outpack[IP_MAXPACKET]; /* Max packet size = 65535 */
char BSPACE = '\b'; /* characters written for flood */
char DOT = '.';
char *hostname;
@@ -341,7 +341,7 @@
err(EX_NOPERM, "-s flag");
}
ultmp = strtoul(optarg, &ep, 0);
- if (ultmp > MAXPACKET)
+ if (ultmp > MAXPAYLOAD)
errx(EX_USAGE, "packet size too large: %lu",
ultmp);
if (*ep || ep == optarg || !ultmp)
@@ -785,7 +785,7 @@
register struct icmp *icp;
register u_long l;
register int i, j;
- register u_char *cp,*dp;
+ register u_char *cp, *dp;
static int old_rrlen;
static char old_rr[MAX_IPOPTLEN];
struct ip *ip;
@@ -926,7 +926,8 @@
hlen -= 2;
j = *++cp;
++cp;
- if (j > IPOPT_MINOFF)
+ i = 0;
+ if (j > IPOPT_MINOFF) {
for (;;) {
l = *++cp;
l = (l<<8) + *++cp;
@@ -939,11 +940,18 @@
ina.s_addr = ntohl(l);
printf("\t%s", pr_addr(ina));
}
- hlen -= 4;
- j -= 4;
- if (j <= IPOPT_MINOFF)
- break;
- (void)putchar('\n');
+ hlen -= 4;
+ j -= 4;
+ i += 4;
+ if (j <= IPOPT_MINOFF)
+ break;
+ if (i >= MAX_IPOPTLEN) {
+ (void)printf("\t(truncated route)");
+ break;
+ }
+ (void)putchar('\n');
+ }
+
}
break;
case IPOPT_RR:
@@ -1002,6 +1010,8 @@
break;
default:
(void)printf("\nunknown option %x", *cp);
+ hlen = hlen + cp[1] - 1;
+ cp = cp + cp[1] - 1;
break;
}
if (!(options & F_FLOOD)) {
@@ -1402,7 +1412,7 @@
if (ii > 0)
for (kk = 0;
- kk <= MAXPACKET - (8 + PHDR_LEN + ii);
+ kk <= MAXPAYLOAD - (8 + PHDR_LEN + ii);
kk += ii)
for (jj = 0; jj < ii; ++jj)
bp[jj + kk] = pat[jj];
[-- Attachment #2 --]
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.5 (FreeBSD)
Comment: For info see http://www.gnupg.org
iD8DBQE698lfWry0BWjoQKURAkc0AJ99zBCatUjGzBdTdrpvG3uuEfYuIgCgquRP
GntaGMNMgXYgF19c1PX/v1g=
=jH05
-----END PGP SIGNATURE-----
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010508032432.A91836>
