1、媒介
不知怎的比來甚是忖量校園糊口,忖量食堂的炒飯。那時(shí)會(huì)往各類安然bbs上刷刷帖子,喜好看他人寫的一些關(guān)于安然技能或經(jīng)驗(yàn)的總結(jié);那時(shí)BBS上良多文章標(biāo)題問題都是:成功滲入XXX,成功拿下XXX。這里便以一篇進(jìn)侵菲律賓某大年夜學(xué)的文章引出文章的主題,我們先簡要看一下過程。大年夜學(xué)網(wǎng)站利用了名為joomla的開源web法度,(1)青年利用一個(gè)joomla已公開的縫隙進(jìn)進(jìn)web后臺(tái)(2)青年利用joomla后臺(tái)上傳限制不嚴(yán)的缺點(diǎn)上傳了一個(gè)webshell(3)節(jié)制主機(jī)贈(zèng)予我國國旗。
本來進(jìn)侵一臺(tái)主機(jī)如斯等閑,治理員判斷給web法度打上安然補(bǔ)丁。治理員的工作是結(jié)束了,作為安然從業(yè)人員再一想是不是是joomla后臺(tái)這里可以上傳webshell是不是是有標(biāo)題問題呢,假定joomla后臺(tái)不克不及上傳webshell,是不是是可以削減進(jìn)侵的可能和損掉。下面進(jìn)進(jìn)本文的主題:web后臺(tái)法度的安然性。
2、簡介
國內(nèi)良多站點(diǎn)都是基于開源論壇、cms搭建的,好比discuz、phpwind、dedecms等。這些法度都是國內(nèi)開源web法度中的佼佼者,也比較重視安然性。平常平凡大年夜家存眷比較多的是sql注進(jìn)、xss這些可以直接盜取用戶數(shù)據(jù)的縫隙。網(wǎng)上因?yàn)槿蹩诹畋贿M(jìn)侵的案例數(shù)不堪數(shù),別的用戶數(shù)據(jù)泄漏事務(wù)時(shí)而產(chǎn)生,純真靠暗碼防護(hù)的后臺(tái)被沖破,被社工的可能性愈來愈大年夜。獲得一個(gè)治理后臺(tái)暗碼后,再連絡(luò)后臺(tái)法度的肆意代碼履行、文件包含或號令注進(jìn)等縫隙獲得一個(gè)shell,盜取用戶資料不是甚么難事。此時(shí)后臺(tái)法度的安然性成為一個(gè)短板。
Discuz是一款風(fēng)行的論壇法度,筆者這里就以它的后臺(tái)法度為例簡單闡發(fā)一下其安然性,下面直接看一些縫隙案例(Discuz最新版本已打補(bǔ)丁,請用戶及時(shí)進(jìn)級到最新版-Discuz! X3.1 R20140101)。
3、案例闡發(fā)
Tips:下文提到的$settingnew是discuz后臺(tái)存儲(chǔ)表單數(shù)據(jù)的變量,后臺(tái)用戶可控。
案例一:用戶輸進(jìn)數(shù)據(jù)過濾邏輯不當(dāng)
縫隙文件:X3\source\admincp\admincp_setting.php
闡發(fā):
// 1、alice點(diǎn)竄$settingnew['extcredits']非數(shù)組
if(is_array($settingnew['extcredits'])) {
foreach($settingnew['extcredits'] as $key => $value) {
// 2、給$settingnew['initcredits'][1]傳進(jìn)phpinfo();,非數(shù)組繞過intval轉(zhuǎn)換
$settingnew['initcredits'][$i] = intval($settingnew['initcredits'][$i]);
... 省略 ...
for($i = 1; $i <= 8; $i++) {
// 3、 phpinfo();被賦值給$initformula
$initformula = str_replace('extcredits'.$i, $settingnew['initcredits'][$i], $initformula);
}
// 4、phpinfo()帶進(jìn)eval履行
eval("\$_G['setting']['initcredits'] = round($initformula);");
案例二:二次注進(jìn)
簡單介紹一下二次注進(jìn),歹意用戶alice在A處傳進(jìn)歹意數(shù)據(jù)并被存儲(chǔ)到數(shù)據(jù)庫,在A處不直接導(dǎo)致安然標(biāo)題問題;B處援引到A處存儲(chǔ)的數(shù)據(jù),從而觸發(fā)安然標(biāo)題問題。
縫隙文件:X3\source\admincp\admincp_setting.php
闡發(fā):
// 1、alice上傳一個(gè)圖片木馬假定為1.gif; alice設(shè)置$settingnew['seccodedata']['type']值為1.gif\0:xx(按照圖片地址做恰當(dāng)目次跳轉(zhuǎn));該值未作任何過濾存進(jìn)數(shù)據(jù)庫
if($settingnew['seccodedata']['type'] == 0 || $settingnew['seccodedata']['type'] == 2) {
$seccoderoot = 'static/image/seccode/font/en/';
} elseif($settingnew['seccodedata']['type'] == 1) {
$seccoderoot = 'static/image/seccode/font/ch/';
}
縫隙文件:source\module\misc\misc_seccode.php
// 2、$_G['setting']['seccodedata']['type']值來自于數(shù)據(jù)庫,即為1處傳進(jìn)的1.gif\0:xx
if(!is_numeric($_G['setting']['seccodedata']['type'])) {
$etype = explode(':', $_G['setting']['seccodedata']['type']);
if(count($etype) >1) {
// 3、 \0截?cái)喃@得$codefile為圖片小馬(也可利用././././多個(gè)路徑符編制截?cái)?
$codefile = DISCUZ_ROOT.'./source/plugin/'.$etype[0].'/seccode/seccode_'.$etype[1].'.php';
... 省略 ...
if(file_exists($codefile)) {
// 4、圖片木馬被include獲得webshell
@include_once $codefile;
案例三:法度進(jìn)級新增邏輯導(dǎo)致的縫隙
縫隙文件:X3\source\admincp\admincp_adv.php
// 1、alice上傳一個(gè)圖片木馬假定為1.gif; alice傳進(jìn)type參數(shù)值為1.gif\0:xx(按照圖片地址做恰當(dāng)目次跳轉(zhuǎn))
$type = $_GET['type'];
... ...
if($type) {
//2、獲得$etype為1.gif\0
$etype = explode(':', $type);
if(count($etype) >1) {
//3、$advfile值被\0截?cái)?,為圖片木馬路徑1.gif
$advfile = DISCUZ_ROOT.'./source/plugin/'.$etype[0].'/adv/adv_'.$etype[1].'.php';
$advclass = 'adv_'.$etype[1];
}
... 省略 ...
//4、包含圖片木馬,獲得webshell
if(file_exists($advfile)) {
require_once $advfile;
對比下X2.5版本的邏輯,此處縫隙美滿是因?yàn)樾略龃a導(dǎo)致的。
$type = $_GET['type'];
$target = $_GET['target'];
$typeadd = '';
if($type) {
$advfile = libfile('adv/'.$type, 'class');
if(file_exists($advfile)) {
require_once $advfile;
案例四:縫隙修補(bǔ)不完美
縫隙文件:X3\api\uc.php
闡發(fā):
//1、config_ucenter.php內(nèi)容部門截取以下:define('UC_API', 'http://localhost/bbs/uc_server');
$configfile = trim(file_get_contents(DISCUZ_ROOT.'./config/config_ucenter.php'));
... ...
//2、$UC_AP外部可控,alice傳進(jìn)$UC_API的值為xyz');eval($_POST[cmd];
獲得$configfile值為define('UC_API', 'xyz\');eval($_POST[cmd];'); xyz后面的引號被轉(zhuǎn)義。
$configfile=preg_replace("/define\('UC_API',\s*'.*?'\);/i",
"define('UC_API','".addslashes($UC_API)."');", $configfile);
//3、將define('UC_API', 'xyz\');eval($_POST[cmd];');寫進(jìn)建設(shè)文件
if($fp = @fopen(DISCUZ_ROOT.'./config/config_ucenter.php', 'w')) {
@fwrite($fp, trim($configfile));
@fclose($fp);
}
//4、alice再次傳進(jìn)$UC_API的值為xyz,preg_replace利用的正則表達(dá)式是
define\('UC_API',\s*'.*?'\); .*?'非貪婪匹配,匹配到第一個(gè)引號結(jié)束,
之前的轉(zhuǎn)義符被替代xyz\替代為xyz,從而獲得$configfile值為
define('UC_API', 'xyz');eval($_POST[cmd];');寫進(jìn)建設(shè)文件獲得webshell。
這個(gè)標(biāo)題問題早在2010年外部已公開,官方已及時(shí)發(fā)出補(bǔ)丁
詳情請參考:http://www.oldjun.com/blog/index.php/archives/76/
4、總結(jié)
上面這些例子主如果筆者實(shí)踐經(jīng)驗(yàn)的一些總結(jié),不必然周全,??茨芙o大年夜家拓展一些思路;好比上述提到的二次注進(jìn),$settingnew['seccodedata']['type']這個(gè)變量沒過濾,$settingnew的其他數(shù)組也可能沒過濾,也確切存在多處近似的標(biāo)題問題,大年夜家可以自行往測驗(yàn)測驗(yàn)一下。關(guān)于代碼審計(jì)的編制首要有兩個(gè)大年夜標(biāo)的目標(biāo):(1)危險(xiǎn)函數(shù)向上追蹤輸進(jìn);(2)追蹤用戶輸進(jìn)是不是進(jìn)進(jìn)危險(xiǎn)函數(shù);這里的危險(xiǎn)函數(shù)關(guān)于危險(xiǎn)函數(shù)首要包含代碼履行相干:eval、assert,文件包含:include、require等,號令履行:system、exec等,寫文件:fwrite、file_put_contents等;
代碼審計(jì)的編制這里保舉兩篇文章:
https://code.谷歌.com/p/pasc2at/wiki/SimplifiedChinese
http://wenku.百度.com/view/c85be95a3b3567ec102d8a12.html
5、反思
1、一切輸進(jìn)都是有害的;
后臺(tái)法度的用戶輸進(jìn)比擬前臺(tái)首要增加了后臺(tái)表單的數(shù)據(jù),別的有些后臺(tái)撐持上傳文件(如dz1.5的自定義sql),上傳文件的內(nèi)容也屬于輸進(jìn);這些輸進(jìn)都屬于用戶范圍。必然要做嚴(yán)格的節(jié)制和過濾。
2、安然意識;
其實(shí)良多縫隙的產(chǎn)生其實(shí)不是手藝標(biāo)題問題導(dǎo)致的,而是我們貧乏安然意識,不正視安但是變成的悲劇。特別是第三個(gè)和第四個(gè),完全不該該產(chǎn)生;需要對開辟人員做安然宣導(dǎo)和根基的安然培訓(xùn)。
3、縫隙Review;
(1)開辟人員收到縫隙后要對縫隙產(chǎn)生的啟事做總結(jié),并Review代碼中是不是有近似的標(biāo)題問題。有些時(shí)辰開辟人員僅僅是修補(bǔ)了安然人員或白帽子供給的縫隙點(diǎn),別的一處代碼有近似的標(biāo)題問題沒修補(bǔ)繼續(xù)爆出漏洞,無限無盡。如許做還會(huì)帶來更大年夜的隱患,黑客是很是甘愿答應(yīng)并善于總結(jié)反思的,每個(gè)補(bǔ)丁其實(shí)也是給黑客拓展了思路,假定修補(bǔ)不完全后果很嚴(yán)重。
(2)開辟人員修補(bǔ)完成后安然人員需要進(jìn)行測試確認(rèn),上述的案例四就是光鮮的例子。有前提的環(huán)境下安然人員應(yīng)當(dāng)清算一些常見縫隙修復(fù)指引,如許也能夠進(jìn)步工作效力。