Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
wso2-rce-cve-2022-29464 — Exploit para CVE-2022-29464, una vulnerabilidad de carga de archivos arbitraria no autenticada en servidores WSO2, que permite la ejecución remota de código mediante la carga de un archivo JSP malicioso. | Kitploit
Herramientas/GitHubGitHub/tufanturhan/wso2-rce-cve-2022-29464
Generación de PayloadsAnálisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebPruebas de Penetración
GitHubtufanturhan/wso2-rce-cve-2022-29464

wso2-rce-cve-2022-29464

Exploit para CVE-2022-29464, una vulnerabilidad de carga de archivos arbitraria no autenticada en servidores WSO2, que permite la ejecución remota de código mediante la carga de un archivo JSP malicioso.

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Ver Repositorio
21hace 4 añosAún no revisado
Compartir

CVE-2022-29464

Exploit de WSO2 RCE (CVE-2022-29464).

Details

CVE-2022-29464 es una vulnerabilidad crítica en WSO2 descubierta por Orange Tsai. La vulnerabilidad es una subida de archivos arbitrarios no autenticada y sin restricciones que permite a atacantes no autenticados obtener RCE en servidores WSO2 mediante la subida de archivos JSP maliciosos.

La ruta de subida vulnerable es /fileupload, que es gestionada por FileUploadServlet, que es una ruta sin protección como podemos ver en el archivo de configuración indentity.xml:```xml

root@kitploit:~
el `FileUploadServlet` y en [`init`](https://github.com/wso2/carbon-kernel/blob/d47232dfb2b26c0ef18a74e2ef4aa503caa59697/core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/transports/FileUploadServlet.java#L71) y a través de una serie de llamadas a métodos carga finalmente desde el archivo de configuración `carbon.xml` múltiples formatos/acciones de carga de archivos junto con el objeto que maneja cada formato.```java
    public void init(ServletConfig servletConfig) throws ServletException {
        this.servletConfig = servletConfig;
        try {
            fileUploadExecutorManager = new FileUploadExecutorManager(bundleContext, configContext, webContext);
            //Registering FileUploadExecutor Manager as an OSGi service
            bundleContext.registerService(FileUploadExecutorManager.class.getName(), fileUploadExecutorManager, null);
        } catch (CarbonException e) {
            log.error("Exception occurred while trying to initialize FileUploadServlet", e);
            throw new ServletException(e);
        }
    }

