| # ONNX FunctionProto DoS PoC |
|
|
| **CVE:** TBD (submitted to huntr.com) |
| **Severity:** CVSS 7.5 High (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H) |
| **CWE:** CWE-400 Uncontrolled Resource Consumption |
| **Affected:** onnx <= 1.21.0 |
|
|
| ## Description |
|
|
| Non-recursive FunctionProto call graph expansion causes exponential CPU exhaustion during ONNX shape inference. |
|
|
| The ONNX checker validates that functions are not directly recursive but does NOT limit the total work done when resolving a non-recursive DAG of function calls. |
|
|
| This is the ONNX equivalent of the **XML Billion Laughs** (CVE-2003-1564) attack. |
|
|
| ## PoC Files |
|
|
| | File | N | File Size | Shape Inference Time | |
| |------|---|-----------|---------------------| |
| | `onnx_functionproto_dos_n35.onnx` | 35 | 3,939 bytes | **23.96 seconds** | |
| | `onnx_functionproto_dos_n40.onnx` | 40 | 4,509 bytes | **266 seconds (4+ min)** | |
|
|
| ## Reproduction |
|
|
| ```python |
| import onnx, time |
| |
| # Load and run shape inference on the PoC file |
| model = onnx.load("onnx_functionproto_dos_n40.onnx") |
| |
| # Step 1: Checker passes (no direct recursion) |
| onnx.checker.check_model(model) # passes without error |
| |
| # Step 2: Shape inference triggers CPU exhaustion |
| t0 = time.time() |
| onnx.shape_inference.infer_shapes(model) # takes 266+ seconds |
| print(f"Took {time.time()-t0:.1f}s") |
| ``` |
|
|
| ## Growth Rate |
|
|
| Time grows at rate ~phi^N (golden ratio ~1.618) per additional function: |
| - N=30: 2.2s |
| - N=35: 24s |
| - N=40: 266s |
| - N=45: ~2940s (49 min) |
| - N=50: ~32000s (9 hours) |
|
|
| All from files < 5 KB. |
|
|
| ## Responsible Disclosure |
|
|
| Reported via [huntr.com](https://huntr.com) bug bounty program. |
|
|