作者:LoRexxar'@知道創宇404實驗室
英文版本:http://www.bjnorthway.com/986/
2018年1月30日,joomla更新了3.8.4版本,這次更新修復了4個安全漏洞,以及上百個bug修復。
https://www.joomla.org/announcements/release-news/5723-joomla-3-8-4-release.html
為了漏洞應急這幾個漏洞,我花費了大量的時間分析漏洞成因、尋找漏洞觸發位置、回溯邏輯,下面的文章比起漏洞分析來說,更接近我思考的思路,希望能給大家帶來不一樣的東西。
背景
其中的4個安全漏洞包括
- Low Priority - Core - XSS vulnerability in module chromes (affecting Joomla 3.0.0 through 3.8.3)
- Low Priority - Core - XSS vulnerability in com_fields (affecting Joomla 3.7.0 through 3.8.3)
- Low Priority - Core - XSS vulnerability in Uri class (affecting Joomla 1.5.0 through 3.8.3)
- Low Priority - Core - SQLi vulnerability in Hathor postinstall message (affecting Joomla 3.7.0 through 3.8.3)
根據更新,我們去到github上的joomla項目,從中尋找相應的修復補丁,可以發現,4個安全漏洞的是和3.8.4的release版同時更新的。
https://github.com/joomla/joomla-cms/commit/0ec372fdc6ad5ad63082636a0942b3ea39acc7b7
通過補丁配合漏洞詳情中的簡單描述我們可以確定漏洞的一部信息,緊接著通過這部分信息來回溯漏洞成因。
SQLi vulnerability in Hathor postinstall message
https://developer.joomla.org/security-centre/722-20180104-core-sqli-vulnerability.html
Description
The lack of type casting of a variable in SQL statement leads to a SQL injection vulnerability in the Hathor postinstall message.
Affected Installs
Joomla! CMS versions 3.7.0 through 3.8.3
補丁分析
第一個漏洞說的比較明白,是說在Hathor的postinstall信息處,由于錯誤的類型轉換導致了注入漏洞。
我們來看看相應的補丁

符合漏洞描述的點就是這里,原來的取第一位改為了對取出信息做強制類型轉換,然后拼接入sql語句。
這里假設我們可以控制$adminstyle,如果我們通過傳入數組的方式設置該變量為數組格式,并且第1個字符串可控,那么這里就是一個可以成立的漏洞點。
現在我們需要找到這個功能的位置,并且回溯變量判斷是否可控。
找到漏洞位置
hathor是joomla自帶的兩個后臺模板之一,由于hathor更新迭代沒有isis快,部分功能會缺失,所以在安裝完成之后,joomla的模板為isis,我們需要手動設置該部分。
Templates->styles->adminnistrator->hathor

修改完成后回到首頁,右邊就是postinstallation message

回溯漏洞
回到代碼中,我們需要找到$adminstyle這個變量進入的地方。
$adminstyle = $user->getParam('admin_style', '');
這里user為JFactory::getUser(),跟入getParam方法
/libraries/src/User/User.php line 318
public function getParam($key, $default = null)
{
return $this->_params->get($key, $default);
}
這里$this->_params來自$this->_params = new Registry;
跟入Registry的get方法
libraries/vendor/joomla/registry/src/Registry.php line 201
public function get($path, $default = null)
{
// Return default value if path is empty
if (empty($path))
{
return $default;
}
if (!strpos($path, $this->separator))
{
return (isset($this->data->$path) && $this->data->$path !== null && $this->data->$path !== '') ? $this->data->$path : $default;
}
// Explode the registry path into an array
$nodes = explode($this->separator, trim($path));
// Initialize the current node to be the registry root.
$node = $this->data;
$found = false;
// Traverse the registry to find the correct node for the result.
foreach ($nodes as $n)
{
if (is_array($node) && isset($node[$n]))
{
$node = $node[$n];
$found = true;
continue;
}
if (!isset($node->$n))
{
return $default;
}
$node = $node->$n;
$found = true;
}
if (!$found || $node === null || $node === '')
{
return $default;
}
return $node;
}
根據這里的調用方式來看,這里會通過這里的的判斷獲取是否存在adminstyle,如果沒有則會返回default(這里為空)

接著回溯$this->data,data來自$this->data = new \stdClass;
回溯到這里可以發現$admin_style的地方是從全局變量中中讀取的。
默認設置為空/administrator/components/com_users/models/forms/user.xml

但我們是可以設置這個的
后臺users->users->super user設置,右邊我們可以設置當前賬戶使用的后臺模板,將右邊修改為使用hathor型模板。
通過抓包我們可以發現,這里顯式的設置了當前賬戶的admin_type,這樣如果我們通過傳入數組,就可以設置admin_type為任意值

然后進入代碼中的數據庫操作
/administrator/templates/hathor/postinstall/hathormessage.php function hathormessage_postinstall_condition

訪問post_install頁面觸發

