Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

Infinite loop in ChunkHeader._load_strings / _load_templates on a crafted chunk (cyclic next_offset)

Aperta Adatta ai principianti
#101 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

@memx13 ci sta già lavorando.

Dal 23/10/2026.

  • #102 di @memx13 — aperta

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
78/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
python
Ambito
backend, security

Direzione di ricerca

Leggi Evtx/Evtx.py, concentrandoti su ChunkHeader._load_strings e _load_templates e sui campi next_offset in Nodes.py. Inizia riproducendo, con un timeout, la prova di concetto fornita sugli offset ciclici, quindi verifica se entrambi i loader incontrano offset ripetuti. Il lavoro è completato quando le catene cicliche ritornano invece di bloccarsi e i test di regressione coprono i casi di ciclo.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Summary

Evtx.Evtx.ChunkHeader._load_strings and ._load_templates walk each hash-bucket's on-disk next_offset chain with no guard against an offset that repeats. Because next_offset is read straight from the file, a crafted chunk whose string (or template) chain is cyclic — node A's next_offset points to B and B's points back to A — makes the while ofs > 0: loop run forever. Parsing an untrusted .evtx then hangs the process indefinitely (CWE-835, uncontrolled loop / denial of service).

This is separate from the length-0 records() loop fixed in #17; these two chunk loaders have no cycle/visited protection, and the problem is still present on master (c000744).

Affected code

Evtx/Evtx.py:

def _load_strings(self):
    ...
    for i in range(64):
        ofs = self.unpack_dword(0x80 + (i * 4))
        while ofs > 0:
            string_node = self.add_string(ofs)
            ofs = string_node.next_offset()   # dword read straight from the file

next_offset is a dword read directly from the buffer (Nodes.py, NameStringNode / TemplateNode: declare_field("dword", "next_offset", 0x0)), so an attacker fully controls it. _load_templates has the same shape — it checks a 0x0C token and a self-pointer per node, but two mutually-pointing templates satisfy both checks, so it can cycle too.

Reachability

Evtx(path).records() iterates chunks without verifying their checksums, and rendering a record reaches add_string → _load_strings. So a single crafted file passed to evtx_dump badfile.evtx hangs the process.

Proof of concept

Builds one 64 KB chunk whose first string bucket points at a two-node cycle (A↔B). The vulnerable call never returns, so run it under a timeout:

import struct
from Evtx.Evtx import ChunkHeader

buf = bytearray(0x10000)
buf[0:8] = b"ElfChnk\x00"
a, b = 0x200, 0x210
struct.pack_into("<I", buf, 0x80, a)   # string hash bucket[0] -> A
struct.pack_into("<I", buf, a, b)      # A.next_offset -> B
struct.pack_into("<H", buf, a + 6, 0)  # A.string_length = 0
struct.pack_into("<I", buf, b, a)      # B.next_offset -> A  (A <-> B)
struct.pack_into("<H", buf, b + 6, 0)  # B.string_length = 0

ChunkHeader(bytes(buf), 0).strings()   # never returns

Measured on master (c000744): a non-cyclic bucket returns in ~0.002 s; the cyclic one does not return (killed after 8 s). Reproduced on Python 3.14 (the loop is version-independent).

Suggested fix

Track the offsets already visited while walking a bucket and stop when one repeats. I'll open a PR with the fix plus a regression test that fails on current master and passes with the change.

Environment
  • python-evtx master (c000744), version 0.8.1
  • Python 3.14 (reproduces on 3.9–3.14; not version-specific)
Lingua principale
Python
Stelle
783
Fork
169
Merge medio
2g 21h
PR unite (30g)
1

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di williballenthin/python-evtx

Tutte le issue di williballenthin/python-evtx

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.