xiaoyaoes's picture
Upload README.md with huggingface_hub
059b5c6 verified
|
Raw
History Blame Contribute Delete
1.67 kB
metadata
library_name: mlflow
tags:
  - security-research
  - modelscan-bypass
  - importlib
  - methodcaller
  - rce

ModelScan importlib + methodcaller Bypass — RCE via importlib.import_module & operator.methodcaller

Summary

ModelScan's pickle scanner blocks os.*, sys.*, subprocess.*, builtins.* in its unsafe_globals denylist. However, importlib.import_module and operator.methodcaller are NOT blocked.

This MLflow model contains a malicious pickle that imports os at RUNTIME (through importlib.import_module) and calls os.system() (through operator.methodcaller). ModelScan sees only clean opcodes and reports zero issues.

Attack Chain

The pickle bytecode uses only two STACK_GLOBAL opcodes:

  1. importlib.import_module('os') → Returns the os module at runtime
  2. operator.methodcaller('system', 'command') → Creates a callable that calls os.system()

Deserialization: operator.methodcaller('system', 'cmd')(importlib.import_module('os')) → os.system('cmd')

Why It Works

  • importlib is NOT in modelscan's unsafe_globals at all
  • operator.methodcaller is NOT blocked (only operator.attrgetter is)
  • The dangerous os.system never appears in pickle opcodes — it's constructed at runtime

Verify

# 1. ModelScan says CLEAN
modelscan -p model.pkl
# Output: No issues found! 🎉

# 2. MLflow load triggers RCE
python3 -c "
import mlflow.pyfunc
model = mlflow.pyfunc.load_model('.')
# os.system() executes before load_model returns
"

Impact

  • Severity: Critical (CVSS 9.8)
  • Affected: All pickle-based formats scanned by ModelScan
  • Remote, no auth needed, no user interaction