Skip to content

Commit 9ebb2d9

Browse files
committed
f
1 parent d847f32 commit 9ebb2d9

File tree

2 files changed

+91
-18
lines changed
  • src/pentesting-cloud/azure-security

2 files changed

+91
-18
lines changed

src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ az ad sp show --id 00000003-0000-0000-c000-000000000000 --query "appRoles[?id=='
139139
```
140140

141141
<details>
142-
<summary>Find all applications with API permissions to non-Microsoft APIs (az cli)</summary>
142+
<summary>Find all applications API permissions and mark Microsoft-owned APIs</summary>
143143

144144
```bash
145145
#!/usr/bin/env bash
@@ -162,6 +162,32 @@ is_microsoft_owner() {
162162
return 1
163163
}
164164

165+
get_permission_value() {
166+
local resource_app_id="$1"
167+
local perm_type="$2"
168+
local perm_id="$3"
169+
local key value
170+
key="${resource_app_id}|${perm_type}|${perm_id}"
171+
172+
value="$(awk -F '\t' -v k="$key" '$1==k {print $2; exit}' "$tmp_perm_cache")"
173+
if [ -n "$value" ]; then
174+
printf '%s\n' "$value"
175+
return 0
176+
fi
177+
178+
if [ "$perm_type" = "Scope" ]; then
179+
value="$(az ad sp show --id "$resource_app_id" --query "oauth2PermissionScopes[?id=='$perm_id'].value | [0]" -o tsv 2>/dev/null || true)"
180+
elif [ "$perm_type" = "Role" ]; then
181+
value="$(az ad sp show --id "$resource_app_id" --query "appRoles[?id=='$perm_id'].value | [0]" -o tsv 2>/dev/null || true)"
182+
else
183+
value=""
184+
fi
185+
186+
[ -n "$value" ] || value="UNKNOWN"
187+
printf '%s\t%s\n' "$key" "$value" >> "$tmp_perm_cache"
188+
printf '%s\n' "$value"
189+
}
190+
165191
command -v az >/dev/null 2>&1 || { echo "az CLI not found" >&2; exit 1; }
166192
command -v jq >/dev/null 2>&1 || { echo "jq not found" >&2; exit 1; }
167193
az account show >/dev/null
@@ -170,7 +196,8 @@ apps_json="$(az ad app list --all --query '[?length(requiredResourceAccess) > `0
170196

171197
tmp_map="$(mktemp)"
172198
tmp_ids="$(mktemp)"
173-
trap 'rm -f "$tmp_map" "$tmp_ids"' EXIT
199+
tmp_perm_cache="$(mktemp)"
200+
trap 'rm -f "$tmp_map" "$tmp_ids" "$tmp_perm_cache"' EXIT
174201

175202
# Build unique resourceAppId values used by applications.
176203
jq -r '.[][2][]?.resourceAppId' <<<"$apps_json" | sort -u > "$tmp_ids"
@@ -184,9 +211,9 @@ while IFS= read -r rid; do
184211
printf '%s\t%s\t%s\n' "$rid" "$owner" "$name" >> "$tmp_map"
185212
done < "$tmp_ids"
186213

187-
echo -e "appDisplayName\tappId\tresourceApiDisplayName\tresourceAppId\tresourceOwnerOrgId\tpermissionType\tpermissionId"
214+
echo -e "appDisplayName\tappId\tresourceApiDisplayName\tresourceAppId\tisMicrosoft\tpermissions"
188215

189-
# Print only app permissions where the target API is NOT Microsoft-owned.
216+
# Print all app API permissions and mark if the target API is Microsoft-owned.
190217
while IFS= read -r row; do
191218
app_name="$(jq -r '.[0]' <<<"$row")"
192219
app_id="$(jq -r '.[1]' <<<"$row")"
@@ -201,14 +228,25 @@ while IFS= read -r row; do
201228
[ -n "$resource_name" ] || resource_name="UNKNOWN"
202229

203230
if is_microsoft_owner "$owner_org"; then
204-
continue
231+
is_ms="true"
232+
else
233+
is_ms="false"
205234
fi
206235

