程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> PHP綜合 >> php強制轉換類型和CMS遠程管理插件的危險

php強制轉換類型和CMS遠程管理插件的危險

編輯:PHP綜合

遠程管理插件是十分受WordPress站點管理員歡迎的工具,它們允許用戶同時對多個站點執行相同的操作,如,更新到最新的發行版或安裝插件。然而,為了實現這些操作,客戶端插件需要賦予遠程用戶很大的權限。因此,確保管理服務器和客戶端插件之間的通信安全且不能被攻擊者偽造就變得相當重要了。本文將談及幾款可用插件,利用其弱點,攻擊者甚至可以完全危及到運行這些插件的站點。

ManageWP, InfiniteWP, and CMS Commander

這三個服務有著相同的客戶端插件基礎代碼(目測最初是ManageWp實現,然後另外兩個對其進行了調整),因而它們都有簽名繞過漏洞並且會導致遠程代碼執行。

管理服務器注冊一個客戶端插件的私鑰,用來計算每一條消息的消息認證碼,而不是要求用戶提供管理員憑證[MAC,我們平時看到它會將其當做硬件的MAC地址,這裡是Message Authentication Code ]。當一條消息通過使用共享密鑰的消息摘要算法後就生成了消息摘要。該MAC隨後附在消息後面一起發送出去,接收方收到後用共享秘鑰對收到的消息進行計算,生成MAC2,然後和MAC1進行比較。消息摘要用於驗證消息的真實性和完整性[學過密碼學的同學都應該知道],是一個確保通信安全的好方法,但是這三項服務的客戶端插件在實現上的缺陷導致了嚴重的漏洞。

一條由helper.class.php認證的傳入消息如下所示:

// $signature is the MAC sent with the message  
// $data is part of the message  
if (md5($data . $this->get_random_signature()) == $signature) {  
    // valid message  
}

使用非嚴格的等於意味著在比較前會發生類型“欺騙”[類型轉換]。md5()函數的輸出永遠都是字符串,但是如果$signature變了是一個整數,那麼比較時發生的類型轉換就容易偽造一個匹配的MAC。例如,如果真實的MAC是以”0”開頭,或者非數字字符開頭,那麼0就能匹配上,如果是”1xxx”這樣的,那麼整數1就能匹配,一次類推。[這裡其實是php的一個特性,當然其他語言也會有,當一個字符串和數字進行非嚴格等於的比較時,如果第一個字符是數字就會將其轉換成對應的整數進行比較,如果是非0-9的字符,就會將其當做0,php.net的說明:如果比較一個數字和字符串或者比較涉及到數字內容的字符串,則字符串會被轉換為數值並且比較按照數值來進行]。

字符串轉換為數值:

當一個字符串被當作一個數值來取值,其結果和類型如下:

如果該字符串沒有包含 '.','e' 或 'E' 並且其數字值在整型的范圍之內(由 PHP_INT_MAX 所定義),該字符串將被當成integer 來取值。其它所有情況下都被作為 float 來取值。

該字符串的開始部分決定了它的值。如果該字符串以合法的數值開始,則使用該數值。否則其值為 0(零)。合法數值由可選的正負號,後面跟著一個或多個數字(可能有小數點),再跟著可選的指數部分。指數部分由 'e' 或 'E' 後面跟著一個或多個數字構成。

<?php
var_dump(0 == "a"); // 0 == 0 -> true
var_dump("1" == "01"); // 1 == 1 -> true
var_dump("10" == "1e1"); // 10 == 10 -> true
var_dump(100 == "1e2"); // 100 == 100 -> true
    
 var_dump('abcdefg' == 0); // true 
 var_dump('1abcdef' == 1); // true 
 var_dump('2abcdef' == 2); // true  }
 ?>

遺憾的是,攻擊者可以提供一個整數作為簽名。init.php中,傳入的請求將會使用base64_decode()解碼,然後反序列化其結果。Unserialize()的使用意味著可以控制輸入數據的類型,一個偽造的序列化消息如下:

a:4:{s:9:"signature";i:0;s:2:"id";i:100000;s:6:"action";s:16:"execute_php_code";s:6:"params";a:2:{s:8:"username";s:5:"admin";s:4:"code";s:25:"exec('touch /tmp/owned');";}}

這條消息使用整數0作為簽名,然後使用插件提供的execute_php_code執行任意的PHP代碼。

$signature = 0;  
// $data is the action concatenated with the message ID  
$data = 'execute_php_code' . 100000;  
if (md5($data . $this->get_random_signature()) == $signature) {  
    // valid message if the output of  
    // md5() doesn't start with a digit  
}

查看本欄目

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved