Cluckβwait, what? I swear Iβm hearing voices, but all the elves are goneβ¦
Anyway, the Neighborhood HOA runs their IT infrastructure on Azure. Their admins use RBAC for access control.
Your task: Audit the RBAC configuration to ensure security best practices are followed. They claim elevated access uses PIM, but confirm there are no permanently assigned Owner roles.
This task is guided by the system. Therefore, I will only show the commands and most important console outputs here:
π Welcome to the Owner Challenge! π
You're connected to a read-only Azure CLI session in "The Neighborhood" tenant.
Your mission: Investigate the permissions and identify WHO has access they shouldn't.
Connecting you now... βοΈ
Let's learn some more Azure CLI, the --query parameter with JMESPath syntax!
$ az account list --query "[].name"
Here, [] loops through each item, .name grabs the name field
neighbor@b13c1911d74e:~$ az account list --query "[].name"
[
"theneighborhood-sub",
...
You can do some more advanced queries using conditional filtering with custom output.
$ az account list --query "[?state=='Enabled'].{Name:name, ID:id}"
Cool! π [?condition] filters what you want, {custom:fields} makes clean output β¨
neighbor@b13c1911d74e:~$ az account list --query "[?state=='Enabled'].{Name:name, ID:id}"
[
{
"ID": "2b0942f3-9bca-484b-a508-abdae2db5e64",
"Name": "theneighborhood-sub"
...
Let's take a look at the Owner's of the first listed subscription π. Pass in the first subscription id.
Try: az role assignment list --scope "/subscriptions/{ID of first Subscription}" --query [?roleDefinition=='Owner']
neighbor@b13c1911d74e:~$ az role assignment list --scope "/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64" --query [?roleDefinition=='Owner']
[
{
"condition": "null",
"conditionVersion": "null",
"createdBy": "85b095fa-a9b4-4bdc-a3af-c9f95ebb8dd6",
...
Ok π€ β there is a group present for the Owners permission; however, we've been assured this is a π PIM enabled group.
Currently, no PIM activations are present. π¨
Let's run the previous command against the other subscriptions to see what we come up with.
neighbor@b13c1911d74e:~$ az role assignment list --scope "/subscriptions/065cc24a-077e-40b9-b666-2f4dd9f3a617" --query [?roleDefinition=='Owner']
...
"name": "6b452f58-6872-4064-ae9b-78742e8d987e",
"principalId": "6b982f2f-78a0-44a8-b915-79240b2b4796",
"principalName": "IT Admins",
"principalType": "Group",
...
Looks like you are on to something here! π΅οΈ We were assured that only the π PIM group was present for each subscription.
π Let's figure out the membership of that group.
Hint: use the az ad member list command. Pass the group id instead of the name.
Remember: | less lets you scroll through long output
neighbor@b13c1911d74e:~$ az ad member list --group 6b982f2f-78a0-44a8-b915-79240b2b4796 | less
...
"groupTypes": [],
"id": "631ebd3f-39f9-4492-a780-aef2aec8c94e",
"isAssignableToRole": null,
...
Well π€, that's annoying. Looks like we have a nested group!
Let's run the command one more time against this group.
neighbor@b13c1911d74e:~$ az ad member list --group 631ebd3f-39f9-4492-a780-aef2aec8c94e | less
...
"displayName": "Firewall Frank",
"givenName": "Frank",
"id": "b8613dd2-5e33-4d77-91fb-b4f2338c19c9",
"jobTitle": "HOA IT Administrator",
"mail": "frank.firewall@theneighborhood.invalid",
elevated access instead of permanent assignments. Permanent Owner roles create persistent
attack paths and violate least-privilege principles.
Challenge Complete! To finish, type: finish