el constructor de la clase FileUploadExecutorManager es el siguiente:```java public FileUploadExecutorManager(BundleContext bundleContext, ConfigurationContext configCtx, String webContext) throws CarbonException { this.bundleContext = bundleContext; this.configContext = configCtx; this.webContext = webContext; this.loadExecutorMap(); }

root@kitploit:~
el constructor llama al método privado [`loadExecutorMap()`](https://github.com/wso2/carbon-kernel/blob/d47232dfb2b26c0ef18a74e2ef4aa503caa59697/core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/transports/fileupload/FileUploadExecutorManager.java#L131) que es donde se realiza la carga de la configuración:```java
    private void loadExecutorMap() throws CarbonException {
        [snipped]
                try {
            documentElement = XMLUtils.toOM(serverConfiguration.getDocumentElement());
        } catch (Exception e) {
            String msg = "Unable to read Server Configuration.";
            log.error(msg);
            throw new CarbonException(msg, e);
        }
        [snipped]
        OMElement fileUploadConfigElement =
                documentElement.getFirstChildWithName(
                        new QName(ServerConstants.CARBON_SERVER_XML_NAMESPACE, "FileUploadConfig"));
        for (Iterator iterator = fileUploadConfigElement.getChildElements(); iterator.hasNext();) {
            OMElement mapppingElement = (OMElement) iterator.next();
            if (mapppingElement.getLocalName().equalsIgnoreCase("Mapping")) {
                OMElement actionsElement =
                        mapppingElement.getFirstChildWithName(
                                new QName(ServerConstants.CARBON_SERVER_XML_NAMESPACE, "Actions"));
                String confPath = System.getProperty(CarbonBaseConstants.CARBON_CONFIG_DIR_PATH);
        [snipped]

las configuraciones de los formatos de carga de archivos se encuentran dentro del espacio de nombres FileUploadConfig en el archivo de configuración XML, esta es la configuración predeterminada:```xml 100

root@kitploit:~
    <Mapping>
        <Actions>
            <Action>keystore</Action>
            <Action>certificate</Action>
            <Action>*</Action>
        </Actions>
        <Class>org.wso2.carbon.ui.transports.fileupload.AnyFileUploadExecutor</Class>
    </Mapping>

    <Mapping>
        <Actions>
            <Action>jarZip</Action>
        </Actions>
        <Class>org.wso2.carbon.ui.transports.fileupload.JarZipUploadExecutor</Class>
    </Mapping>
    <Mapping>
        <Actions>
            <Action>dbs</Action>
        </Actions>
        <Class>org.wso2.carbon.ui.transports.fileupload.DBSFileUploadExecutor</Class>
    </Mapping>
    <Mapping>
        <Actions>
            <Action>tools</Action>
        </Actions>
        <Class>org.wso2.carbon.ui.transports.fileupload.ToolsFileUploadExecutor</Class>
    </Mapping>
    <Mapping>
        <Actions>
            <Action>toolsAny</Action>
        </Actions>
        <Class>org.wso2.carbon.ui.transports.fileupload.ToolsAnyFileUploadExecutor</Class>
    </Mapping>
</FileUploadConfig>
root@kitploit:~
el método `loadExecutorMap()` crea y rellena un `HashMap` de `<Action, Class>` con las Actions y las Classes extraídas del archivo de configuración, que se usará más tarde para elegir qué clase utilizar para manejar adecuadamente un formato/acción determinado.

Más tarde, cuando la ruta `/fileupload` recibe una solicitud POST, se llamará al método [`doPost()`](https://github.com/wso2/carbon-kernel/blob/d47232dfb2b26c0ef18a74e2ef4aa503caa59697/core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/transports/FileUploadServlet.java#L53) del servlet. El método simplemente reenvía los objetos de solicitud y respuesta al método `execute()` de `fileUploadExecutorManager`, que se inicializó en `init()`.```java
    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);
        }
    }

el método execute(), divide la URL de la solicitud justo después de la cadena fileupload/, lo que significa que extrae lo que esté después de /fileupload/ en la URL de la solicitud y lo asigna a actionString.```java public boolean execute(HttpServletRequest request, HttpServletResponse response) throws IOException {

root@kitploit:~
    HttpSession session = request.getSession();
    String cookie = (String) session.getAttribute(ServerConstants.ADMIN_SERVICE_COOKIE);
    request.setAttribute(CarbonConstants.ADMIN_SERVICE_COOKIE, cookie);
    request.setAttribute(CarbonConstants.WEB_CONTEXT, webContext);
    request.setAttribute(CarbonConstants.SERVER_URL,
                         CarbonUIUtil.getServerURL(request.getSession().getServletContext(),
                                                   request.getSession()));


    String requestURI = request.getRequestURI();

    //TODO - fileupload is hardcoded
    int indexToSplit = requestURI.indexOf("fileupload/") + "fileupload/".length();
    String actionString = requestURI.substring(indexToSplit);

    // Register execution handlers
    FileUploadExecutionHandlerManager execHandlerManager =
            new FileUploadExecutionHandlerManager();
    CarbonXmlFileUploadExecHandler carbonXmlExecHandler =
            new CarbonXmlFileUploadExecHandler(request, response, actionString);
    execHandlerManager.addExecHandler(carbonXmlExecHandler);
    OSGiFileUploadExecHandler osgiExecHandler =
            new OSGiFileUploadExecHandler(request, response);
    execHandlerManager.addExecHandler(osgiExecHandler);
    AnyFileUploadExecHandler anyFileExecHandler =
            new AnyFileUploadExecHandler(request, response);
    execHandlerManager.addExecHandler(anyFileExecHandler);
    execHandlerManager.startExec();
    return true;
}
root@kitploit:~
el `actionString` se pasa al constructor de la clase `CarbonXmlFileUploadExecHandler` junto con `request` y `response`:```java
        private CarbonXmlFileUploadExecHandler(HttpServletRequest request,
                                               HttpServletResponse response,
                                               String actionString) {
            this.request = request;
            this.response = response;
            this.actionString = actionString;
        }

