Skip to content

NSEC _read_bitmap does not bound bitmap_length against the record end #1725

@bluetoothbot

Description

@bluetoothbot

Problem

_read_bitmap(end) reads an attacker-controlled bitmap_length byte and then unconditionally does self.offset += 2 + bitmap_length, with no check that offset_plus_two + bitmap_length <= end. Because Python slicing is forgiving, the inner self.data[offset_plus_two:bitmap_end] does not raise even when bitmap_end overshoots — it simply consumes adjacent bytes (the next record's header) as bitmap data and then leaves self.offset past the NSEC record's declared end. _read_others only resets self.offset = end in the exception path, so a malformed-but-non-throwing NSEC silently corrupts the parse offset for every subsequent record in the same packet, and the bitmap window/byte arithmetic can convert two random adjacent bytes into hundreds of rdtypes entries that get cached on the resulting DNSNsec.

Why This Matters

Single-packet impact only (record-boundary confusion + a few KB of synthesized rdtypes cached as long as the NSEC stays in the DNSCache), but it lets a malicious LAN peer suppress legitimate records in a packet (subsequent records fail to parse or are skipped) and pollute the NSEC cache with attacker-chosen "absent" type bits. That second effect can be used to talk an AddressResolver out of issuing follow-up queries for a real host, since NSEC negative answers gate that decision.

Suggested Fix

After reading bitmap_length, clamp / validate against end: if offset_plus_two + bitmap_length > end: raise IncomingDecodeError(...). Also validate window < 256 (it already fits in a byte) and bound the total rdtypes length so a 255-byte window can't compose with multiple windows to bloat the in-memory cached record.

Details

Severity 🟡 Medium
Category memory_safety
Location src/zeroconf/_protocol/incoming.py:383-399
Effort ⚡ Quick fix

🤖 Created by Kōan from audit session

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions