| --- |
| license: mit |
| tags: |
| - security |
| - proof-of-concept |
| - mleap |
| - denial-of-service |
| --- |
| |
| # MLeap TensorFlow `GraphDef` native-crash PoC |
|
|
| This repository contains a proof-of-concept malicious `.mleap` file for a responsibly-disclosed |
| vulnerability in [`combust/mleap`](https://github.com/combust/mleap) (tested at commit |
| `88de54dd4fb7720c7c56ff5c2b51cdec4353a128`), reported via huntr's Model File Vulnerability |
| program. |
|
|
| ## What this file is |
|
|
| `tf_crash_poc.zip` is a syntactically valid, standard-format `.mleap` bundle (built with MLeap's |
| own `BundleWriter`, not hand-crafted) containing a single root `tensorflow` node whose embedded |
| `graph.pb` is **0 bytes** β a syntactically valid, trivially empty TensorFlow `GraphDef` protobuf |
| message β and which declares **zero** input/output tensors and no target nodes. |
|
|
| ## What happens when you load it |
|
|
| ```scala |
| import ml.combust.bundle.BundleFile |
| import ml.combust.mleap.runtime.MleapSupport._ |
| import ml.combust.mleap.runtime.MleapContext.defaultContext |
| import ml.combust.mleap.runtime.frame.DefaultLeapFrame |
| import ml.combust.mleap.core.types.StructType |
| |
| val bundle = BundleFile(new java.io.File("tf_crash_poc.zip")).loadMleapBundle().get |
| val transformer = bundle.root |
| val emptyFrame = DefaultLeapFrame(StructType(Seq()).get, Seq(ml.combust.mleap.runtime.frame.Row())) |
| transformer.transform(emptyFrame) // <-- crashes the JVM here |
| ``` |
|
|
| Loading the bundle succeeds without error (MLeap performs no validation of the embedded graph |
| bytes at load time). Running inference on it β the ordinary, expected way to use a loaded MLeap |
| pipeline β triggers a **native access violation** inside TensorFlow's own C API: |
|
|
| ``` |
| # A fatal error has been detected by the Java Runtime Environment: |
| # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffc6f92f3f7, ... |
| # The crash happened outside the Java Virtual Machine in native code. |
| ``` |
|
|
| with the fault located precisely in `TF_GraphImportGraphDef`, called from |
| `ml.combust.mleap.tensorflow.TensorflowModel.getSessionFromFrozenGraph()`. See |
| `verification-log.txt` in this repository for the full, unmodified crash output and stack trace |
| from the reporter's own reproduction, and the reporter's full write-up submitted via huntr for the |
| complete technical analysis. |
|
|
| This is **not** a catchable Java exception β no `try`/`catch(Throwable)` at any level of a calling |
| application can prevent the JVM process from terminating. |
|
|
| ## Scope note |
|
|
| This PoC is provided solely for the purpose of responsible vulnerability disclosure and |
| reproduction by the `mleap` maintainers / huntr triage team. It is not intended for any other use. |
|
|