mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['', 'src/generic-methodologies-and-resources/python/keras-mo
This commit is contained in:
parent
ed73335268
commit
017c1497ca
@ -1,17 +1,17 @@
|
||||
# Keras Model Deserialization RCE and Gadget Hunting
|
||||
# Keras: десеріалізація моделей — RCE та пошук гаджетів
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Ця сторінка підсумовує практичні техніки експлуатації проти конвеєра десеріалізації моделей Keras, пояснює внутрішню структуру формату .keras та поверхню атаки, а також надає набір інструментів для дослідників для знаходження вразливостей файлів моделей (MFVs) та гаджетів після виправлення.
|
||||
Ця сторінка підсумовує практичні техніки експлуатації проти конвеєра десеріалізації моделей Keras, пояснює внутрішню структуру нативного формату .keras та його поверхню атаки, а також надає набір інструментів для дослідників для пошуку Model File Vulnerabilities (MFVs) та post-fix гаджетів.
|
||||
|
||||
## Внутрішня структура формату .keras
|
||||
|
||||
Файл .keras є ZIP-архівом, що містить принаймні:
|
||||
Файл .keras — це ZIP-архів, що містить щонайменше:
|
||||
- metadata.json – загальна інформація (наприклад, версія Keras)
|
||||
- config.json – архітектура моделі (основна поверхня атаки)
|
||||
- model.weights.h5 – ваги в HDF5
|
||||
- model.weights.h5 – ваги у HDF5
|
||||
|
||||
Файл config.json керує рекурсивною десеріалізацією: Keras імпортує модулі, вирішує класи/функції та реконструює шари/об'єкти з словників, контрольованих атакуючим.
|
||||
config.json керує рекурсивною десеріалізацією: Keras імпортує модулі, визначає класи/функції та відтворює шари/об'єкти з довідників, контрольованих зловмисником.
|
||||
|
||||
Приклад фрагмента для об'єкта шару Dense:
|
||||
```json
|
||||
@ -32,21 +32,21 @@
|
||||
}
|
||||
```
|
||||
Десеріалізація виконує:
|
||||
- Імпорт модулів та розв'язання символів з ключів module/class_name
|
||||
- виклик from_config(...) або конструктора з аргументами kwargs, контрольованими атакуючим
|
||||
- Рекурсія в вкладені об'єкти (активації, ініціалізатори, обмеження тощо)
|
||||
- Імпорт модулів та розв'язання символів із ключів module/class_name
|
||||
- Виклик from_config(...) або конструктора з kwargs під контролем атакувальника
|
||||
- Рекурсія у вкладені об'єкти (activations, initializers, constraints, etc.)
|
||||
|
||||
Історично це відкривало три примітиви для атакуючого, що створює config.json:
|
||||
- Контроль над тим, які модулі імпортуються
|
||||
- Контроль над тим, які класи/функції розв'язуються
|
||||
- Контроль над аргументами kwargs, переданими в конструктори/from_config
|
||||
Історично це надавало атакувальнику, який створює config.json, три примітиви:
|
||||
- Контроль того, які модулі імпортуються
|
||||
- Контроль того, які класи/функції розв'язуються
|
||||
- Контроль kwargs, що передаються в конструкторах/from_config
|
||||
|
||||
## CVE-2024-3660 – RCE байт-коду Lambda-слою
|
||||
## CVE-2024-3660 – Lambda-layer bytecode RCE
|
||||
|
||||
Корінна причина:
|
||||
- Lambda.from_config() використовував python_utils.func_load(...), який декодує base64 та викликає marshal.loads() на байтах атакуючого; десеріалізація Python може виконувати код.
|
||||
Причина:
|
||||
- Lambda.from_config() використовувала python_utils.func_load(...), яка base64-decodes і викликає marshal.loads() на байтах атакувальника; Python unmarshalling може виконувати код.
|
||||
|
||||
Ідея експлуатації (спрощене навантаження в config.json):
|
||||
Ідея експлойту (спрощений payload у config.json):
|
||||
```json
|
||||
{
|
||||
"module": "keras.layers",
|
||||
@ -60,19 +60,19 @@
|
||||
}
|
||||
}
|
||||
```
|
||||
Зменшення ризиків:
|
||||
- Keras за замовчуванням використовує safe_mode=True. Серіалізовані Python-функції в Lambda заблоковані, якщо користувач явно не відмовляється від цього, встановивши safe_mode=False.
|
||||
Mitigation:
|
||||
- Keras за замовчуванням застосовує safe_mode=True. Серіалізовані Python-функції в Lambda блокуються, якщо користувач явно не відмовляється від цього, вказавши safe_mode=False.
|
||||
|
||||
Примітки:
|
||||
- Спадкові формати (старі HDF5 збереження) або старі кодові бази можуть не виконувати сучасні перевірки, тому атаки в стилі "пониження" все ще можуть застосовуватися, коли жертви використовують старі завантажувачі.
|
||||
Notes:
|
||||
- Legacy формати (older HDF5 saves) або старі codebases можуть не виконувати сучасних перевірок, тож “downgrade” style атаки можуть спрацювати, якщо жертви використовують старі loaders.
|
||||
|
||||
## CVE-2025-1550 – Довільний імпорт модуля в Keras ≤ 3.8
|
||||
## CVE-2025-1550 – Довільний імпорт модулів у Keras ≤ 3.8
|
||||
|
||||
Корінна причина:
|
||||
- _retrieve_class_or_fn використовував необмежений importlib.import_module() з рядками модуля, контрольованими атакуючими, з config.json.
|
||||
- Вплив: Довільний імпорт будь-якого встановленого модуля (або модуля, закладеного атакуючим на sys.path). Код виконується під час імпорту, після чого відбувається створення об'єкта з аргументами kwargs атакуючого.
|
||||
Root cause:
|
||||
- _retrieve_class_or_fn використовував importlib.import_module() без обмежень з рядками модулів, контрольованими атакуючим, з config.json.
|
||||
- Impact: Довільний імпорт будь-якого встановленого модуля (або модуля, підсіяного атакуючим на sys.path). Код, що виконується під час імпорту, запускається, після чого об'єкт створюється з kwargs, заданими атакуючим.
|
||||
|
||||
Ідея експлуатації:
|
||||
Exploit idea:
|
||||
```json
|
||||
{
|
||||
"module": "maliciouspkg",
|
||||
@ -81,15 +81,15 @@
|
||||
}
|
||||
```
|
||||
Покращення безпеки (Keras ≥ 3.9):
|
||||
- Список дозволених модулів: імпорти обмежені офіційними модулями екосистеми: keras, keras_hub, keras_cv, keras_nlp
|
||||
- Режим безпеки за замовчуванням: safe_mode=True блокує небезпечне завантаження серіалізованих функцій Lambda
|
||||
- Основна перевірка типів: десеріалізовані об'єкти повинні відповідати очікуваним типам
|
||||
- Module allowlist: імпорти обмежені офіційними модулями екосистеми: keras, keras_hub, keras_cv, keras_nlp
|
||||
- Safe mode default: safe_mode=True блокує завантаження небезпечних Lambda серіалізованих функцій
|
||||
- Basic type checking: десеріалізовані об'єкти повинні відповідати очікуваним типам
|
||||
|
||||
## Поверхня гаджетів після виправлення всередині списку дозволених
|
||||
## Поверхня post-fix gadget всередині allowlist
|
||||
|
||||
Навіть з дозволеним списком і режимом безпеки, залишається широка поверхня серед дозволених викликів Keras. Наприклад, keras.utils.get_file може завантажувати довільні URL-адреси в місця, вибрані користувачем.
|
||||
Навіть з allowlisting та safe mode, серед дозволених Keras callables залишається широка поверхня. Наприклад, keras.utils.get_file може завантажувати довільні URL до місць, які вибирає користувач.
|
||||
|
||||
Гаджет через Lambda, який посилається на дозволену функцію (не серіалізований байт-код Python):
|
||||
Gadget через Lambda, що посилається на дозволену функцію (не серіалізований Python bytecode):
|
||||
```json
|
||||
{
|
||||
"module": "keras.layers",
|
||||
@ -106,18 +106,18 @@
|
||||
}
|
||||
```
|
||||
Важливе обмеження:
|
||||
- Lambda.call() додає вхідний тензор як перший позиційний аргумент під час виклику цільового викликаного об'єкта. Вибрані гаджети повинні терпіти додатковий позиційний аргумент (або приймати *args/**kwargs). Це обмежує, які функції є життєздатними.
|
||||
- Lambda.call() додає вхідний тензор як перший позиційний аргумент при виклику цільового callable. Обрані gadgets повинні витримувати додатковий позиційний аргумент (або приймати *args/**kwargs). Це обмежує, які функції придатні.
|
||||
|
||||
Потенційні наслідки дозволених гаджетів:
|
||||
- Довільне завантаження/запис (посадка шляхів, отруєння конфігурацій)
|
||||
- Мережеві зворотні виклики/ефекти, подібні до SSRF, в залежності від середовища
|
||||
- Ланцюгування до виконання коду, якщо записані шляхи пізніше імпортуються/виконуються або додаються до PYTHONPATH, або якщо існує місце для запису з виконанням при запису
|
||||
Potential impacts of allowlisted gadgets:
|
||||
- Довільне завантаження/запис (path planting, config poisoning)
|
||||
- Мережеві callbacks/ефекти на зразок SSRF, залежно від середовища
|
||||
- Ланцюжок до виконання коду, якщо записані шляхи згодом імпортуються/виконуються або додаються до PYTHONPATH, або якщо існує записувана локація, яка виконує код при записі
|
||||
|
||||
## Інструменти дослідника
|
||||
## Набір інструментів дослідника
|
||||
|
||||
1) Систематичне виявлення гаджетів у дозволених модулях
|
||||
1) Систематичне виявлення gadgets у дозволених модулях
|
||||
|
||||
Перелічте кандидатні викликані об'єкти в keras, keras_nlp, keras_cv, keras_hub і пріоритезуйте ті, що мають побічні ефекти з файлами/мережею/процесами/середовищем.
|
||||
Перерахуйте кандидатні callables у keras, keras_nlp, keras_cv, keras_hub і пріоритезуйте ті, що мають побічні ефекти на файли/мережу/процеси/середовище.
|
||||
```python
|
||||
import importlib, inspect, pkgutil
|
||||
|
||||
@ -160,9 +160,9 @@ candidates.append(text)
|
||||
|
||||
print("\n".join(sorted(candidates)[:200]))
|
||||
```
|
||||
2) Пряме тестування десеріалізації (не потрібен архів .keras)
|
||||
2) Пряме тестування десеріалізації (не потрібен .keras архів)
|
||||
|
||||
Введіть підготовлені словники безпосередньо в десеріалізатори Keras, щоб дізнатися прийняті параметри та спостерігати за побічними ефектами.
|
||||
Подавайте створені dicts безпосередньо в Keras deserializers, щоб дізнатися, які params приймаються, і спостерігати побічні ефекти.
|
||||
```python
|
||||
from keras import layers
|
||||
|
||||
@ -178,22 +178,63 @@ cfg = {
|
||||
|
||||
layer = layers.deserialize(cfg, safe_mode=True) # Observe behavior
|
||||
```
|
||||
3) Перехресне тестування версій та формати
|
||||
3) Перехресне тестування версій і форматів
|
||||
|
||||
Keras існує в кількох кодових базах/епохах з різними обмеженнями та форматами:
|
||||
- Вбудований Keras TensorFlow: tensorflow/python/keras (старий, запланований до видалення)
|
||||
- TensorFlow вбудований Keras: tensorflow/python/keras (legacy, заплановано видалити)
|
||||
- tf-keras: підтримується окремо
|
||||
- Multi-backend Keras 3 (офіційний): введено нативний .keras
|
||||
- Multi-backend Keras 3 (official): впроваджено нативний .keras
|
||||
|
||||
Повторюйте тести в різних кодових базах та форматах (.keras проти старого HDF5), щоб виявити регресії або відсутні обмеження.
|
||||
Повторюйте тести у кількох кодових базах та форматах (.keras vs legacy HDF5), щоб виявити регресії або відсутні захисні механізми.
|
||||
|
||||
## Рекомендації щодо захисту
|
||||
## Захисні рекомендації
|
||||
|
||||
- Ставтеся до файлів моделей як до ненадійного вводу. Завантажуйте моделі лише з надійних джерел.
|
||||
- Тримайте Keras в актуальному стані; використовуйте Keras ≥ 3.9, щоб скористатися перевагами дозволів та перевірок типів.
|
||||
- Не встановлюйте safe_mode=False при завантаженні моделей, якщо ви не повністю довіряєте файлу.
|
||||
- Розгляньте можливість виконання десеріалізації в ізольованому середовищі з найменшими привілеями без виходу в мережу та з обмеженим доступом до файлової системи.
|
||||
- Застосовуйте дозволи/підписи для джерел моделей та перевірки цілісності, де це можливо.
|
||||
- Розглядайте файли моделей як недовірений вхід. Завантажуйте моделі лише з довірених джерел.
|
||||
- Тримайте Keras оновленим; використовуйте Keras ≥ 3.9, щоб скористатися allowlisting та перевірками типів.
|
||||
- Не встановлюйте safe_mode=False під час завантаження моделей, якщо ви повністю не довіряєте файлу.
|
||||
- Розгляньте виконання десеріалізації в sandboxed, із найменшими привілеями, без виходу в мережу та з обмеженим доступом до файлової системи.
|
||||
- За можливості застосовуйте allowlists/підписи для джерел моделей та перевірки цілісності.
|
||||
|
||||
## ML pickle import allowlisting for AI/ML models (Fickling)
|
||||
|
||||
Багато форматів моделей AI/ML (PyTorch .pt/.pth/.ckpt, joblib/scikit-learn, старі артефакти TensorFlow тощо) містять вбудовані дані Python pickle. Атакуючі регулярно зловживають pickle GLOBAL imports та конструкторами об’єктів, щоб досягти RCE або підміни моделі під час завантаження. Сканери, що базуються на чорних списках, часто пропускають нові або не вказані небезпечні імпорти.
|
||||
|
||||
Практичним fail-closed захистом є перехоплення десеріалізатора Python pickle та дозволення лише перевіреного набору нешкідливих імпортів, пов'язаних з ML, під час unpickling. Trail of Bits’ Fickling реалізує цю політику й постачає куратований ML import allowlist, побудований на тисячах публічних Hugging Face pickles.
|
||||
|
||||
Модель безпеки для «безпечних» імпортів (інтуїції, виведені з досліджень і практики): імпортовані символи, які використовує pickle, мають одночасно:
|
||||
- Не виконувати код і не спричиняти виконання (немає скомпільованих/джерельних об’єктів коду, викликів оболонки, хуків тощо)
|
||||
- Не отримувати/не встановлювати довільні атрибути або елементи
|
||||
- Не імпортувати і не отримувати посилання на інші Python-об’єкти з pickle VM
|
||||
- Не викликати жодні вторинні десеріалізатори (наприклад, marshal, nested pickle), навіть опосередковано
|
||||
|
||||
Увімкніть захисти Fickling якомога раніше під час старту процесу, щоб будь-які завантаження pickle, що виконуються фреймворками (torch.load, joblib.load тощо), перевірялися:
|
||||
```python
|
||||
import fickling
|
||||
# Sets global hooks on the stdlib pickle module
|
||||
fickling.hook.activate_safe_ml_environment()
|
||||
```
|
||||
Операційні поради:
|
||||
- Ви можете тимчасово disable/re-enable the hooks за потреби:
|
||||
```python
|
||||
fickling.hook.deactivate_safe_ml_environment()
|
||||
# ... load fully trusted files only ...
|
||||
fickling.hook.activate_safe_ml_environment()
|
||||
```
|
||||
- Якщо заблоковано known-good model, розширте allowlist для вашого середовища після перегляду символів:
|
||||
```python
|
||||
fickling.hook.activate_safe_ml_environment(also_allow=[
|
||||
"package.subpackage.safe_symbol",
|
||||
"another.safe.import",
|
||||
])
|
||||
```
|
||||
- Fickling також надає загальні засоби захисту під час виконання, якщо ви віддаєте перевагу більш деталізованому контролю:
|
||||
- fickling.always_check_safety() to enforce checks for all pickle.load()
|
||||
- with fickling.check_safety(): for scoped enforcement
|
||||
- fickling.load(path) / fickling.is_likely_safe(path) for one-off checks
|
||||
|
||||
- Надавайте перевагу форматам моделей, які не використовують pickle, коли це можливо (наприклад, SafeTensors). Якщо потрібно приймати pickle, запускайте завантажувачі з мінімальними привілеями, без виходу в мережу, і застосовуйте allowlist.
|
||||
|
||||
Ця allowlist-first стратегія наочно блокує типові шляхи експлуатації ML pickle, зберігаючи при цьому високу сумісність. У бенчмарку ToB, Fickling позначив 100% синтетичних шкідливих файлів і дозволив ~99% чистих файлів з провідних репозиторіїв Hugging Face.
|
||||
|
||||
## Посилання
|
||||
|
||||
@ -203,5 +244,11 @@ Keras існує в кількох кодових базах/епохах з р
|
||||
- [CVE-2025-1550 – Keras arbitrary module import (≤ 3.8)](https://nvd.nist.gov/vuln/detail/CVE-2025-1550)
|
||||
- [huntr report – arbitrary import #1](https://huntr.com/bounties/135d5dcd-f05f-439f-8d8f-b21fdf171f3e)
|
||||
- [huntr report – arbitrary import #2](https://huntr.com/bounties/6fcca09c-8c98-4bc5-b32c-e883ab3e4ae3)
|
||||
- [Trail of Bits blog – Fickling’s new AI/ML pickle file scanner](https://blog.trailofbits.com/2025/09/16/ficklings-new-ai/ml-pickle-file-scanner/)
|
||||
- [Fickling – Securing AI/ML environments (README)](https://github.com/trailofbits/fickling#securing-aiml-environments)
|
||||
- [Fickling pickle scanning benchmark corpus](https://github.com/trailofbits/fickling/tree/master/pickle_scanning_benchmark)
|
||||
- [Picklescan](https://github.com/mmaitre314/picklescan), [ModelScan](https://github.com/protectai/modelscan), [model-unpickler](https://github.com/goeckslab/model-unpickler)
|
||||
- [Sleepy Pickle attacks background](https://blog.trailofbits.com/2024/06/11/exploiting-ml-models-with-pickle-file-attacks-part-1/)
|
||||
- [SafeTensors project](https://github.com/safetensors/safetensors)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user