漏洞描述
Apache Struts是美国阿帕奇(Apache)基金会的一个开源项目,是一套用于创建企业级Java Web应用的开源MVC框架。
Apache Struts在特定条件下,存在文件上传漏洞(网宿评分:高危、CVSS 3.0 评分:8.1):
攻击者可以操纵文件上传参数来实现路径遍历,在某些情况下,这可能导致恶意文件上传。
影响版本
Struts 2.0.0 - 2.3.37(EOL)
Struts 2.5.0 - 2.5.33(EOL)
Struts 6.0.0 - 6.3.0.2
环境搭建
同S2-066
漏洞成因
S2-067与S2-066有90%的相似,S2-067是S2-066补丁的绕过。
通过前一篇文章的分析我们直到S2-066的修复是在向ActionContext的parameters属性添加一个参数,先检查parameters属性是否为空,如果为空,则直接添加参数,
如果parameters不为空,则遍历文件上传的参数ContentType与UploadFileName等,将其先同意转换为小写,然后在与parameters中的元素比较,
当存在相同的元素的时候先删除parameters中的参数再将新的参数添加到parameters中,这样就避免了用户上传表单中非文件参数对文件上传参数的影响覆盖。
通过对S2-066的学习我们还可以直到,form表单参数的name属性的值会被当作OGNL解析,用来向ValueStack上的root映射中的元素设置属性值。
既如此,name属性的值就可以是任何有效的OGNL表达式,从而实现任意属性的设置。
当我们使用这样的表达是的时候top.uploadFileName会发生什么。
让我们定位到com.opensymphony.xwork2.interceptor.ParametersInterceptor.setParameters方法
这里面调用了ValueStack的setParameter方法向ValueStack的root映射中设置属性值。
1 | protected void setParameters(final Object action, ValueStack stack, HttpParameters parameters) { |
通过setParaameters的方法签名也可以看出来其第一个参数是一个OGNL表达式。
1 | public void setParameter(String expr, Object value) { |
程序继续向下执行最终会来到 com.opensymphony.xwork2.ognl.OgnlUtil.compileAndExecute方法。
这个方法会根据ognl表达式来获取ognl表达式对应的ognl树,然后解析ognl树。
当ognl表达式为uploadFileName的时候,得到的tree为ASTProperty类型,S2-066就是执行ASTProperty的setValueBody方法设置ValueStack 的root映射中的元素。
当ognl表达式为top.uploadFileName的时候,得到的tree为ASTChain类型,S2-067就是执行ASTChain的setValueBody方法设置ValueStack 的root映射中的元素。
1 | private <T> Object compileAndExecute(String expression, Map<String, Object> context, OgnlTask<T> task) throws OgnlException { |
ASTChain的setValueBody方法
1 | protected void setValueBody(OgnlContext context, Object target, Object value) throws OgnlException { |
ASTChain的Children包含两个元素均为ASTProperty类型,就是通过.将top.uploadFileName进行了分割成两部分。
首先通过top节点去取target的值,注意这里target之前是有值的就是ValueStack的root映射部分,即一个CompoundRoot对象,包含两个元素UploadAction以及DefaultTextProvider对象。这里也就是通过top节点取取一个值来覆盖原来的target。
代码继续向下执行会来到com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor.getProperty方法。
这里判断name是否为top,如果为top则返回root的第一个元素,否则会遍历root中的元素,如果元素中有name属性则返回该元素。root的第一个元素即为UploadAction,即上一步求的target为UploadAction。
1 | public Object getProperty(Map context, Object target, Object name) throws OgnlException { |
重新求得target后则会调用uploadFileName的节点得setValue方法为target设置值。uploadFileName节点是ASTProperty类型,这就是典型得OGNL表达式的语法了,后面的内容就与S2-066的逻辑一致了。
因为在S2-067中我们使用的payload是top.uploadFileName与UploadFileName在统一大小写后也并不相等,所以就能完美的绕过S2-066添加的remove方法的补丁了。
1 | this._children[this._children.length - 1].setValue(context, target, value); |
另外,ValueStack的root映射中包含两个元素,一个是UploadAction,一个是DefaultTextProvider,既然UploadAction的属性可以被设置,那么DefaultTextProvider的属性也是可以被设置的。
这样我们就可以控制DefaultTextProvider对象的属性值,是不是可以做些什么呢?
漏洞修复
新增了一个类并被推荐使用。。。。FileUploadAction并没有被修改,应该是这样的。赶时间
参考链接
无