el constructor los guardará en sus propiedades. después de eso, el objeto carbonXmlExecHandler junto con otros objetos se añadirán a execHandlerManager usando el método addExecHandler().```java public void addExecHandler(FileUploadExecutionHandler handler) { if (prevHandler != null) { prevHandler.setNext(handler); } else { firstHandler = handler; } prevHandler = handler; }

root@kitploit:~
Entonces se llama a `execHandlerManager.startExec()`:```java
        public void startExec() throws IOException {
            firstHandler.execute();
        }

startExec() llama a execute() del primer objeto agregado que es CarbonXmlFileUploadExecHandler:```java public void execute() throws IOException { boolean foundExecutor = false; for (String key : executorMap.keySet()) { if (key.equals(actionString)) { AbstractFileUploadExecutor obj = executorMap.get(key); foundExecutor = true; obj.executeGeneric(request, response, configContext); break; } } if (!foundExecutor) { next(); } }

root@kitploit:~
[`execute()`](https://github.com/wso2/carbon-kernel/blob/d47232dfb2b26c0ef18a74e2ef4aa503caa59697/core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/transports/fileupload/FileUploadExecutorManager.java#L430) recorre el `HashMap` de `<Action, Class>` creado anteriormente y encuentra la Action (clave) que es igual a `actionString`; si la encuentra, se llamará al método `executeGeneric()` del objeto asociado a esa Action.
al revisar la configuración predeterminada tiene 7 acciones, que son:
* `keystore`, `certificate`, `*` manejadas por `org.wso2.carbon.ui.transports.fileupload.AnyFileUploadExecutor`
* `jarZip` manejada por `org.wso2.carbon.ui.transports.fileupload.JarZipUploadExecutor`
* `dbs` manejada por `org.wso2.carbon.ui.transports.fileupload.DBSFileUploadExecutor`
* `tools` manejada por `org.wso2.carbon.ui.transports.fileupload.ToolsFileUploadExecutor`
* `toolsAny` manejada por `org.wso2.carbon.ui.transports.fileupload.ToolsAnyFileUploadExecutor`
cada uno de estos objetos maneja la subida de forma diferente; algunos de ellos aceptan extensiones específicas.

el primero que encontré vulnerable a escritura arbitraria de archivos fue `toolsAny` ([`ToolsAnyFileUploadExecutor`](https://github.com/wso2/carbon-kernel/blob/4.4.x/core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/transports/fileupload/ToolsAnyFileUploadExecutor.java)).
`ToolsAnyFileUploadExecutor` no tiene un método `executeGeneric()` pero extiende [`AbstractFileUploadExecutor`](https://github.com/wso2/carbon-kernel/blob/d47232dfb2b26c0ef18a74e2ef4aa503caa59697/core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/transports/fileupload/AbstractFileUploadExecutor.java#L61) que sí tiene un método [`executeGeneric()`](https://github.com/wso2/carbon-kernel/blob/d47232dfb2b26c0ef18a74e2ef4aa503caa59697/core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/transports/fileupload/AbstractFileUploadExecutor.java#L97):```java
    boolean executeGeneric(HttpServletRequest request,
                           HttpServletResponse response,
                           ConfigurationContext configurationContext) throws IOException {//,
        //    CarbonException {
        this.configurationContext = configurationContext;
        try {
            parseRequest(request);
            return execute(request, response);
        } catch (FileUploadFailedException e) {
            sendErrorRedirect(request, response, e);
        } catch (FileSizeLimitExceededException e) {
            sendErrorRedirect(request, response, e);
        } catch (CarbonException e) {
            sendErrorRedirect(request, response, e);
        }
        return false;
    }

