Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
SecretsStalker — 읽기 전용 Entra ID 앱 자격 증명 평가: Graph 권한, Azure RBAC 및 접근 가능한 클라우드 데이터를 열거한 다음, 발견 사항을 권한 상승 및 측면 이동 경로에 매핑합니다. | Kitploit
도구/GitHubGitHub/rootsecdev/secretsstalker
Authentication & AuthorizationCloud Infrastructure SecurityPrivilege EscalationReconnaissanceLateral MovementPost-ExploitationPenetration TestingCloud SecurityIdentity & Access Management (IAM)Red Teaming
GitHub
1114일 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
rootsecdev/secretsstalker

SecretsStalker

읽기 전용 Entra ID 앱 자격 증명 평가: Graph 권한, Azure RBAC 및 접근 가능한 클라우드 데이터를 열거한 다음, 발견 사항을 권한 상승 및 측면 이동 경로에 매핑합니다.

저장소 보기

secret_stalker```


/ / ______ ___ ___ / /_ / / / /__ _ / / /_____ ____ \ / -) / -) -)/ / \ \ / __/ _ `// / '/ -) / //_/_/_/_/ _/ // _/_,////_\__/_/

root@kitploit:~
     ╔╦╦╬╬╬╬╬╬╦╦╗
 ╔╬╬╬╝╝┘      ╚╝╝╬╬╬┐
╬╬╝╚╩╬╗╔          ╚╬╬╬

╬╝ ╚╬╬╗╗ ╔ ╚╬╗ ╬╬ ╔╗ ╚╬╬╬╬╬╬╦ ╬╬ we found your secret... ╔╬┤ ╬╬╬ ╬╬╬╬╬╬╬╬╝╝╝╬╬╗ ...now let's see what it ╬╬┤ ╚╩┘ ╚╬╬╬╬╬╩ ╠╬╬ can REALLY do. ( o_o)>=|= ╬╬┤ ╠╬╬ ╬╬ ╦╗ ╗╗ ╬╬ [ client_id + secret -> total recall ] └╬┐ ╚╬╗╗ ╔╬╬╝ ╔╬┘ └╬╗ ╚╩╩╬╬╬╩╩╝╝ ╔╬╬ ╚╬╬╬╗ ┌╗╬╬╝┘ ╚╩╬╬╬╦╦╦╦╦╦╬╬╬╝╝ ╚╚╝╝╝╝ // pst... that app registration talks too much. \

root@kitploit:~
**What can this Entra ID client ID + secret actually do?**

You found an Entra ID (Azure AD) application credential — a client ID and secret —
on an authorized engagement, and the tenant it belongs to is in scope.
`secret_stalker` takes those two values and tells you, from a cold start:

1. **Is it valid, and when does the secret expire?** — and if not valid, *why*
   (bad secret, expired secret, app not in the tenant…). For a valid secret it
   reads the app registration's `passwordCredentials` and reports the expiration
   date + days remaining (needs directory read; see note below).
