Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

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

Đang mở Phù hợp với người mới
#101 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

@memx13 đang làm issue này rồi.

Từ ngày 23/10/2026.

  • #102 của @memx13 — đang mở

Đánh giá

Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức phù hợp với người mới
78/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
python
Lĩnh vực
backend, security

Hướng nghiên cứu

Đọc Evtx/Evtx.py, tập trung vào ChunkHeader._load_strings và _load_templates cũng như các trường next_offset trong Nodes.py. Trước tiên, hãy tái hiện bằng chứng khái niệm được cung cấp về các offset tuần hoàn với thời gian chờ giới hạn, sau đó kiểm tra xem cả hai bộ nạp có gặp các offset lặp lại hay không. Hoàn tất khi các chuỗi tuần hoàn trả về thay vì bị treo và các bài kiểm thử hồi quy bao quát những trường hợp chu kỳ.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

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)
Ngôn ngữ chính
Python
Star
783
Fork
169
Merge trung bình
2 ngày 21 giờ
Pull request đã merge (30 ngày)
1

Chuẩn bị môi trường

Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của williballenthin/python-evtx

Tất cả issue của williballenthin/python-evtx

Issue tương tự

Thêm issue về Python

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.