WSO2 RCE(CVE-2022-29464) 漏洞复现

admin 2022年4月27日20:41:28安全漏洞评论152 views10547字阅读35分9秒阅读模式

星期五实验室


阅读须知
星期五实验室的技术文章仅供参考,此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等(包括但不限于)进行检测或维护参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息造成的直接或间接后果和损失,均由使用者本人负责。

星期五实验室拥有对此文章的修改、删除和解释权限,如转载或传播此文章,需保证文章的完整性,未经授权,不得用于其他。




01

漏洞描述

WSO2 RCE(CVE-2022-29464) 漏洞复现
漏洞描述

WSO2 API Manager是一款可以旨在提供优秀的API管理功能的产品,能够实现API的创建、发布、生命周期管理、流量控制、版本控制、治理和安全控制等功能。WSO2 API Manager可以为开发团队提供Web页面进行部署、管理和监控API。WSO2由于无限制的任意文件上传可以导致远程代码执行漏洞。目前官方已经给出了解决办法。



影响版本

WSO2 API Manager 2.2.0 and aboveWSO2 Identity Server 5.2.0 and aboveWSO2 Identity Server Analytics 5.4.0, 5.4.1, 5.5.0, 5.6.0WSO2 Identity Server as Key Manager 5.3.0 and aboveWSO2 Enterprise Integrator 6.2.0 and above


               

02

漏洞复现

WSO2 RCE(CVE-2022-29464) 漏洞复现

环境设置
虚拟机Ubuntu16.0.4
本机Windows11
JDK 8U191
WSO2 API Manager v4.0.0  
源码和wso2am-4.0.0.zip都需要下载方便后期调试,下载链接如下:
https://github.com/wso2/product-apim/releases/tag/v4.0.0



环境搭建

  1. 运行服务
将下载好的wso2am-4.0.0.zip解压到服务器上,Windows或者Linux都可,然后进入wso2am-4.0.0/bin目录中,运行bat或者sh。


WSO2 RCE(CVE-2022-29464) 漏洞复现


运行效果如下:


WSO2 RCE(CVE-2022-29464) 漏洞复现


2.访问目标网址

这里我们直接访问http://localhost:9443/,它就会自动导航到登陆界面,如下表示搭建成功。


WSO2 RCE(CVE-2022-29464) 漏洞复现


3.源码使用IDEA打开
导入源码后,下载相关依赖包即可。


WSO2 RCE(CVE-2022-29464) 漏洞复现


4.设置远程调试
这里填写ubuntu的ip地址,端口随意,其它的基本不用改变。

WSO2 RCE(CVE-2022-29464) 漏洞复现


5.服务开启debug
服务每次打开时,使用如下命令,下图表示运行成功。
bash api-manager.sh --debug 5005 #linux./api-manager.bat --debug 5005 #windows

WSO2 RCE(CVE-2022-29464) 漏洞复现


细节分析

CVE-2022-29464 是Orange Tsai发现的 WSO2 上的严重漏洞。该漏洞是一种未经身份验证的无限制任意文件上传,允许未经身份验证的攻击者通过上传恶意JSP文件在 WSO2 服务器上获得 RCE。
查看配置文件发现/repository/conf/identity/目录下存在identity.xml文件
https://docs.wso2.com/display/MB220/Configuring+identity.xml
<ResourceAccessControl default-access="allow">    <Resource context="/duoauthenticationendpoint(.*)" http-method="all" secured="false"/>    <!--这就是文件上传的url,可以看到/fileupload 是不需要认证就可以访问的-->    <Resource context="(.*)/fileupload(.*)" http-method="all" secured="false"/>    <Resource context="(.*)/filedownload(.*)" http-method="all" secured="false"/>    <Resource context="(.*)/logincontext(.*)" http-method="all" secured="false"/></ResourceAccessControl>