XSS vulnerability in com_fields
https://developer.joomla.org/security-centre/720-20180102-core-xss-vulnerability.html
Description
Inadequate input filtering in com_fields leads to a XSS vulnerability in multiple field types, i.e. list, radio and checkbox.
Affected Installs
Joomla! CMS versions 3.7.0 through 3.8.3
補丁分析

漏洞詳情寫了很多,反而是補丁比較模糊,我們可以大膽猜測下,當插入的字段類型為list、radio、checkbox多出的部分變量沒有經過轉義
首先我們需要先找到觸發點
后臺content->fields->new,然后設置type為radio,在鍵名處加入相應的payload

然后保存新建文章

成功觸發
漏洞分析
由于補丁修復的方式比較特殊,可以猜測是在某些部分調用時使用了textContent而不是nodeValue,在分析變量時以此為重點。
漏洞的出發點/administrator/components/com_fields/libraries/fieldslistplugin.php line 31

由于找不到該方法的調用點,所以我們從觸發漏洞的點分析流程。
編輯文章的上邊欄是通過administrator/components/com_content/views/article/tmp/edit.php line 99載入的

這里JLayoutHelper:render會進入/layouts/joomla/edit/params.php
然后在129行進入JLayoutHelper::render('joomla.edit.fieldset', $displayData);

跟入/layouts/joomla/edit/fieldset.php line 16,代碼在這里通過執行form的getFieldset獲取了提交的自定義字段信息。

跟入/libraries/src/Form/Form.php line 329 function getFieldset

跟如1683行 findFieldsByFieldset函數。

這里調用xml來獲取數據,從全局的xml變量中匹配。
這里的全局變量中的xml中的option字段就來自于設置時的$option->textContent,而只有list, radio and checkbox.這三種是通過這里的函數做處理,其中list比較特殊,在后面的處理過程中,list類型的自定義字段會在/libraries/cms/html/select.php line 742 function options被二次處理,但radio不會,所以漏洞存在。

整個xss漏洞從插入到觸發限制都比較大,實戰價值較低。
XSS vulnerability in Uri class
https://developer.joomla.org/security-centre/721-20180103-core-xss-vulnerability.html
Description
Inadequate input filtering in the Uri class (formerly JUri) leads to a XSS vulnerability.
Affected Installs
Joomla! CMS versions 1.5.0 through 3.8.3
補丁分析
比起其他幾個來說,這里的漏洞就屬于特別清晰的,就是在獲取系統變量時,沒做相應的過濾。

前臺觸發方式特別簡單,因為這里的script_name是獲取基礎url路徑的,會拼接進所有頁面的和鏈接有關系的地方,包括js或者css的引入。
漏洞利用
讓我們來看看完整的代碼
if (strpos(php_sapi_name(), 'cgi') !== false && !ini_get('cgi.fix_pathinfo') && !empty($_SERVER['REQUEST_URI']))
{
// PHP-CGI on Apache with "cgi.fix_pathinfo = 0"
// We shouldn't have user-supplied PATH_INFO in PHP_SELF in this case
// because PHP will not work with PATH_INFO at all.
$script_name = $_SERVER['PHP_SELF'];
}
else
{
// Others
$script_name = $_SERVER['SCRIPT_NAME'];
}
static::$base['path'] = rtrim(dirname($script_name), '/\\');
很明顯只有當$script_name = $_SERVER['PHP_SELF']的時候,漏洞才有可能成立
只有當php是fastcgi運行,而且cgi.fix_pathinfo = 0時才能進入這個判斷,然后利用漏洞還有一個條件,就是服務端對路徑的解析存在問題才行。
http://127.0.0.1/index.php/{evil_code}/321321
--->
http://127.0.0.1/index.php
當該路徑能被正常解析時,http://127.0.0.1/index.php/{evil_code}就會被錯誤的設置為基礎URL拼接入頁面中。

一個無限制的xss就成立了
XSS vulnerability in module chromes
https://developer.joomla.org/security-centre/718-20180101-core-xss-vulnerability.html
Description
Lack of escaping in the module chromes leads to XSS vulnerabilities in the module system.
Affected Installs
Joomla! CMS versions 3.0.0 through 3.8.3
補丁分析

漏洞存在的點比較清楚,修復中將$moduleTag進行了一次轉義,同樣的地方有三處,但都是同一個變量導致的。
這個觸發也比較簡單,當我們把前臺模板設置為protostar(默認)時,訪問前臺就會觸發這里的modChrome_well函數。
漏洞利用
讓我們看看完整的代碼

很明顯后面module_tag沒有經過更多處理,就輸出了,假設我們可控module_tag,那么漏洞就成立。
問題在于怎么控制,這里的函數找不到調用的地方,能觸發的地方都返回了傳入的第二個值,猜測和上面的get_param一樣,如果沒有設置該變量,則返回default值。
經過一番研究,并沒有找到可控的設置的點,這里只能暫時放棄。
ref
- Joomla 3.8.4 https://www.joomla.org/announcements/release-news/5723-joomla-3-8-4-release.html
- Joomla security patches https://developer.joomla.org/security-centre/
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/529/