Check Point公司的研究员最近在Magento电子商务网络平台上发现了一个危险的远程代码执行(RCE)漏洞,该漏洞会导致Magento平台上的电子商铺全部被黑客所控制,包括信用卡信息和一些其他的财产信息和个人信息,已经有大约二十万的网上商城受到了这个漏洞的影响。
Check Point公司在公开这个漏洞之前,已经私下将其披露给了eBay公司,并建议eBay公司立即修复这个漏洞。2015年2月9日,该公司发布了一个补丁(从这里获取SUPEE-5344)来修复这个漏洞,并敦促那些没有安装这个补丁的商城老板和管理员们尽快安装这个安全补丁。
这个漏洞是由一连串的漏洞所组成的,这个漏洞允许一个未经过身份验证的攻击者在网站的服务器上执行PHP代码。攻击者可以绕过所有的安全机制并且获得控制商店和其数据库的最高权限,而且还允许攻击者盗取信用卡信息并得到进入系统的管理员权限。
这种攻击不局限于任何的插件或主题。所有的漏洞都出现在Magento网站的核心部分,并且会影响其社区版和企业版的默认安装。Check Point的客户们在IPS软件的保护之下已经不会受到这个漏洞的影响了。
这些漏洞是由Check Point公司恶意软件与漏洞研究部门的Netanel Rubin发现的。Check Point公司的研究人员经常被称为“白帽黑客”,他们的工作就是在心怀不轨的黑客能够利用这些漏洞之前,发现并修补这些安全漏洞。Check Point公司正在不断努力去提升公众、客户还有企业的安全意识和安全教育,而这次所发表的文章正是公司所做出的努力的一部分。
Magento公司建议那些Magento平台上的电商企业安装其发布的SUPEE-5344补丁。尽管Check Point公司并没有检测到该漏洞被利用的痕迹,但是管理员们仍然需要监视那些符合这个攻击模式的所有日志文件。
已确认的漏洞:1.9.1.0 CE和1.14.1.0 EE(撰写文章时的最新版本)。
Magento是eBay公司在2012年收购的一个流行的电子商务平台。它有两个版本:
■一个是社区版本,它是开源的,并且含有社区开发人员贡献的代码。
■另一个是企业版,它提供了更多的功能,例如客户支持和其他一些额外的收益。
我们发现了一个漏洞链,它将允许一个未经过身份验证的攻击者在有漏洞的服务器上运行PHP代码。它由很多个漏洞组成,我们会在接下来的技术描述部分进行分析。这些漏洞被命名为CVE-2015-1397, CVE-2015-1398, CVE-2015-1399。
披露时间表
2015年1月14日--第一次与Magento安全部门联系
2015年1月15日--提供包括修复建议在内的完整漏洞分析报告
2015年2月9日--Magento发布了补丁(SUPEE-5344)
2015年4月20日—公开发布
在我们开始描述技术细节之前,先来看看每一个漏洞的研究结果,我们需要简要地解释Magento是如何使用一个反射式代码来实现提供动态信息的。
Magento使用了含有不同功能的模块。每一个模块都有各自的控制器,并且在PHP的类文件中定义了每个模块的功能和公共方法。
用户所发出的每一个请求都会被解析,并且可以识别系统中的模块、控制器和功能方法。变量PATH_INFO中包含了请求的模块、控制器和方法名,格式如下:
GET /index.php/[MODULE_NAME]/[CONTROLLER_NAME]/[ACTION_NAME] HTTP/1.1
系统会动态加载使用这个算法的控制器:
1. 查看[MODULE_NAME]是否存在于模块白名单中。
2. 如果存在,构建一个类名,格式为:Mage_[MODULE_NAME]_[CONTROLLER_NAME]Controller
3. 找到一个类文件并将每一个‘_’符号用’/’来代替,并且在结尾加上一个php后缀。
4. 如果文件找到了,就将其引入。
例如,如果我们发送这个请求:
GET /index.php/downloadable/file/ HTTP/1.1
下列类文件就会被加载:
Mage_Downloadable_FileController
当管理员用户尝试加载一个控制器,该系统模块名称后附加字符串“Adminhtml”。
因此,如果我们将“admin”前缀添加到请求:
GET /index.php/admin/downloadable/file/ HTTP/1.1
我们得到下列类文件名称(注意:反射加载程序重复“Adminhtml”后的模块名称前缀):
Mage_Downloadable_Adminhtml_Downloadable_FileController
因此,除了明显的LFI任何文件与“ Controller.php” 后缀(' / index . php /下载/……文件”),我们就可以绕过管理身份验证,如果我们发送这个请求:
GET /index.php/downloadable/Adminhtml_Downloadable_File/ HTTP/1.1
这将尝试加载这个类:
Mage_Downloadable_Adminhtml_Downloadable_FileController
这个控制器注入漏洞有个白名单限制 。这大大限制了我们的攻击面。一些模块实现除了具体权限的额外检查。我们没有任何特权,这些检查将会失败。对攻击者来说,有一个不利的条件。这些保障措施实施将真的约束我们的攻击面,我们找不到任何突破(RCE,LFI没有后缀)这种方法的漏洞。
当一个控制器被加载时,系统是如何确定我们是否是管理员呢?让我们继续测试。对于一个需要进行身份验证的控制器,我们发现系统并不会阻塞未经验证的用户接入系统。相反,系统还会用一个“登录”控制器来代替这个被调用的控制器。
这段代码如下:
$requestedActionName = $request->getActionName(); $openActions = array( LIST_OF_OPEN_ACTIONS (login, reset password, etc.) ); if (in_array($requestedActionName, $openActions)) { $request->setDispatched(true); // An open actions } else { // Should check authentication if($user) { // A user exist $user->reload(); // Check validity of user } if (!$user || !$user->getId()) { // No user or no user ID if ($request->getPost('login')) { // Try to login TRY_TO_LOGIN } // No active user session AND no user login - access denied if (!$request->getParam('forwarded')) { if ($request->getParam('isIframe')) { CHANGE_CONTROLLER } elseif($request->getParam('isAjax')) { CHANGE_CONTROLLER } else { CHANGE_CONTROLLER } return false; } } } Mage_Admin_Model_Observer::actionPreDispatchAdmin()
现在已经很少有不检查权限的模块了,这些没有任何功能的模块往往会引起攻击者的注意。无论如何,让我们来看一看’Adminhtml’模块中的’Cms_Wysiwyg’控制器。这个控制器只有一个名叫‘directive’的功能,它会根据我们输入的路径去载入一张图片。
// Get the ___directive parameter $directive = $this->getRequest()->getParam('___directive'); // base64_decodes the input $directive = Mage::helper('core')->urlDecode($directive); // Filter the input $url = Mage::getModel('cms/adminhtml_template_filter')->filter($directive); // Try to load the image try { $image = Varien_Image_Adapter::factory('GD2'); $image->open($url); $image->display(); } Mage_Adminhtml_Cms_WysiwygController::directiveAction()
幸运的是,有一个函数是非常有价值的:即‘blockDirective()’,它能够创建一个Magento类块来供我们控制和使用。
在系统初始化请求信息块后,它将会继续使用函数’setDataUsingMethod()’来设置参数:
public function setDataUsingMethod($key, $args=array()) { $method = 'set'.$this->_camelize($key); // Parse the method name $this->$method($args); // Call the method return $this; // Return (Wow, such dynamics, very $this) } Mage_Core_Moder_Email_Template_Filter::blockDirective()
作为一个攻击者,我们会想要去控制整个字典文件。系统会尝试通过一个验证函数来验证我们的输入,代码如下:
// This is the actual array from the request parameter $value = $this->getData('value'); // Checks for a 'from' and 'to' keys (I edited the ‘if’ statement a little bit so it’ll be convenient to read) if (strlen($value['from']) > 0) || strlen($value['to']) > 0) { return $value; // Just return the dictionary as it! } Mage_Adminhtml_Block_Widget_Grid_Column_Filter_Range::getValue()
因此,如果字典中有‘from’和‘to’,函数会返回一个原始的字典数据。
既然我们已经控制了整个字典文件,那么我们就可以注入任何我们想要注入的SQL代码了。对攻击者来说,幸运的是,Magento使用的是PHP PDO,它默认支持单语句的复合条件查询。在我们的测试中,Magento将’PDO::ATTR_EMULATE_PREPARES’的值设为了’true’。这意味着我们能够注入任何SQL语句来查询我们想要的东西了。
对攻击者来说,有一个不利的条件,即系统禁止了CGI的在其系统目录中执行。为了绕过这个保护措施,我们可以在其子目录中创建另一个’.htaccess’文件并且重写父类的函数声明。然而,这只是一个普通的利用技巧,当服务器检测可疑文件的时候很容易检测到这个文件。
【原文 Analyzing the Magento Vulnerability (Updated) 安全脉搏Expl0r3r 整理发布】