4000-520-616
欢迎来到免疫在线!(蚂蚁淘生物旗下平台)  请登录 |  免费注册 |  询价篮
主营:原厂直采,平行进口,授权代理(蚂蚁淘为您服务)
咨询热线电话
4000-520-616
当前位置: 首页 > 新闻动态 >
新闻详情
技术分析:剖析HikaShop PHP对象注入漏洞 - 51CTO.COM
来自 : netsecurity.51cto.com/art/2014 发布时间:2021-03-24

HikaShop是基于著名开源CMS Joomla!的电子商务程序,可以帮助用户轻松的开发电子商务网站或网店。

498)this.width=498;\' onmousewheel = \'javascript:return big(this)\' border=\"0\" alt=\"技术分析:剖析HikaShop PHP对象注入漏洞\" src=\"http://s8.51cto.com/wyfs02/M01/54/09/wKioL1R2gUnilnFVAAHu17Qg_fk618.jpg\" width=\"690\" height=\"446\" />

距离上次我们发现Joomla!的HikaShop扩展对象注入漏洞(影响版本 2.3.3)已经两月有余了。今天要讲的这个漏洞允许黑客向网站发送恶意指令,从而造成远程代码执行。

小科普

由于本篇文技术含量稍高,这里小编做一些术语科普,希望对大家有用:

魔术方法:在 PHP中以两个下划线开头的方法,调用时需要在类中预定义。析构函数:当对象脱离其作用域时,系统自动执行析构函数,做好 清理善后 的工作。回调函数:把函数的指针(地址)作为参数传递给另一个函数,该指针被用来调用其所指向的函数。序列化:将对象的状态信息转换为可以存储或传输的形式。类实例:必须通过对象名来访问,也就是说要想使用类实例,必须创建对象。

对象注入的原理

对象注入通常发生在用户的输入,被传递给unserialize()函数然后进行调用的时候。黑客可以通过构造输入内容,向WEB服务器发送当前WEB应用下的一个序列化的类实例,保证这些被定义为魔术方法的类,在特定的时候会被触发,从而执行其中的恶意代码。

漏洞的罪魁祸首

代码中的124行和132行有两个重要的点值得我们注意,$infos变量被设置为JRequest::getVar()的返回值,这就意味着它可以接收$_GET[\'infos\']或者$_POST[\'infos\']的值。接着,$infos的值被base64编码后,会传递给unserialize()函数。

Hikashop漏洞的攻击利用方法如图:

498)this.width=498;\' onmousewheel = \'javascript:return big(this)\' border=\"0\" alt=\"技术分析:剖析HikaShop PHP对象注入漏洞\" src=\"http://s1.51cto.com/wyfs02/M00/54/08/wKioL1R2gE7hP-MiAAD2ON3uvrg016.jpg\" width=\"690\" height=\"223\" />

我们在了解这些信息后,就需要想办法达成我们的邪恶目的。在我们的POC调用了Joomla! 3.3.x的类,并且定义成功后,我们就可以读取WEB服务器上的/etc/passwd。

找出利用方法,直击问题核心

我们首先要做的,就是分析该程序代码的执行顺序。同时,我们也需要使用Joomla!类的魔术方法。值得一提的时候,PHP类的析构方法__destruct(),在脚本执行完毕时会自动执行析构函数。

在这个特定案例下,我们选择了JDatabaseDriverMysqli类的析构方法来达成我们的需求,这可以让我们从任何存在的类里去调用方法。Destruct函数调用disconnect方法如图:

498)this.width=498;\' onmousewheel = \'javascript:return big(this)\' border=\"0\" alt=\"技术分析:剖析HikaShop PHP对象注入漏洞\" src=\"http://s2.51cto.com/wyfs02/M01/54/08/wKioL1R2gGOyxZw-AAA86laqgqA189.jpg\" width=\"322\" height=\"80\" />

这里采用了$this- disconnectHandlers调用那些回调函数,Disconnect函数如图:

498)this.width=498;\' onmousewheel = \'javascript:return big(this)\' border=\"0\" alt=\"技术分析:剖析HikaShop PHP对象注入漏洞\" src=\"http://s2.51cto.com/wyfs02/M01/54/0A/wKiom1R2f_PANOXnAAEIQ-eqTc8409.jpg\" width=\"484\" height=\"292\" />

我们准备通过创建一个改版过的JDatabaseDriverMysqli类,它可以让我们更改变量的默认值。特别需要指出的是,我们需要满足几个条件来实现序列化。一旦Hikashop被反序列化,会生成一些实例,然后析构函数会执行我们提供的任何函数或者方法。

为了实现上述的需求,我们需要做到以下几点:

1.一定要把$this- connection的值设为 True (否则我们不能调试到call_user_func_array()函数里面去)

2.使用某个包含如下内容的数组(以下任意一点即可)赋给$this- disconnectHandlers:

(1)包含我们目标函数名的字符串

(2)包含方法名称和对应类的一个实例,比如这个数组(new ourClass(), ourClassMethod )

我们不能控制传递给目标函数的参数内容(它永远是我们类的实例),这就限制了我们在以下环境里研究方法:

1.那些我们不能使用任何参数的时候

2.那些函数的第一个参数类型并没有针对黑客进行限制的时候

3.那些因环境需要,而使用的多参数模式(事实上我们只需构造发送一个参数,因为其他的参数可能被置为默认值或者空值,并且记入服务器的错误日志)

发现有趣的方法

使用一些grep命令,我们会看到PHPMailer类的这个方法,PHPMailer类的require_once方法如图:

