从补丁到漏洞分析——记一次joomla漏洞应急

作者:LoRexxar'@知道创宇404实验室

发表时间:2018年2月7日

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,代码在这里通过执行formgetFieldset获取了提交的自定义字段信息。

跟入/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

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏FreeBuf

利用缓存服务形成的SSRF和其它客户端形式渗透

Edge Side Includes (ESI)标记语言主要用于各种流行的HTTP代理中(如反向代理、负载均衡、缓存服务器、代理服务器)解决网页缓存问题。早前我...

602
来自专栏用户3211691的专栏

前端面试题1(HTML篇)

html5有哪些新特性、移除了那些元素?如何处理HTML5新标签的浏览器兼容问题?如何区分 HTML 和 HTML5?

441
来自专栏IMWeb前端团队

video标签在不同平台上的事件表现差异分析

本文作者:IMWeb 张颖 原文出处:IMWeb社区 未经同意,禁止转载 video标签属性和事件介绍 为了文章的完整性,首先还是列举一下video标...

2476
来自专栏我的小碗汤

Go语言IDE GoLand的BUG

GoLand 是 Jetbrains 推出的 Golang IDE,在内侧阶段我就开始使用了,刚出的时候我还在博客中发表过文章(看了下日期是 16 年年底)。

1043
来自专栏谦谦君子修罗刀

程序员面试闪充--iOS密码学

但凡一个有点追求的iOS开发,总得会点加密技术,要不然用户信息就有可能被其他人获取用来做一些对我们不利的事情。 视频地址: 密码学 一、base64 base6...

29910
来自专栏黑白安全

WAF绕过的一些总结和思考

WAF分类: 1.网络层类 2.最常见且容易部署的应用层类 (部署在APAC++HE之前,APAC++HE之后) 应用层WAF – 利用WAF自身缺陷和M...

602
来自专栏向治洪

React Native组件只Image

不管在Android还是在ios原生的开发中,图片都是作为控件给出来的,在RN中也有这么一个控件(Image)。根据官网的资料,图片分为本地静态图片,网络图片和...

1967
来自专栏Seebug漏洞平台

Django CSRF Bypass (CVE-2016-7401) 漏洞分析

Author: p0wd3r (知道创宇404安全实验室) Date: 2016-09-28 0x00 漏洞概述 1.漏洞简介 Django是一个由Python...

2855
来自专栏FreeBuf

见招拆招:绕过WAF继续SQL注入常用方法

Web Hacker总是生存在与WAF的不断抗争之中的,厂商不断过滤,Hacker不断绕过。WAF bypass是一个永恒的话题,不少基友也总结了很多奇技怪招。...

1885
来自专栏点滴积累

geotrellis使用(二十三)动态加载时间序列数据

目录 前言 实现方法 总结 一、前言        今天要介绍的绝对是华丽的干货。比如我们从互联网上下载到了一系列(每天或者月平均等)的MODIS数据,我们怎么...

3156

扫码关注云+社区