本文來自i春秋作者:索馬里的海賊

前言

一篇說了一般審計中的流程,有的時候我們的目的并不是完整的審計一套系統,而是在搞事的過程中發現目標站或者旁站或者關聯站點為開源cms,這時候的目的是盡快拿到可利用的漏洞。這時候當然也可以按部就班慢慢從框架流程看起,不過估計大伙都沒這個心思,那么再來說說一些快速發現的漏洞挖掘方法。

一、關注重點

為了搞事,所以當然是從比較嚴重的問題開始看,xss csrf這些留到最后,先看命令執行,文件操作,sql這3塊。這次主要說sql(因為發現的就是sql注入) sql注入快速挖掘,第一步先看有沒有全局的防御機制 比如很多cms都會在全局配置文件里有這么一塊

foreach(array('_GET','_POST','_COOKIE') as $key=>$value){
        $key = daddslashes($value);//daddslashes是addslashes函數的擴展版 增加了對數組的循環轉義
}

比如這次目標Mlecms的代碼 inc/include/globals.php行24

foreach(array('_GET','_POST','_COOKIE') as $_request){
        foreach($_request as $i => &$n){
                ${$i} = daddslashes($n);
        }
}

類似這樣的代碼,把GPC的內容都轉義了一遍 碰上這樣的情況 就不要再去想簡單的跟蹤請求參數來注入了 直接去找能重新引入單引號或者反斜杠的地方 比如下面的一些例子

> substr() //取到轉義處,留下反斜杠
> $sth['xx'] //當變量為字符串時 取的是xx位置的一個字符
> stripslashes() //這三個就不解釋了
> urldecode() //這三個就不解釋了
> base64_decode() //這三個就不解釋了
> parse_str() //parse_str之前會先urldecode

或者直接找除了GPC之外的能提交的內容 比如常見的X-Forwarded-For的注入 referer的注入 它們都來自$_SERVER數組 而且經常被認為是安全的而不進行處理。當然現在大伙兒(碼農)意識都高了(其實是被搞怕了) 再不濟也知道從X-Forwarded-For取到IP之后做個轉義,更多的是拿到IP之后用正則校驗一下是不是正常的IP 比如目標CMS

function get_ip(){
        if(!empty($_SERVER["HTTP_CLIENT_IP"])){
                $cip = $_SERVER["HTTP_CLIENT_IP"];
        }else if(!empty($_SERVER["HTTP_X_FORWARDED_FOR"])){
                $cip = $_SERVER["HTTP_X_FORWARDED_FOR"];
        }else if(!empty($_SERVER["REMOTE_ADDR"])){
                $cip = $_SERVER["REMOTE_ADDR"];
        }else{
                $cip = '';
        }
        preg_match("/[\d\.]{7,15}/",$cip,$cips);
        $cip = isset($cips[0]) ? $cips[0] : 'unknown';
        unset($cips);
        return $cip;
}

可以看到最后用/[\d\.]{7,15}/這條正則匹配了一下 這里不說這樣判斷IP是否正確,至少除了數字和點之外 混不進其他字符了??沒有了單引號也就幾乎沒有了注入的可能。

二、實戰

上一段說了不少能引入單引號或者繞過全局轉義的地方,那么就來實戰一下 這里從$_SERVER開始,為了快速發現問題 一些搜索技巧必須熟練 比如這里我用的一條正則

(SELECT|INSERT|UPDATE|DELETE).*\$_SERVER

簡單給不懂正則的童鞋解釋一下這條正則的意思是 有(SELECT|INSERT|UPDATE|DELETE)其中之一且后面出現了$_SERVER 如果能在sql語句拼接中出現不會被轉義的$_SERVER內容的話,很有可能就是一個注入了 不得不說,審代碼 運氣也很重要,還真被我搜到一處

inc/lib/admin.lib.php 行46

public static function logs($type,$info){
            global $db,$admin_config,$gmt_time;
            if($admin_config['logs_open'] == 1){
                    $sql = "INSERT INTO `{$db->prefix}logs` (`type`,`info`,`pageurl`,`lang`,`username`,`ip`,`ipaddress`,`addtime`) VALUES ('{$type}','{$info}','http://{$_SERVER['SERVER_NAME']}".substr(get_url(),0,200)."','".LANG."','{$_SESSION['admin']['login']['username']}','".get_ip()."','".ip::get_address(get_ip())."','".$gmt_time."');";
                    $db->execute($sql);
                }

$_SERVER['SERVER_NAME']被拼進了sql語句,$_SERVER['SERVER_NAME']是什么鬼,能吃么?能偽造么? 答案是肯定的 來看看php官方對SERVER_NAME的定義

中文版

'SERVER_NAME' 當前運行腳本所在的服務器的主機名。如果腳本運行于虛擬主機中,該名稱是由那個虛擬主機所設置的值決定。

英文版

'SERVER_NAME' The name of the server host under which the current script is executing. If the script is running on a virtual host, this will be the value defined for that virtual host.

Note: Under Apache 2, you must set UseCanonicalName = On and ServerName. Otherwise, this value reflects the hostname supplied by the client, which can be spoofed. It is not safe to rely on this value in security-dependent contexts.

有沒有發現 英文版多了點東西 簡單翻譯一下: 在apache2 下 如果你沒有設置ServerName或者沒有把UseCanonicalName 設置為 On的話,這個值就會是客戶端提供的hostname??不安全喲

所以老師說英語學得好 爸爸回家早 噢不 滲透搞得好

那么這個客戶端提供的hostname是什么鬼呢,其實就是http包中的Host: 字段的值

那么又有人說了,如果修改了Host字段的值,那配置了ServerName的web容器怎么判斷是哪個虛擬主機呢

這里就要說另一個有意思的事了,如果我們的http包中有兩個或者多個Host值 會是什么情況呢

對于apache來說,不管你有多少個 它只取第一個

對于php來說,不管你有多少個,它全要了 是的 全要了。。 比如

Host:a.com Host:b.com

php的$_SERVER['SERVER_NAME']會取到 a.com, b.com 用逗號分隔的兩個host值 這下就好辦了

三、利用

logs函數在后臺登陸的時候會被調用,不管登錄成功與否,都會調用logs()函數寫入登錄記錄,利用的話??隨便填賬號密碼? ?burp或者fiddler攔下來 添加一個Host頭 然后查看結果就好了

如圖

總結

寫文章好累。。。

快速漏洞挖掘需要積累常見漏洞觸發點,函數,語言特性等等。 順便建議不會正則的看看正則表達式入門,提高搜索效率、挖漏洞也能碰上不少正則,到時候看不懂錯失0day就虧了。

原文地址:http://bbs.ichunqiu.com/thread-13714-1-1.html?from=seebug


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/78/