executeGeneric() llama primero a parseRequest() con el objeto de solicitud como parámetro:```java protected void parseRequest(HttpServletRequest request) throws FileUploadFailedException, FileSizeLimitExceededException { fileItemsMap.set(new HashMap<String, ArrayList>()); formFieldsMap.set(new HashMap<String, ArrayList>());

root@kitploit:~
    ServletRequestContext servletRequestContext = new ServletRequestContext(request);
    boolean isMultipart = ServletFileUpload.isMultipartContent(servletRequestContext);
    Long totalFileSize = 0L;

    if (isMultipart) {

        List items;
        try {
            items = parseRequest(servletRequestContext);
        } catch (FileUploadException e) {
            String msg = "File upload failed";
            log.error(msg, e);
            throw new FileUploadFailedException(msg, e);
        }
        boolean multiItems = false;
        if (items.size() > 1) {
            multiItems = true;
        }

        // Add the uploaded items to the corresponding maps.
        for (Iterator iter = items.iterator(); iter.hasNext();) {
            FileItem item = (FileItem) iter.next();
            String fieldName = item.getFieldName().trim();
            if (item.isFormField()) {
                if (formFieldsMap.get().get(fieldName) == null) {
                    formFieldsMap.get().put(fieldName, new ArrayList<String>());
                }
                try {
                    formFieldsMap.get().get(fieldName).add(new String(item.get(), "UTF-8"));
                } catch (UnsupportedEncodingException ignore) {
                }
            } else {
                String fileName = item.getName();
                if ((fileName == null || fileName.length() == 0) && multiItems) {
                    continue;
                }
                if (fileItemsMap.get().get(fieldName) == null) {
                    fileItemsMap.get().put(fieldName, new ArrayList<FileItemData>());
                }
                totalFileSize += item.getSize();
                if (totalFileSize < totalFileUploadSizeLimit) {
                    fileItemsMap.get().get(fieldName).add(new FileItemData(item));
                } else {
                    throw new FileSizeLimitExceededException(getFileSizeLimit() / 1024 / 1024);
                }
            }
        }
    }
}
root@kitploit:~
primero se asegura de que la solicitud POST sea una solicitud POST multipart y luego extrae los archivos subidos, se asegura de que la solicitud POST contenga al menos un archivo subido y lo valida contra el tamaño máximo de archivo.
después de retornar de `parseRequest()`, `executeGeneric()` llamará ahora al método `execute()`, que es [anulado](https://github.com/wso2/carbon-kernel/blob/d47232dfb2b26c0ef18a74e2ef4aa503caa59697/core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/transports/fileupload/ToolsAnyFileUploadExecutor.java#L36) por `ToolsAnyFileUploadExecutor`:```java
	@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;
	}

Aquí es donde reside el fallo: el método execute() es vulnerable a una vulnerabilidad de path traversal, ya que confía en el nombre de archivo proporcionado por el usuario en la solicitud POST. Sin que el path traversal escape del directorio tmp, el archivo se guarda realmente en:``` ./tmp/work/extra/$uuid/$filename

root@kitploit:~
con `uuid` devolviéndose en la respuesta:

![image](https://assets.kitploit.com/production/public/readmes/33730/46ab2e31428a23ca42c93423c5c2a7508cb72c7e508d0a7e5405a35c27a4f619.png)

el archivo se puede encontrar en:

![image](https://assets.kitploit.com/production/public/readmes/33730/49f94872497ef3ce08545f18bf26a84e60729c3ad0faef81819d2af8adf44f1d.png)

Ahora solo necesitamos salir del directorio `tmp` y añadir nuestra shell JSP a alguna ubicación servida por WSO2. una de estas ubicaciones es `./repository/deployment/server/webapps`:
![image](https://assets.kitploit.com/production/public/readmes/33730/0b60e9e33d9ed74a78436d46e069d59fa84c773cd381c729400d6fc811c8ce09.png)

este directorio contiene múltiples aplicaciones WAR desplegadas y también archivos WAR sin procesar. una de esas aplicaciones WAR es `authenticationendpoint`, que gestiona la autenticación de WSO2 y su ubicación es `./repository/deployment/server/webapps/authenticationendpoint`:
![image](https://assets.kitploit.com/production/public/readmes/33730/ec6897e79bbb927cd87141ba9fd07d303ffe35f3c075c53982da6c3f3126bb52.png)

# PoC
![image](https://assets.kitploit.com/production/public/readmes/33730/f18951e9acbdfdbd282f6c83037d849069b2225774598bd70d1a135ff83bdc1c.png)

![image](https://assets.kitploit.com/production/public/readmes/33730/b513180803a0562bebfc66ea9dca8572ea6f9f8bc63a898c4e32cb811b0c2ebc.png)

![image](https://assets.kitploit.com/production/public/readmes/33730/0d02bf7c174a316d5acbdc73c245cefc1a9ee00d54887a3306f6a897708474f5.png)
Descargar herramienta