Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
wso2-rce-cve-2022-29464 — Exploit pour CVE-2022-29464, une vulnérabilité de téléchargement de fichier arbitraire non authentifié dans les serveurs WSO2, permettant l'exécution de code à distance via le téléchargement d'un fichier JSP malveillant. | Kitploit
Outils/GitHubGitHub/tufanturhan/wso2-rce-cve-2022-29464
Génération de PayloadsAnalyse des VulnérabilitésExploitationExploitation d'Applications WebTests d'Intrusion
GitHubtufanturhan/wso2-rce-cve-2022-29464

wso2-rce-cve-2022-29464

Exploit pour CVE-2022-29464, une vulnérabilité de téléchargement de fichier arbitraire non authentifié dans les serveurs WSO2, permettant l'exécution de code à distance via le téléchargement d'un fichier JSP malveillant.

Voir le dépôt
21il y a 4 ansPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2022-29464

Exploit RCE WSO2 (CVE-2022-29464).

Détails

CVE-2022-29464 est une vulnérabilité critique sur WSO2 découverte par Orange Tsai. La vulnérabilité est un téléchargement de fichier arbitraire non authentifié et sans restriction qui permet aux attaquants non authentifiés d'obtenir une RCE sur les serveurs WSO2 en téléchargeant des fichiers JSP malveillants.

La route de téléchargement vulnérable est /fileupload qui est gérée par FileUploadServlet qui est une route non protégée comme on peut le voir dans le fichier de configuration indentity.xml :```xml

root@kitploit:~
le `FileUploadServlet` et lors de [`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) et à travers une série d'appels de méthodes charge finalement à partir du fichier de configuration `carbon.xml` plusieurs formats/actions de téléversement ainsi que l'objet qui gère chaque format.```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);
        }
    }

le constructeur de la classe FileUploadExecutorManager est le suivant :```java public FileUploadExecutorManager(BundleContext bundleContext, ConfigurationContext configCtx, String webContext) throws CarbonException { this.bundleContext = bundleContext; this.configContext = configCtx; this.webContext = webContext; this.loadExecutorMap(); }

root@kitploit:~
le constructeur appelle la méthode privée [`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) qui est l'endroit où le chargement de la configuration est effectué :```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]

Les configurations des formats de téléchargement de fichiers se trouvent dans l'espace de noms FileUploadConfig dans le fichier de configuration XML, voici la configuration par défaut :```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:~
la méthode `loadExecutorMap()` crée et remplit une `HashMap` de `<Action, Class>` avec les Actions et les Classes extraites du fichier de configuration. ce qui sera utilisé plus tard pour choisir la classe à utiliser pour gérer correctement un format/action donné.

Plus tard, lorsque la route `/fileupload` reçoit une requête POST, la méthode [`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) du servlet sera appelée. la méthode transfère simplement les objets requête et réponse à la méthode `execute()` de `fileUploadExecutorManager` qui a été initialisée dans `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);
        }
    }

la méthode execute(), divise l'URL de la requête juste après la chaîne fileupload/, ce qui signifie qu'elle extrait tout ce qui se trouve après le /fileupload/ dans l'URL de la requête et l'assigne à 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:~
le `actionString` est passé au constructeur de la classe `CarbonXmlFileUploadExecHandler` avec `request` et `response` :```java
        private CarbonXmlFileUploadExecHandler(HttpServletRequest request,
                                               HttpServletResponse response,
                                               String actionString) {
            this.request = request;
            this.response = response;
            this.actionString = actionString;
        }

le constructeur les enregistrera dans ses propriétés. après cela, l'objet carbonXmlExecHandler avec d'autres objets sera ajouté à execHandlerManager en utilisant la méthode addExecHandler().```java public void addExecHandler(FileUploadExecutionHandler handler) { if (prevHandler != null) { prevHandler.setNext(handler); } else { firstHandler = handler; } prevHandler = handler; }

root@kitploit:~
ensuite `execHandlerManager.startExec()` est appelé :```java
        public void startExec() throws IOException {
            firstHandler.execute();
        }

startExec() appelle execute() du premier objet ajouté qui est 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) parcourt la `HashMap` de `<Action, Class>` créée précédemment et trouve l'Action (clé) qui est égale à `actionString`. Si elle est trouvée, la méthode `executeGeneric()` de l'objet associé à cette Action sera appelée.
Pour réviser, la configuration par défaut comporte 7 actions :
* `keystore`, `certificate`, `*` gérés par `org.wso2.carbon.ui.transports.fileupload.AnyFileUploadExecutor`
* `jarZip` géré par `org.wso2.carbon.ui.transports.fileupload.JarZipUploadExecutor`
* `dbs` géré par `org.wso2.carbon.ui.transports.fileupload.DBSFileUploadExecutor`
* `tools` géré par `org.wso2.carbon.ui.transports.fileupload.ToolsFileUploadExecutor`
* `toolsAny` géré par `org.wso2.carbon.ui.transports.fileupload.ToolsAnyFileUploadExecutor`
Chacun de ces objets gère le téléversement de manière différente ; certains acceptent des extensions spécifiques.

Le premier que j'ai trouvé vulnérable à une écriture de fichier arbitraire était `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` ne possède pas de méthode `executeGeneric()` mais étend [`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) qui, elle, possède une méthode [`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() appelle d'abord parseRequest() avec l'objet request comme paramètre :```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:~
il assure d'abord que la requête POST est une requête POST multipart, puis extrait les fichiers téléchargés, s'assure que la requête POST contient au moins un fichier téléchargé et le valide par rapport à la taille maximale du fichier.
après être revenu de `parseRequest()`, `executeGeneric()` appellera maintenant la méthode `execute()` qui est [surchargée](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) par `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;
	}

C'est là que se trouve le bug : la méthode execute() est vulnérable à une traversée de chemin car elle fait confiance au nom de fichier fourni par l'utilisateur dans la requête POST. Sans échappement de la traversée de chemin pour sortir du répertoire temporaire, le fichier est en fait enregistré dans :``` ./tmp/work/extra/$uuid/$filename

root@kitploit:~
avec `uuid` étant renvoyé dans la réponse :

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

le fichier peut être trouvé dans :

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

Maintenant, il suffit de sortir du répertoire `tmp` et d'ajouter notre shell JSP à un emplacement servi par WSO2. L'un de ces emplacements est `./repository/deployment/server/webapps` :
![image](https://assets.kitploit.com/production/public/readmes/33730/0b60e9e33d9ed74a78436d46e069d59fa84c773cd381c729400d6fc811c8ce09.png)

Ce répertoire contient plusieurs applications WAR déployées ainsi que des fichiers WAR bruts. L'une de ces applications WAR est `authenticationendpoint` qui gère l'authentification auprès de WSO2 et son emplacement est `./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)
Télécharger l’outil