Supervisord远程命令执行漏洞分析(CVE-2017-11610)

Supervisor介绍

Supervisord是一款由Python语言开发,用于管理后台应用(服务)的工具,方便运维人员使用图形化界面进行管理。

近期,Supervisord曝出了一个需认证的远程命令执行漏洞(CVE-2017-11610),通过POST请求Supervisord管理界面恶意数据,可以获取服务器操作权限,存在严重的安全风险。

漏洞简介

本次漏洞就出在XML-RPC接口对数据的处理上。 默认情况下Supervisor并不会开启这个接口,但这并不代表这个漏洞不重要,相反的是,在Supervisor的使用中,很多人喜欢利用web页面来管理,而不是使用上文中提到的supervisorctl命令行工具。使用web页面有一个方便之处,即通过简单配置,使用者可以在其他机器的浏览器上通过网址访问并控制Supervisor。省去非一定在本地配置的麻烦(例如在docker中使用Supervisor,就不用每次进入容器控制Supervisor)。

漏洞分析

本次分析从Supervisor入口出发,根据漏洞的相关披露,层层进行解析。 先从入口看起:Supervisord启动文件Supervisord.py。 因为事先知道攻击数据是通过http方式传入到sever端的,所以重点关注下Supervisord启动方法(run)中的启动http服务方法,这里是self.options.openhttpservers()

options.py文件中 ,在这里可以看到self.httpservers = self.make_http_servers(supervisord) 在这里调用了make_http_servers()方法 在Options类中找到make_http_servers() 方法

可见这个方法是从supervisor.http中导入的,我们继续跟进http.py文件查看make_http_servers()方法的实现  

根据漏洞的披露,我们知道这个漏洞是在XML-RPC接口的调用上出现了问题,在上图代码的最后一行supervisor_xmlrpc_handler()方法,就是用来处理RPC调用的。 我们从supervisor的入口开始,一路顺藤摸瓜找到了罪魁祸首,接下来跟进supervisor_xmlrpc_handler()方法看一下出现漏洞的原因 supervisor_xmlrpc_handler方法在xmlrpc.py文件中实现

找到漏洞纰漏的traverse方法,可以看到supervisor_xmlrpc_handler()方法中的call函数将解析出来的method以及params传入tracerse方法中。 我们先来看下call函数在哪里被调用,以及method,params到底是什么: 在supervisor_xmlrpc_handler这个类中,有一个continue_request()函数,如下所示

在params, method = self.loads(data)一行中,可以看到params和method的产生,并且在这个函数最下面一行,可见调用了call()将返回值给了value。我们先看下这个类中的loads函数,如下所示:

可见params和method是由xml tag中的methodName和params中的值得来的。 上面说的有些抽象,为了方便下面漏洞的理解,下面举个例子:在这里利用python使用RPC协议给supervisord发一个请求,来看下RPC协议的结构和params、method分别是什么。

这里的supervisor.supervisord.options.warnings.linecache.os.system就是method参数值,而param的值就是touch /tmp/success1 正常的交互中,这两个值往往是method=supervisor.startProcess;param=要启动的应用名 现在call()函数已经明晰了,再看看call函数中的tracerse方法。下面继续跟入tracerse方法

在tracerse方法中,将传入的method通过“.”来拆分,赋值给path 判断开头是否为“_”,如果是,则报错 然后看ob = getattr(ob, name, None)这行,getattr()是一个自省函数,下面举一个简单的例子说明下getattr()

 我们仔细分析下如下代码:

在这里类似一个递归,将原本链状的method中的方法遍历出来,例如method原先的结构是a.b.c.d这里path列表就应该是[a,b,c,d],然后遍历name。通过ob = getattr(ob, name, None),首先将ob中的a方法赋给新的ob,再将新的ob(现在是a方法)中的b方法取出来赋给新的ob。以此类推,最终的ob会是链状结构最后一个方法(也就是d),然后传入params值,被执行 所以如果想攻击利用成功,必须找到一个调用链,例如如下调用链下图是调用关系:

Options中的warnings方法

Warnings中的linecache方法

Linecache中的os方法

漏洞利用

解决方案

升级supervisor到最新版本或在配置中修改[inet_http_server]配置

Copyright © 2017 ITGATHER.COM - 闽ICP备19016859号-1
扫二维码--> 返回顶部