236+
permissions_csv=""
207237
while IFS= read -r access; do
208238
perm_type="$(jq -r '.type' <<<"$access")"
209239
perm_id="$(jq -r '.id' <<<"$access")"
210-
echo -e "${app_name}\t${app_id}\t${resource_name}\t${resource_app_id}\t${owner_org}\t${perm_type}\t${perm_id}"
240+
perm_value="$(get_permission_value "$resource_app_id" "$perm_type" "$perm_id")"
241+
perm_label="${perm_type}:${perm_value}"
242+
if [ -z "$permissions_csv" ]; then
243+
permissions_csv="$perm_label"
244+
else
245+
permissions_csv="${permissions_csv},${perm_label}"
246+
fi
211247
done < <(jq -c '.resourceAccess[]' <<<"$rra")
248+
249+
echo -e "${app_name}\t${app_id}\t${resource_name}\t${resource_app_id}\t${is_ms}\t${permissions_csv}"
212250
done < <(jq -c '.[2][]' <<<"$row")
213251
done < <(jq -c '.[]' <<<"$apps_json")
214252
```
@@ -472,5 +510,3 @@ az rest --method GET \
472510
- `microsoft.directory/applications.myOrganization/permissions/update`
473511

474512
{{#include ../../../../banners/hacktricks-training.md}}
475-
476-

src/pentesting-cloud/azure-security/az-services/az-azuread.md

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -761,10 +761,11 @@ For more information about Applications check:
761761
../az-basic-information/
762762
{{#endref}}
763763
764-
When an App is generated 2 types of permissions are given:
764+
When an App is generated 3 types of permissions are given:
765765
766-
- **Permissions** given to the **Service Principal**
766+
- **Permissions** given to the **Service Principal** (via roles).
767767
- **Permissions** the **app** can have and use on **behalf of the user**.
768+
- **API Permissions** that gives the app permissions over EntraID withuot requiring other roles granting these permissions.
768769
769770
{{#tabs }}
770771
{{#tab name="az cli" }}
@@ -820,7 +821,7 @@ az ad sp show --id 00000003-0000-0000-c000-000000000000 --query "appRoles[?id=='
820821
```
821822
822823
<details>
823-
<summary>Find all applications with API permissions to non-Microsoft APIs (az cli)</summary>
824+
<summary>Find all applications API permissions and mark Microsoft-owned APIs (az cli)</summary>
824825
825826
```bash
826827
#!/usr/bin/env bash
@@ -843,6 +844,32 @@ is_microsoft_owner() {
843844
return 1
844845
}
845846
847+
get_permission_value() {
848+
local resource_app_id="$1"
849+
local perm_type="$2"
850+
local perm_id="$3"
851+
local key value
852+
key="${resource_app_id}|${perm_type}|${perm_id}"
853+
854+
value="$(awk -F '\t' -v k="$key" '$1==k {print $2; exit}' "$tmp_perm_cache")"
855+
if [ -n "$value" ]; then
856+
printf '%s\n' "$value"
857+
return 0
858+
fi
859+
860+
if [ "$perm_type" = "Scope" ]; then
861+
value="$(az ad sp show --id "$resource_app_id" --query "oauth2PermissionScopes[?id=='$perm_id'].value | [0]" -o tsv 2>/dev/null || true)"
862+
elif [ "$perm_type" = "Role" ]; then
863+
value="$(az ad sp show --id "$resource_app_id" --query "appRoles[?id=='$perm_id'].value | [0]" -o tsv 2>/dev/null || true)"
864+
else
865+
value=""
866+
fi
867+
868+
[ -n "$value" ] || value="UNKNOWN"
869+
printf '%s\t%s\n' "$key" "$value" >> "$tmp_perm_cache"
870+
printf '%s\n' "$value"
871+
}
872+
846873
command -v az >/dev/null 2>&1 || { echo "az CLI not found" >&2; exit 1; }
847874
command -v jq >/dev/null 2>&1 || { echo "jq not found" >&2; exit 1; }
848875
az account show >/dev/null
@@ -851,7 +878,8 @@ apps_json="$(az ad app list --all --query '[?length(requiredResourceAccess) > `0
851878
852879
tmp_map="$(mktemp)"
853880
tmp_ids="$(mktemp)"
854-
trap 'rm -f "$tmp_map" "$tmp_ids"' EXIT
881+
tmp_perm_cache="$(mktemp)"
882+
trap 'rm -f "$tmp_map" "$tmp_ids" "$tmp_perm_cache"' EXIT
855883
856884
# Build unique resourceAppId values used by applications.
857885
jq -r '.[][2][]?.resourceAppId' <<<"$apps_json" | sort -u > "$tmp_ids"
@@ -865,9 +893,9 @@ while IFS= read -r rid; do
865893
printf '%s\t%s\t%s\n' "$rid" "$owner" "$name" >> "$tmp_map"
866894
done < "$tmp_ids"
867895
868-
echo -e "appDisplayName\tappId\tresourceApiDisplayName\tresourceAppId\tresourceOwnerOrgId\tpermissionType\tpermissionId"
896+
echo -e "appDisplayName\tappId\tresourceApiDisplayName\tresourceAppId\tisMicrosoft\tpermissions"
869897
870-
# Print only app permissions where the target API is NOT Microsoft-owned.
898+
# Print all app API permissions and mark if the target API is Microsoft-owned.
871899
while IFS= read -r row; do
872900
app_name="$(jq -r '.[0]' <<<"$row")"
873901
app_id="$(jq -r '.[1]' <<<"$row")"
@@ -882,14 +910,25 @@ while IFS= read -r row; do
882910
[ -n "$resource_name" ] || resource_name="UNKNOWN"
883911
884912
if is_microsoft_owner "$owner_org"; then
885-
continue
913+
is_ms="true"
914+
else
915+
is_ms="false"
886916
fi
887917
918+
permissions_csv=""
888919
while IFS= read -r access; do
889920
perm_type="$(jq -r '.type' <<<"$access")"
890921
perm_id="$(jq -r '.id' <<<"$access")"
891-
echo -e "${app_name}\t${app_id}\t${resource_name}\t${resource_app_id}\t${owner_org}\t${perm_type}\t${perm_id}"
922+
perm_value="$(get_permission_value "$resource_app_id" "$perm_type" "$perm_id")"
923+
perm_label="${perm_type}:${perm_value}"
924+
if [ -z "$permissions_csv" ]; then
925+
permissions_csv="$perm_label"
926+
else
927+
permissions_csv="${permissions_csv},${perm_label}"
928+
fi
892929
done < <(jq -c '.resourceAccess[]' <<<"$rra")
930+
931+
echo -e "${app_name}\t${app_id}\t${resource_name}\t${resource_app_id}\t${is_ms}\t${permissions_csv}"
893932
done < <(jq -c '.[2][]' <<<"$row")
894933
done < <(jq -c '.[]' <<<"$apps_json")
895934
```
@@ -1383,5 +1422,3 @@ The default mode is **Audit**:
13831422
- [EntraTokenAid](https://github.com/zh54321/EntraTokenAid)
13841423
13851424
{{#include ../../../banners/hacktricks-training.md}}
1386-
1387-

0 commit comments

Comments
 (0)