Skip site navigation (1)Skip section navigation (2)
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>