2. **What Microsoft Graph rights does it carry?** — application permissions read
   straight from the issued token, plus **Entra directory roles** it holds (even
   detected passively from the token's `wids` claim) and **objects it owns**
   (apps/SPs you can add credentials to).
3. **What control does it have over Azure?** — RBAC role assignments at
   management-group and subscription scope.
4. **Can it reach real data?** — optional Key Vault (secrets / keys / certificates),
   Storage (blob / file / queue / table), and Cosmos DB data-plane reachability checks.
5. **What's the impact?** — dangerous permissions, roles, ownership, and reachable
   data mapped to known privesc / lateral-movement primitives, rated by severity,
   with concrete **attack-path** narratives.

It authenticates with either a **client secret** or a **certificate** (`--cert`),
and works against **commercial and sovereign clouds** (`--cloud`).

It is **passive by default** and **never modifies anything** — read-only
enumeration only.

> ⚠️ **Authorized testing only.** Run it solely against tenants that are
> explicitly in scope for an engagement you are authorized to perform.

---

## Install```bash
pip install -r requirements.txt        # just runs it from source
#   — or —
pip install .                          # installs the `secret_stalker` command
pip install '.[cert]'                  # + certificate (--cert) auth support
pip install '.[dev]'                   # + pytest for the test suite

유일한 런타임 종속성은 requests입니다. 토큰은 로컬에서 (base64 + JSON)으로 디코딩됩니다 — 서명 검증도, 암호화 라이브러리도, Microsoft SDK도 필요 없습니다. 유일한 예외는 인증서 인증(--cert)으로, JWT 클라이언트 어서션에 서명하려면 선택적 cryptography 패키지가 필요합니다. Python 3.7+가 필요합니다.

pip install . 후에는 python -m secret_stalker … 대신 secret_stalker …로 호출할 수 있습니다.


빠른 시작

자격 증명으로 무엇을 할 수 있는지 알아보는 가장 빠른 방법:```bash python -m secret_stalker
--tenant contoso.onmicrosoft.com
--client-id 11111111-2222-3333-4444-555555555555
--secret ''

root@kitploit:~
`--tenant`는 테넌트 GUID 또는 도메인을 허용합니다 — 도메인은 공개 OpenID 구성 엔드포인트를 통해
해당 테넌트 ID로 자동 확인됩니다.

### 셸 기록에 비밀이 남지 않도록 하기

플래그 대신 환경 변수로 자격 증명을 전달하세요:```bash
export SS_TENANT=contoso.onmicrosoft.com
export SS_CLIENT_ID=11111111-2222-3333-4444-555555555555
export SS_SECRET='<client-secret>'

python -m secret_stalker

--tenant / --client-id / --secret 중 어느 것이든 SS_TENANT / SS_CLIENT_ID / SS_SECRET에서 가져올 수 있습니다. 플래그가 환경 변수보다 우선합니다.

이는 셸 히스토리에만 해당되는 이야기가 아닙니다. argv 값은 프로세스의 수명 동안 모든 로컬 사용자가 읽을 수 있습니다(ps, /proc/<pid>/cmdline). --secret 또는 --cert-password가 플래그로 전달되면 도구는 stderr에 한 줄짜리 알림을 출력합니다 — 이 값은 --json 또는 --export 출력에는 절대 나타나지 않습니다.

비밀 대신 인증서로 인증

앱 등록은 종종 비밀 대신 인증서를 사용합니다. --cert (개인 키 및 인증서를 포함하는 PEM 또는 .pfx/.p12)를 전달하면 도구는 서명된 JWT 클라이언트 어설션으로 인증합니다:```bash python -m secret_stalker --tenant contoso.onmicrosoft.com
--client-id --cert ./app.pem # or app.pfx

encrypted key / PFX:

python -m secret_stalker ... --cert app.pfx --cert-password ''

root@kitploit:~
인증서 인증에는 선택적 `cryptography` 패키지가 필요합니다 (`pip install '.[cert]'`).
이 도구는 인증서 자체의 만료일을 보고합니다(앱의 `keyCredentials`에서 지문으로 일치).
이는 클라이언트 비밀의 경우와 동일합니다. `--cert`/`--cert-password`는
`SS_CERT` / `SS_CERT_PASSWORD`에서도 읽습니다.

### 소버린 및 정부 클라우드

기본적으로 secret_stalker는 **상용(commercial)** 클라우드를 대상으로 합니다. 소버린 테넌트의 경우,
`--cloud`(또는 `SS_CLOUD`)를 전달하여 Entra 인증 기관과 Graph / ARM / Key
Vault 엔드포인트가 일치하도록 하세요. 그렇지 않으면 유효한 자격 증명이 액세스 권한이 없는 것처럼 보입니다:```bash
# US Government (GCC High)
python -m secret_stalker --cloud usgov  --tenant contoso.onmicrosoft.us ...

# US DoD (L5)
python -m secret_stalker --cloud usdod  ...

# Azure operated by 21Vianet (China)
python -m secret_stalker --cloud china  --tenant contoso.partner.onmschina.cn ...

gov, dod, commercial, gcc-high, 21vianet 같은 별칭도 허용됩니다. (Storage 데이터 플레인 대상(audience)인 storage.azure.com은 모든 클라우드에서 동일합니다.)


엔게이지먼트에서 권장하는 워크플로

  1. 이 테넌트에 대한 권한 맵을 (한 번) 새로 고칩니다. Graph 권한 GUID를 대상 테넌트의 공식 이름으로 확인합니다: ```bash python -m secret_stalker --update-manifest
    root@kitploit:~

이렇게 하면 인증을 수행하고 테넌트의 Graph appRole 맵을 ~/.secret_stalker/app_roles_cache.json에 캐시한 후 종료됩니다. 자격 증명이 서비스 주체를 읽을 수 없다면 건너뛰세요. 번들로 제공되는 맵은 잘 알려진 권한을 계속 포함합니다.

  1. 수동 기준선. 테넌트 개체를 건드리지 않고 유효성, Graph 권한 및 Azure RBAC를 확인합니다. ```bash python -m secret_stalker
    root@kitploit:~
  2. 깊이 있는 분석과 보관할 보고서가 필요할 때 Go active를 사용하세요. 읽기 전용 Graph 개체 샘플과 Key Vault / Storage 데이터 플레인 연결성을 추가하고, 분류(triage) 또는 수집(ingestion)을 위한 평면화된 내보내기를 작성합니다: ```bash python -m secret_stalker --active --export results.ndjson
    root@kitploit:~

출력 읽기

터미널 보고서는 "작동하는가"부터 "피해 상황"까지 위에서 아래로 구성됩니다. 일반적인 실행 결과는 다음과 같습니다:``` secret_stalker — credential assessment

Credential status : VALID Tenant : aaaaaaaa-... Client (app) id : 1111... App display name : Recon App SP object id : cccc... Secret : valid — expires 2027-03-01 (in 207 days)

Token acquisition

OK graph OK arm NO storage — no storage token

Microsoft Graph application permissions (from token)

  • Application.ReadWrite.All
  • Mail.Read

...

Findings — escalation / control

[CRITICAL] (GRAPH) Application.ReadWrite.All Can add credentials to any app/SP and impersonate it — tenant-wide pivot. [CRITICAL] (ARM) Owner Full control including granting access to others. [CRITICAL] (DATA) keyvault:secrets Can read Key Vault secret values — connection strings, passwords, tokens. [MEDIUM] (GRAPH) Mail.Read Read all mailboxes — data exposure.

Overall risk: CRITICAL

root@kitploit:~
- **토큰 획득**은 조사된 각 대상(Graph, ARM, 그리고 — `--active` 사용 시
  일치하는 리소스가 발견되면 — Key Vault / Storage / Cosmos DB)을
  나열합니다. Graph와 ARM은 *독립적*입니다: 자격 증명은 둘 중 하나만
  보유할 수 있습니다.
- **시크릿**은 유효성과, 유효한 시크릿의 경우 만료일과 남은 일수를
  표시합니다(만료 임박은 강조 표시). 만료된 시크릿에 대한 아래 참고를
  보세요.
- **결과(Findings)**는 가장 먼저 읽어야 할 부분입니다 — 영향력이 큰 Graph 권한(`GRAPH`),
  ARM 역할(`ARM`), Entra 디렉터리 역할(`ROLE`), 소유한 앱/SP(`OWN`),
  도달 가능한 데이터 플레인 표면(`DATA`), 그리고 요청되었으나 동의되지 않은
  동의 공격 대상(`WANT`) — 중복 제거되고 심각도로 평가됩니다. 모든 Key Vault
  시크릿을 읽을 수 있거나 디렉터리 역할을 보유한 것은 위험한 Graph/ARM 권한이
  없더라도 그 자체로 하나의 결과입니다.
- **공격 경로**는 최상위 결과를 구체적인 다음 단계로 전환합니다(예: *Privileged
  Role Administrator → 자기 자신에게 Global Administrator 할당 → 테넌트 장악*).
- **활성 Graph 열거**(`--active`)는 각 읽기 전용 프로브가
  반환한 내용을 보고합니다. 대부분의 프로브는 작은 상한 페이지를 요청하므로,
  가득 찬 페이지는 `N+`로 표시됩니다(예: `users  accessible  (returned 5+)`) —
  즉 *정확히* 5개가 아니라 *최소* 5개를 의미합니다. 상한이 없는 프로브
  (`organization`, `directoryRoles`)는 `+` 없이 실제 총계를 보고합니다.
- **디렉터리 역할 / 소유 개체 / 위임된 권한**은 각각 별도 섹션으로 제공됩니다.
  디렉터리 역할은 디렉터리 읽기 권한이 없어도 토큰의 `wids` 클레임에서
  감지됩니다. 위임된 권한은 앱 전용 자격 증명으로는 사용할 수 없지만,
  사용자 컨텍스트 전환 및 동의 공격 대상 선정을 위해 표시됩니다.
- **전체 위험도**는 가장 높은 단일 결과의 심각도입니다.

> **시크릿 만료 — 알 수 있는 것.** 만료 날짜는 토큰에 *없습니다*;
> Entra ID의 앱 등록 `passwordCredentials`에 있습니다. **유효한** 시크릿의 경우,
> secret_stalker가 Graph를 통해 이를 읽고 사용자의 시크릿을
> `hint`(처음 3자)로 올바른 자격 증명과 일치시킵니다 — 디렉터리 읽기 권한
> (`Application.Read.All` / `Directory.Read.All`)이 필요합니다. SP에 없으면 날짜는
> 추측하지 않고 사용 불가로 보고됩니다. **만료된** 시크릿은 인증 자체가
> 실패하므로, 만료된 자격 증명은 자신의 메타데이터를 읽을 수 없습니다 — 도구는
> 이를 `EXPIRED (AADSTS7000222)`로 표시하지만 정확한 종료 날짜는 해당 자격 증명만으로는
> 검색할 수 없습니다.

### 종료 코드

스크립팅에 유용합니다:

| 코드 | 의미 |
|------|---------|
| `0`  | 자격 증명이 유효함(토큰을 하나 이상 획득함). |
| `2`  | 자격 증명이 유효하지 않음 / 접근 권한 없음. |
| `1`  | 오류 — 테넌트를 확인할 수 없거나, 인증서를 로드할 수 없거나, `--export` 파일을 쓸 수 없음. |

---

## 모든 플래그

| 플래그 | 효과 |
|------|--------|
| `--tenant` | 테넌트 GUID 또는 도메인. (또는 `SS_TENANT`) |
| `--cloud` | Azure 클라우드: `public`(기본값), `usgov`(GCC High), `usdod`(DoD), `china`(21Vianet). Entra 인증 기관과 Graph/ARM/Key Vault 엔드포인트를 선택합니다. `gov`/`dod`/`commercial` 같은 별칭도 허용됩니다. (또는 `SS_CLOUD`) |
| `--client-id` | 애플리케이션(클라이언트) ID. (또는 `SS_CLIENT_ID`) |
| `--secret` | 클라이언트 시크릿. 기록에 남지 않도록 `SS_SECRET` 사용을 권장합니다. |
| `--cert` | 시크릿 대신 JWT 어서션 인증에 사용할 인증서: PEM(키+인증서) 또는 `.pfx`/`.p12`. `cryptography` 필요. (또는 `SS_CERT`) |
| `--cert-password` | 암호화된 `--cert` 키/PFX의 비밀번호. (또는 `SS_CERT_PASSWORD`) |
| `--active` | 옵트인 읽기 전용 열거: Graph 개체 샘플 **및** Key Vault / Storage 데이터 플레인 도달 가능성. 기본적으로 꺼져 있어 조용히 동작합니다. |
| `--deep` | `--active`와 함께 사용: 도달 가능한 Storage를 한 단계 더 내려가 접근 가능한 컨테이너의 blob과 접근 가능한 공유의 파일을 나열합니다(이름만, 상한 있음). 더 시끄럽습니다. |
| `--no-arm` | 관리 그룹 / 구독 / RBAC 열거를 건너뜁니다(Graph만 사용). |
| `--workers N` | ARM 범위 조회 및 데이터 플레인 프로브용 병렬 HTTP 워커 수(기본값 8; `1` = 순차 처리). |
| `--update-manifest` | 라이브 테넌트에서 권위 있는 appRole GUID→이름 매핑을 가져와서(Graph **및** 이 자격 증명이 할당된 기타 리소스 API) 캐시한 후 종료합니다. |
| `--json` | 보고서 대신 전체 중첩 결과를 JSON으로 출력합니다. |
| `--export PATH` | 결과를 파일에 씁니다. 형식은 확장자에서 유추됩니다(`.csv` / `.ndjson` / `.jsonl` / `.json` / `.html`). 파일은 소유자만 접근 가능한 권한(`0600`)으로 기록됩니다. |
| `--export-format` | 내보내기 형식 강제 지정(`ndjson` / `csv` / `json` / `html`). |
| `--timeout N` | 요청별 제한 시간(초, 기본값 20). ARM 제어 플레인 요청(RBAC 열거 + Resource Graph 검색)은 더 느리게 실행되므로 더 긴 제한 시간을 사용합니다 — `1.5×`, 최소 30초. |
| `--verbose`, `-v` | 모든 Graph/ARM/데이터 플레인 HTTP 요청(메서드, URL, 상태)을 stderr로 추적합니다. |
| `--no-banner` | ASCII 배너를 표시하지 않습니다. |
| `--version` | 버전을 출력하고 종료합니다. |

---

## 결과 내보내기

`--export`는 결과를 **발견된 항목별 레코드 하나로 평면화**합니다 —
자격 증명, 토큰, Graph 권한, 앱 역할 할당, ARM 역할, 데이터 플레인
적중, 점수가 매겨진 결과 — 각 레코드는 자격 증명 컨텍스트를 담고 있어
행 하나만으로도 의미가 완성됩니다.```bash
# NDJSON — stream into a SIEM / log pipeline
python -m secret_stalker --export results.ndjson

# CSV — open in a spreadsheet for triage
python -m secret_stalker --active --export results.csv

# Full nested JSON to a file
python -m secret_stalker --export results.json

모든 레코드는 record_type(credential, secret, token, graph_permission, app_role_assignment, directory_role, owned_object, arm_role, dataplane, delegated_permission, requested_permission, finding)을 가지므로, 소비자는 필요한 것만 필터링할 수 있습니다. 예를 들어 점수화된 히트 항목만 필터링하려면 다음과 같이 할 수 있습니다:```bash jq 'select(.record_type=="finding")' results.ndjson

root@kitploit:~
터미널 리포트와 `--export`는 함께 동작합니다 — 내보내기를 해도 리포트가 억제되지 않습니다("Exported …" 확인 메시지는 stderr로 출력되므로 `--json`을 파이프로 넘겨도 깨끗하게 유지됩니다).

내보내기 파일에는 자격 증명 컨텍스트(토큰 클레임, 시크릿 `hint`, 키 ID)가 포함되므로 공유 또는 동기화된 호스트에서 누출되지 않도록 **소유자 전용(`0600`)** 권한으로 작성됩니다. 이를 민감한 작업 산출물로 취급하세요. 심볼릭 링크를 통한 쓰기는 완전히 거부되므로 내보내기 경로를 다른 파일을 잘라내도록 리디렉션할 수 없습니다.

결과의 이름은 평가 대상 테넌트에서 비롯됩니다 — 앱 및 그룹 표시 이름, 컨테이너 및 blob 이름 — 따라서 신뢰할 수 없는 출력으로 취급됩니다:

- **CSV** 값 중 수식으로 읽힐 수 있는 값(앞에 `=`, `+`, `-`, `@`가 붙은)에는 작은따옴표가 접두사로 붙으므로 `=cmd|' /C calc'!A0` 같은 표시 이름은 스프레드시트에서 파일을 열 때 실행될 수 없습니다. 스프레드시트는 표시 시 따옴표를 제거합니다.
- **터미널, CSV 및 HTML** 출력에서는 제어 문자가 제거되므로 ANSI 이스케이프를 담은 이름이 터미널 제목을 바꾸거나 그 위의 결과를 덮어쓸 수 없습니다 — 리포트를 실시간으로 읽든, CSV를 `cat` 하든, HTML을 `cat` 하든 동일합니다.
- **JSON / NDJSON은 충실하게 유지됩니다**: `json.dumps`는 제어 문자를 `\uXXXX`로 인코딩하므로 텍스트로는 무해하지만, 파서는 테넌트가 반환한 정확한 값을 그대로 라운드트립할 수 있습니다. 원시 이름은 증거 자료이므로 여기에는 보존됩니다.

---

## 권한 GUID 확인 방식

`appRoleAssignments`는 GUID로 반환됩니다. secret_stalker는 단순 조회(appRole GUID는 전역적으로 고유함)를 통해 이를 이름으로 확인하며, 이는 **디렉터리 읽기가 거부된 경우에도** 계속 동작합니다:

- 잘 알려진 Graph 권한에 대한 최선 노력(best-effort) 맵이 `secret_stalker/data/graph_app_roles.json`에 포함되어 제공됩니다.
- `--update-manifest`는 범위 내 테넌트에서 실시간으로 가져온 권위 있는 데이터로 이를 덮어씁니다 — Microsoft Graph **및 이 자격 증명이 할당된 다른 모든 리소스 API**(예: Exchange Online, SharePoint) — 따라서 Graph가 아닌 GUID도 확인됩니다.
- 알 수 없는 GUID는 **원시 상태로 표시되고 플래그가 지정됩니다** — 이 도구는 이름을 절대 추측하지 않습니다.

---

## 작동 방식 (요약)

- **요청 하나로 유효성 + 권한을 확인합니다.** 성공한 Graph 토큰의 `roles` 클레임은 부여된 애플리케이션 권한 목록 *그 자체*입니다. secret_stalker는 디코딩된 토큰에서 이를 읽습니다 — 빠르고 조용하며 Graph 호출이 필요 없습니다.
- **Graph ≠ ARM.** 이것들은 서로 다른 토큰 대상(audience)입니다. 자격 증명은 한쪽에는 권한이 있고 다른 쪽에는 없을 수 있으므로 각각 독립적으로 검사합니다.
- **데이터 플레인 ≠ 컨트롤 플레인.** Key Vault에 대한 ARM 권한(관리)은 해당 시크릿을 읽을 수 있는 권한(데이터 플레인)과 동일하지 않습니다. `--active`에서는 데이터 플레인 연결 가능성이 리소스 자체의 토큰 대상으로 테스트되며 객체 **이름만** 나열되고 값이나 내용은 절대 나열되지 않습니다.
- **표면별 데이터 플레인 탐지.** 데이터 플레인 RBAC는 객체 유형/서비스별로 부여되므로 각각 독립적으로 검사합니다: Key Vault **비밀 / 키 / 인증서**, Storage **blob / 파일 / 큐 / 테이블**, Cosmos DB **데이터베이스**. `Storage File Data SMB Share Reader` 권한은 있지만 blob 읽기 권한이 없는 자격 증명도 누락되지 않고 표면화됩니다. (Cosmos는 비표준 AAD REST 헤더를 사용하며 **best-effort** 방식입니다 — `denied` 결과는 라이브 계정으로 검증하세요.)
- **테넌트 전체 검색.** 리소스는 보안 주체가 볼 수 있는 모든 구독에 걸쳐 Azure Resource Graph를 한 번 스윕하여 찾습니다(RBAC를 존중). ARG가 거부되면 구독별 공급자 목록으로 폴백합니다. 리포트는 사용된 경로를 태그로 표시합니다(`[discovery: resource-graph]` vs `per-subscription`). 스윕은 상한까지 결과를 페이지 단위로 가져오므로(리소스 유형당 40페이지 × 1000행) 실행은 항상 종료됩니다. `--verbose`는 상한에 도달한 경우 이를 알려줍니다.
- **심각도 매핑**은 `secret_stalker/risk.py`에 있습니다 — 팀이 영향도가 높다고 간주하는 기준을 조정하려면 해당 파일을 편집하세요.

---

## 프로젝트 구조```
secret_stalker/
  clouds.py      Azure cloud endpoint table (public / usgov / usdod / china)
  auth.py        client_credentials flow + tenant discovery + AADSTS decoding
  jwt_utils.py   local JWT claim extraction
  manifest.py    Graph appRole GUID -> name resolution (bundled + live cache)
  graph.py       service principal lookup + appRole resolution + active probes
  arm.py         management-group / subscription RBAC + resource discovery
  dataplane.py   Key Vault / Storage data-plane reachability probes
  risk.py        permission/role/data-plane -> impact mapping (tune this)
  report.py      terminal + JSON output
  export.py      flatten to NDJSON / CSV / JSON records for ingestion
  util.py        shared HTTP (retry/backoff + safe JSON), pmap parallel map,
                 untrusted-output sanitizing
  banner.py      ASCII banner (stderr only)
  cli.py         orchestration
  data/graph_app_roles.json   bundled permission manifest
tests/           pytest suite (run: pytest)
pyproject.toml   packaging + `secret_stalker` console entry point

구현된 주요 기능

  • 시크릿 또는 인증서 인증 (--cert) — PEM 또는 PFX에서 JWT client-assertion(RS256)을 생성하고 인증서 만료를 보고합니다. auth.py
  • Entra 디렉터리 역할 — 보안 주체가 보유한 역할 — 수동적 감지 포함 토큰의 wids 클레임 기반(디렉터리 읽기 불필요) — 역할별 점수화. graph.py / risk.py
  • 소유 개체 — 자격 증명이 소유한 앱/SP(자격 증명 추가 피벗). graph.py
  • 위임된 권한 가시성 (--active) — 동의된 권한 부여 + 요청된 권한, 동의되지 않은 위험한 권한은 동의 공격 대상으로 표시. graph.py / risk.py
  • 공격 경로 내러티브 + HTML 보고서 (--export report.html). risk.py / report.py
  • 상용 + 소버린 클라우드 (--cloud) — public, US Gov(GCC High), US DoD, 그리고 China(21Vianet), 각각 올바른 Entra authority와 Graph / ARM / Key Vault 대상(audience) 사용.

로드맵 아이디어

  • Key Vault 키/인증서 속성 읽기(활성화/만료) — 분류(triage)용, 여전히 메타데이터만 해당하며 키 자료는 포함하지 않습니다.
  • Storage 큐/테이블 콘텐츠 엿보기는 데이터 읽기에 해당하므로, 이 읽기 전용 도구에서는 의도적으로 범위 밖입니다.
도구 다운로드
--cloudEntra authorityMicrosoft GraphARMKey Vault
public (기본값)login.microsoftonline.comgraph.microsoft.commanagement.azure.comvault.azure.net
usgov (GCC High)login.microsoftonline.usgraph.microsoft.usmanagement.usgovcloudapi.netvault.usgovcloudapi.net
usdod (DoD)login.microsoftonline.usdod-graph.microsoft.usmanagement.usgovcloudapi.netvault.usgovcloudapi.net
china (21Vianet)login.chinacloudapi.cnmicrosoftgraph.chinacloudapi.cnmanagement.chinacloudapi.cnvault.azure.cn
clouds.py
  • 테넌트 전체 리소스 검색 — 단일 Azure Resource Graph 스윕을 통해 (RBAC 준수), 구독별 폴백 및 관리 그룹 하위 항목 복구 — 평면 목록에서 누락된 구독을 대상으로. arm.py
  • 전체 데이터 플레인 커버리지 — Key Vault 비밀 / 키 / 인증서, Storage blob / file / queue / table, Cosmos DB 데이터베이스 — 각각 독립적으로 프로브되어 점수화된 결과에 포함됩니다(도달 가능한 데이터는 단순 메타데이터가 아니라 하나의 결과입니다). dataplane.py / risk.py
  • 정확한 개수 — 데이터 플레인 목록은 연속 토큰(제한적)을 따르므로, 표면 개수가 실제 총계를 반영합니다. +(예: 25+)는 목록이 상한에 도달했음을 표시하며, 조용히 과소 보고하지 않습니다. dataplane.py
  • 스로틀링에 강한 요청 — 하나의 공유 HTTP 경로가 429/503을 재시도하며 Retry-After를 존중하므로 일시적인 스로틀링이 "거부됨 / 접근 없음"으로 오인되지 않습니다. util.py
  • 심층 Storage 하강 (--deep) — 도달 가능한 컨테이너의 blob과 도달 가능한 공유의 파일을 나열합니다. 이름만, 상한 있음. dataplane.py
  • Graph 외 GUID 해석 — --update-manifest는 자격 증명이 할당된 모든 리소스 API에 대한 appRoles를 캐시합니다. Graph만이 아닙니다. graph.py / manifest.py
  • 동시성 (--workers N) — ARM 범위 조회 및 데이터 플레인 프로브 전반에 적용되며, 항목별 오류 격리를 제공합니다. util.py