CVE-2021-41168
Snudown Markdown parser Hash collision DoS
- CVSS 6.5
- CWE-407
- Resource Management
- Remote
Snudown is a reddit-specific fork of the Sundown Markdown parser used by GitHub, with Python integration added. In affected versions snudown was found to be vulnerable to denial of service attacks to its reference table implementation. References written in markdown ` [reference_name]: https://www.example.com` are inserted into a hash table which was found to have a weak hash function, meaning that an attacker can reliably generate a large number of collisions for it. This makes the hash table vulnerable to a hash-collision DoS attack, a type of algorithmic complexity attack. Further the hash table allowed for duplicate entries resulting in long retrieval times. Proofs of concept and further discussion of the hash collision issue are discussed on the snudown GHSA(https://github.com/reddit/snudown/security/advisories/GHSA-6gvv-9q92-w5f6). Users are advised to update to version 1.7.0.
- CWE
- CWE-407
- CVSS base score
- 6.5
- Published
- 2021-10-21
- OWASP
- A08 Software and Data Integrity Failures
- Orthogonal defect classification
- Algorithm
- Code defect classification
- Incorrect Algorithm
- Category
- Resource Management
- Subcategory
- Resource Exhaustion
- Accessibility scope
- Remote
- Impact
- Denial of Service (DoS)
- Fixed by upgrading
- Yes
Solution
Update Snudown to version 1.7.0 or higher.
Vulnerable code sample
class ReferenceTable:
def __init__(self):
self.references = {}
def add_reference(self, name, url):
if name in self.references:
self.references[name].append(url)
else:
self.references[name] = [url]
def get_reference(self, name):
return self.references.get(name, None)
table = ReferenceTable()
for i in range(1000):
table.add_reference("collision_key", f"https://www.example.com/{i}")
print(table.get_reference("collision_key"))Patched code sample
import re
class ReferenceTable:
def __init__(self, max_refs_per_key=100):
self.references = {}
self.max_refs_per_key = max_refs_per_key
def is_valid_url(self, url):
return re.match(r'^https://[a-zA-Z0-9./_-]+$', url) is not None
def add_reference(self, name, url):
if not self.is_valid_url(url):
return
refs = self.references.get(name, [])
if len(refs) < self.max_refs_per_key:
refs.append(url)
self.references[name] = refs
def get_reference(self, name):
return self.references.get(name, [])
table = ReferenceTable()
for i in range(1000):
table.add_reference("collision_key", f"https://www.example.com/{i}")
print(table.get_reference("collision_key"))Cite this entry
@misc{vaitp:cve202141168,
title = {{Snudown Markdown parser Hash collision DoS}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2021},
note = {VAITP Python Vulnerability Dataset, entry CVE-2021-41168},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2021-41168/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
