本文为《 CVE-2018-11759]Apache mod_jk access control bypass 》的翻译文章。
嘿,各位大佬们:
我非常激动向你们介绍一个我同事(ID为Xel)和我在一次渗透测试中发现的新漏洞:CVE-2018-11795
一年前,我在Wordpress上面才拥有我的第一个CVE,但是现在我们又搞到了第二个!
在我们一位客户的一次基于Apache mod_jk 模块的JBoss / Tomcat 网络服务器进行渗透测试时候,我们发现服务器上存在CVE-2018-1323漏洞(是由Biznet Bilisim A.S.公司的Alphan YAVAS发现并提交的),这会影响到mod_jk模块,同时所影响版本的范围到1.2.42。
为理解其漏洞原理,我们分析了1.2.43版本的mod_jk 补丁。在这个过程中,我们意识到这个漏洞是一个路径穿越问题,是基于Apache httpd、Tomcat或者其他Java服务器的,而且关于他们在处理当用分号进行跨目录路径遍历时各自路径解析的差异点。
Apache httpd将url中的分号视作路径解析中的普通字符,然而Tomcat却将他们当作查询分隔符(和”?”类似)。因此,攻击者可以获取到例如这样的路径: http://server/java_app/..;
,但是对于httpd来中,这并没有触发服务器,并跳转到对应的目录下,而仅仅是被原封原样地转发到了Tomcat上,而且地址尾部会被解析为 ..
。*
译者注:”.. “是两个点加一个空格
这就允许攻击者可以获取到本不应该在Tomcat上可以访问的资源。
图1:比对CVE-2018-1323我们现在已经确定了这个漏洞其实并未完全挖掘出来,因为mod_jk的补丁虽然确实修复了针对mod_jk的特定路径遍历攻击,但是还是没有解决mod_jk对分号路径解析方式的核心问题。
jkstatus是mod_jk模块的管理界面。当设为读写权限的时候,它允许通过配置AJP连接Java Web服务器来代理HTTP请求。
通常,我们可以限制对jkstatus的访问,比如使用如下的httpd指令:
<Location /jkstatus> JKMount jk-status Require ip 127.0.0.1 </Location>
这条指令会阻拦任何外部资源对jkstatus的访问。
我们发现通过在 /jkstatus
后面注入分号,就可以绕过这样的限制。
图3:jkstatus访问控制绕过(分号注入)上图可以看到,在url分号之后提交的get参数,就可以成功向jkstatus请求修改其访问权限的配置。
图4:url中分号后面get参数部分能被解析如果给jkstatus设定成具有读写访问权限的配置,要绕过jkstatus访问控制的话,其产生的影响就等同于通过更改工作人员使用的端口来实现对所有由mod_jk供应的应用程序拒绝服务的效果。不仅如此,如果攻击者再将相应的AJP连接到任何一台他所掌控的服务器上,他也可能会劫持到所有由mod_jk供应服务的web应用的流量。
理论上讲,通过将AJP的目标和端口修改为内部主机和其对应的端口,我们也可以进行内部TCP端口扫描,这是因为Tomcat和httpd的jkstatus返回的错误信息不一致的缘故,具体情况取决于提交的AJP端口是否有效 (错误网关与服务不可用的情况) *。我们并不能对这种类型的SSRF攻击造成的全面影响进行预估和考量。
译者注:错误网关:Bad gateway;服务不可用:Service Unavaliable
图5:AJP:可以提交任意主机名和端口jkstatus(如果是只读权限的配置)还会公开内部服务器主机名、ip、端口、mod_jk模块服务的服务器和路由、以及文件系统上http服务器的绝对路径。
这种对访问控制权限绕过的手法具有很大的破坏效果,但是必须要注意一点的就是,通过JkMount指令定义任何端点的访问控制都有可能被分号注入绕过。
mod_jk(1.2.46版本)已经提供了相应补丁,其他的修复措施(注意,并一定能完全防御,只是起缓解作用)包括有:使用例如 /jkstatus*
这样的位置值设定。
github上我们的库里面有一个docker环境可以拿来测试复现这个漏洞。
两位来自immunIT公司的Raphaël Arrouas (ID为Xel)和Jean Lejeune(ID为Nitrax) 同志。