498)this.width=498;\' onmousewheel = \'javascript:return big(this)\' border=\"0\" alt=\"技术分析:剖析HikaShop PHP对象注入漏洞\" src=\"http://s5.51cto.com/wyfs02/M02/54/08/wKioL1R2gIeCcdzPAAC_G6Tbwgk667.jpg\" width=\"690\" height=\"114\" />

很容易是不是?传递PHPMailer的一个实例,把$this- PluginDir设置指向为可以进行hack的地址(这可以产生一个绝妙的LFI/RFI攻击,可以想象一下我们把$this- PluginDir指向http://blog.sucuri.net/)。然而不幸的是,有两个难题阻碍了我们前进的道路:

问题1 PHPMailer类在当前环境下没有做定义

这绝对是一个让人头疼的问题,但我们真的什么也做不了麽?当然不是!谢天谢地,Joomla!采用了一些非常规则的类进行自动加载,这使得我们在导入PHPMailer类的过程中,自动导入JMail组件。

为了解决这个问题,我们在没有使用过的JDatabaseDriverMysqli的变量中创建了JMail的一个实例。这样的话,自动导入机制可以在导入JMail组件的文件的同时,加载PHPMailer的定义。

问题2 SmtpSend()方法被定义为保护模式,防止外部使用

这倒不是事儿,如果你不能直接调用SmtpSend(),可以找出另一个public方法,对SmtpSend()进行调用!然而幸运女神再次眷顾了我们,确实存在这样一种方法!PostSend函数调用SmtpSend()如图:

498)this.width=498;\' onmousewheel = \'javascript:return big(this)\' border=\"0\" alt=\"技术分析:剖析HikaShop PHP对象注入漏洞\" src=\"http://s7.51cto.com/wyfs02/M02/54/0A/wKiom1R2gB_jkHkQAAGQRaFC3ko008.jpg\" width=\"690\" height=\"242\" />

我们唯一剩下的工作,就是将$this- Mailer的值设为smtp!

这样就完了?

当然不是,我们确实找出了一些LFI/RFI的漏洞,但离我们最初的目标还很遥远。我们的最终目的是:发送简单的命令,一键把后门植入网站根目录!

我们可以使用RFI漏洞进行远程文件包含,那么现在问题来了,它需要WEB容器开启allow_url_include选项,而这个选项默认是关闭的。也许,我们需要寻求另一种方法来达成目标。

Sendmail拯救世界!

你们可能注意到了该截图,那是一个带有PostSend()函数的方法,即$this- SendmailSend(),Sendmail函数如图:

498)this.width=498;\' onmousewheel = \'javascript:return big(this)\' border=\"0\" alt=\"技术分析:剖析HikaShop PHP对象注入漏洞\" src=\"http://s9.51cto.com/wyfs02/M01/54/09/wKioL1R2gLOjBjuBAAGWexoiJlw548.jpg\" width=\"690\" height=\"280\" />

这里展示了一个非常有趣的方法,可以用来在目标服务器的绝对路径下写文件。

popen()函数使用了$sendmail变量($sendmail变量通常包含 /usr/sbin/sendmail -oi -t 或者 /usr/sbin/sendmail -oi -f EMAIL@HERE.COM -t )来执行shell命令,所以我们才可以使用Sendmail函数来发电子邮件。经过进一步分析,可以发现它使用了两个变量,即$this- Sender和$this- Sendmail,前者可以为空。

它们使用了不同的函数:escapeshellcmd()和escapeshellarg()。在escapeshellcmd()里调用$this- Sendmail的话,以下这些特殊字符会被编码:# `|*?~^()[]{}$\\, \\x0A以及\\xFF。最后我们只能使用字母、数字以及少量如 / 和 - 这样的字符。

这距离我们的目标还远远不够!我们可以在Sendmail函数的原始命令中加入我们需要的参数。

所以,如果我们把 /usr/sbin/sendmail -OQueueDirectory=/tmp -X/tmp/smtp.php 这样的参数加进去会如何?同样,如果我们使用现有的poc,同时对代码中其他所有的变量进行设置后,发送一个头部含有以下的内容的邮件又会怎样呢?

头部内容:

确实是个难题吧?如果那样做的话会产生如下后果:

1. -OQueueDirectory=/tmp -X/tmp/smtp.php ,这部分代码会将/tmp/smtp.php发送的邮件给保存起来。

2.我们发送的头部内容,会被保存起来进行反序列化处理。

现在我们需要做的,就是把整个流程整理一下,最后才能达到我们的目标!

完整利用流程图

在这时我们的方法已经很复杂了,一个统筹的流程图在这时显得十分有必要:

498)this.width=498;\' onmousewheel = \'javascript:return big(this)\' border=\"0\" alt=\"技术分析:剖析HikaShop PHP对象注入漏洞\" src=\"http://s7.51cto.com/wyfs02/M01/54/0A/wKiom1R2gEbjERabAAEEdhXiB0o396.jpg\" width=\"690\" height=\"538\" />

一旦黑客成功创建和序列化一个对象,将其传递给存在漏洞的Hikashop扩展加载,就可以窃取/etc/passwd的内容。

我们可以通过该漏洞做许多事,这里所讲到的仅仅是其中一种。如果您使用的是Hikashop扩展,我希望您已经在我们上次发布该漏洞后及时更新了补丁。

水平有限,如有表达不明朗的地方请不吝赐教,可以点击文章下方的 文章纠正

参考来源:http://blog.sucuri.net/2014/11/deep-dive-into-the-hikashop-vulnerability.html

【编辑推荐】

安全漏洞的成本呈上升趋势如何借助lynis扫描Linux的安全漏洞?你知道近一半USB设备存在安全漏洞吗?【责任编辑:蓝雨泪 TEL:(010)68476606】

本文链接: http://hika.immuno-online.com/view-687343.html

发布于 : 2021-03-24 阅读(0)