上面代码可以看到/fileupload后面是可以匹配任何字符串,我们可以重点看下FileUploadServlet这一个类中的init()方法去区分/fileupload/下一级路径,如下所示:
public class FileUploadServlet extends HttpServlet {    protected void doPost(HttpServletRequest request, HttpServletResponse response){}    protected void doGet(HttpServletRequest request, HttpServletResponse response){}    //有javaWeb开发经验的一看就能知道它的作用了    public void init(ServletConfig servletConfig) throws ServletException {        this.servletConfig = servletConfig;
try { this.fileUploadExecutorManager = new FileUploadExecutorManager(this.bundleContext, this.configContext, this.webContext); this.bundleContext.registerService(FileUploadExecutorManager.class.getName(), this.fileUploadExecutorManager, (Dictionary)null); } catch (CarbonException var3) { log.error("Exception occurred while trying to initialize FileUploadServlet", var3); throw new ServletException(var3); } }}


其实这个访问方式还是有注意点的,大家可以看看下图,doPost方法规定了我们只能以POST方式访问。


WSO2 RCE(CVE-2022-29464) 漏洞复现


下面继续查询Init()方法,可以看到初始化了一个FileUploadExecutorManager对象,而这个对象它就能把文件上传相关的xxxExecutor对象初始化,存放在executorMap Map字典中,代码如下:
public class FileUploadExecutorManager {    public FileUploadExecutorManager(BundleContext bundleContext, ConfigurationContext configCtx, String webContext) throws CarbonException {        this.bundleContext = bundleContext;        this.configContext = configCtx;        this.webContext = webContext;        this.loadExecutorMap();    }    public void addExecutor(String action, String executorClass) throws CarbonException {        String msg;               try {            Class clazz = this.bundleContext.getBundle().loadClass(executorClass);            Constructor constructor = clazz.getConstructor();            AbstractFileUploadExecutor object = (AbstractFileUploadExecutor)constructor.newInstance();            //添加值            this.executorMap.put(action, object);                    } catch (Exception var6) {                    }    }}


这中间存储的就是fileupload目录下的实例化类。


WSO2 RCE(CVE-2022-29464) 漏洞复现


我们调试一下看看executorMap中存储了哪些Executor,以下就是我们能够选用的值。


WSO2 RCE(CVE-2022-29464) 漏洞复现


然后我们看看在哪里使用了executorMap。前文我们知道在doPost中我们执行了下面这行代码:
this.fileUploadExecutorManager.execute(request, response);


所以我们跟到FileUploadExecutorManager#execute()方法中,代码如下:

public boolean execute(HttpServletRequest request, HttpServletResponse response) throws IOException {    HttpSession session = request.getSession();    String cookie = (String)session.getAttribute("wso2carbon.admin.service.cookie");    request.setAttribute("wso2carbon.admin.service.cookie", cookie);    request.setAttribute("WebContext", this.webContext);    request.setAttribute("ServerURL", CarbonUIUtil.getServerURL(request.getSession().getServletContext(), request.getSession()));    String requestURI = request.getRequestURI();    int indexToSplit = requestURI.indexOf("fileupload/") + "fileupload/".length();    //actionString就是我们需要执行对象在executeMap中的key值    String actionString = requestURI.substring(indexToSplit);        FileUploadExecutorManager.FileUploadExecutionHandlerManager execHandlerManager = new FileUploadExecutorManager.FileUploadExecutionHandlerManager();    FileUploadExecutorManager.CarbonXmlFileUploadExecHandler carbonXmlExecHandler = new FileUploadExecutorManager.CarbonXmlFileUploadExecHandler(request, response, actionString);    execHandlerManager.addExecHandler(carbonXmlExecHandler);    FileUploadExecutorManager.OSGiFileUploadExecHandler osgiExecHandler = new FileUploadExecutorManager.OSGiFileUploadExecHandler(request, response);    execHandlerManager.addExecHandler(osgiExecHandler);    FileUploadExecutorManager.AnyFileUploadExecHandler anyFileExecHandler = new FileUploadExecutorManager.AnyFileUploadExecHandler(request, response);    execHandlerManager.addExecHandler(anyFileExecHandler);    //开始    execHandlerManager.startExec();    return true;}

到这基本上就是决定执行哪一个Excutor对象,过程过于复杂,限于篇幅问题,这里贴一下他的调用栈。
execute:55, ToolsAnyFileUploadExecutor (org.wso2.carbon.ui.transports.fileupload)executeGeneric:104, AbstractFileUploadExecutor (org.wso2.carbon.ui.transports.fileupload)execute:436, FileUploadExecutorManager$CarbonXmlFileUploadExecHandler (org.wso2.carbon.ui.transports.fileupload)//这里就是上方我们标记 “开始” 的位置startExec:320, FileUploadExecutorManager$FileUploadExecutionHandlerManager (org.wso2.carbon.ui.transports.fileupload)execute:127, FileUploadExecutorManager (org.wso2.carbon.ui.transports.fileupload)doPost:57, FileUploadServlet (org.wso2.carbon.ui.transports)service:660, HttpServlet (javax.servlet.http)service:741, HttpServlet (javax.servlet.http)service:37, ContextPathServletAdaptor (org.eclipse.equinox.http.helper)service:61, ServletRegistration (org.eclipse.equinox.http.servlet.internal)processAlias:128, ProxyServlet (org.eclipse.equinox.http.servlet.internal)service:68, ProxyServlet (org.eclipse.equinox.http.servlet.internal)service:741, HttpServlet (javax.servlet.http)service:68, DelegationServlet (org.wso2.carbon.tomcat.ext.servlet)internalDoFilter:231, ApplicationFilterChain (org.apache.catalina.core)doFilter:166, ApplicationFilterChain (org.apache.catalina.core)doFilter:53, WsFilter (org.apache.tomcat.websocket.server)internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)doFilter:166, ApplicationFilterChain (org.apache.catalina.core)doFilter:72, CsrfGuardFilter (org.owasp.csrfguard)internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)doFilter:166, ApplicationFilterChain (org.apache.catalina.core)doFilter:65, CharacterSetFilter (org.wso2.carbon.tomcat.ext.filter)internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)doFilter:166, ApplicationFilterChain (org.apache.catalina.core)doFilter:126, HttpHeaderSecurityFilter (org.apache.catalina.filters)internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)doFilter:166, ApplicationFilterChain (org.apache.catalina.core)invoke:202, StandardWrapperValve (org.apache.catalina.core)invoke:96, StandardContextValve (org.apache.catalina.core)invoke:541, AuthenticatorBase (org.apache.catalina.authenticator)invoke:139, StandardHostValve (org.apache.catalina.core)invoke:92, ErrorReportValve (org.apache.catalina.valves)invoke:107, TenantContextRewriteValve (org.wso2.carbon.identity.context.rewrite.valve)invoke:110, AuthorizationValve (org.wso2.carbon.identity.authz.valve)invoke:102, AuthenticationValve (org.wso2.carbon.identity.auth.valve)continueInvocation:101, CompositeValve (org.wso2.carbon.tomcat.ext.valves)invokeValves:49, TomcatValveContainer (org.wso2.carbon.tomcat.ext.valves)invoke:62, CompositeValve (org.wso2.carbon.tomcat.ext.valves)invoke:145, CarbonStuckThreadDetectionValve (org.wso2.carbon.tomcat.ext.valves)invoke:690, AbstractAccessLogValve (org.apache.catalina.valves)invoke:57, CarbonContextCreatorValve (org.wso2.carbon.tomcat.ext.valves)invoke:126, RequestCorrelationIdValve (org.wso2.carbon.tomcat.ext.valves)invoke:74, StandardEngineValve (org.apache.catalina.core)service:343, CoyoteAdapter (org.apache.catalina.connector)service:373, Http11Processor (org.apache.coyote.http11)process:65, AbstractProcessorLight (org.apache.coyote)process:868, AbstractProtocol$ConnectionHandler (org.apache.coyote)doRun:1590, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)run:49, SocketProcessorBase (org.apache.tomcat.util.net)runWorker:1149, ThreadPoolExecutor (java.util.concurrent)run:624, ThreadPoolExecutor$Worker (java.util.concurrent)run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)run:748, Thread (java.lang)

接下来就是执行ToolsAnyFileUploadExecutor#excute() 方法了,我们看具体代码

public boolean execute(HttpServletRequest request, HttpServletResponse response) {    PrintWriter out = response.getWriter();    try {        Map fileResourceMap = (Map)this.configurationContext.getProperty("file.resource.map");        if (fileResourceMap == null) {            fileResourceMap = new TreeBidiMap();            this.configurationContext.setProperty("file.resource.map", fileResourceMap);        }        List<FileItemData> fileItems = this.getAllFileItems();        Iterator i$ = fileItems.iterator();
while(i$.hasNext()) { FileItemData fileItem = (FileItemData)i$.next(); String uuid = String.valueOf((double)System.currentTimeMillis() + Math.random()); String serviceUploadDir = this.configurationContext.getProperty("WORK_DIR") + File.separator + "extra" + File.separator + uuid + File.separator; File dir = new File(serviceUploadDir); if (!dir.exists()) { dir.mkdirs(); } //这里是整个rce能正常执行的重点,我们看到这里并没有对文件名做任何的../或./过滤,导致我们可以任意构造 File uploadedFile = new File(dir, fileItem.getFileItem().getFieldName()); FileOutputStream fileOutStream = new FileOutputStream(uploadedFile); Throwable var13 = null;
try { //文件写入 fileItem.getDataHandler().writeTo(fileOutStream); fileOutStream.flush(); } catch (Throwable var31) { } finally }
response.setContentType("text/plain; charset=utf-8"); ((Map)fileResourceMap).put(uuid, uploadedFile.getAbsolutePath()); //返回UUID值也是文件上级目录名 out.write(uuid); } } catch (Exception var33) { } finally { }
return true;}
从上面部分代码可以看出文件的上传是没有做任何的限制,上传路径完全可控,文件内容,文件后缀都是可控的,所以我们先上传一个文件看看。


WSO2 RCE(CVE-2022-29464) 漏洞复现


可以看到返回了UUID,也就是文件上级目录名,接下来到服务器上查找这个文件的位置,发现上传成功。


WSO2 RCE(CVE-2022-29464) 漏洞复现


可以看到上传位置是在项目根目录下的tmp目录中,但是此时的文件无法利用,不过在前文中知道了文件上传路径是完全可控的,所以我们就需要找到能解析jsp页面的目录。


WSO2 RCE(CVE-2022-29464) 漏洞复现


通过全局查找jsp文件存储位置,我们看到了有一个webapps目录,这次修改文件上传路径。
../../../../repository/deployment/server/webapps/authenticationendpoint/y2an0.jsp


WSO2 RCE(CVE-2022-29464) 漏洞复现


发现恶意文件已经上传到想要的目录


WSO2 RCE(CVE-2022-29464) 漏洞复现


成功执行了命令


WSO2 RCE(CVE-2022-29464) 漏洞复现


03

解决方案

WSO2 RCE(CVE-2022-29464) 漏洞复现


更新至最新版本,如未发布最新版本只需要使用缓解措施依旧能够解决问题。

具体解决方案:

https://docs.wso2.com/pages/viewpage.action?pageId=180952746


FRIDAY LAB

星期五实验室成立于2017年,汇集众多技术研究人员,在工业互联网安全前瞻技术研究方向上不断进取。星期五实验室由海内外知名高校的学院精英及来自于顶尖企业的行业专家组成,且大部分人员来自国际领先、国内知名的黑客战队——浙大AAA战队。作为木链科技专业的技术研发团队,星期五实验室凭借精湛的专业技术水平,为产品研发提供新思路、为行业技术革新探索新方向。
WSO2 RCE(CVE-2022-29464) 漏洞复现
WSO2 RCE(CVE-2022-29464) 漏洞复现
WSO2 RCE(CVE-2022-29464) 漏洞复现
WSO2 RCE(CVE-2022-29464) 漏洞复现
WSO2 RCE(CVE-2022-29464) 漏洞复现

扫二维码|关注我们

星期五实验室
FRIDAY LAB


原文始发于微信公众号(星期五实验室):WSO2 RCE(CVE-2022-29464) 漏洞复现

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年4月27日20:41:28
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  WSO2 RCE(CVE-2022-29464) 漏洞复现 http://cn-sec.com/archives/952669.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: