VAITP Dataset

← Back to the dataset

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.

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 ::