Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion REFERENCES.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ Manual workflow: edit `data/scf-check-mapping.json` → `python scripts/Build-Re
| **Stitch-M365** | Private | Submodule (`Engine/lib/CheckID/`) | Manual submodule update |
| **Darn** | [Galvnyz/Darn](https://github.com/Galvnyz/Darn) | Planned | — |

### Canonical Reference Data

Beyond `registry.json` and `frameworks/*.json`, CheckID is the single source of truth for cross-consumer reference data. Consumers fetch these from the tagged release instead of maintaining per-repo copies (which drift):

| File | Purpose | Consumed by |
|------|---------|-------------|
| `data/role-tiers.json` | Entra ID directory-role tier classification (Enterprise Access Model) | PIM / privileged-access detection (`ENTRA-PIM-*`) |
| `data/tier0-permissions.json` | Graph application permissions with documented attack paths to Global Admin | app / service-principal privilege detection |

Each canonical data file has a sibling `*.schema.json` and Pester coverage under `tests/`.

### CI Cascade Flow

```
Expand All @@ -57,7 +68,7 @@ CheckID notify-downstream.yml → repository_dispatch to:

**CI cache sync** (recommended for PowerShell tools like M365-Assess):
- Add `sync-checkid.yml` workflow that receives `checkid-released` dispatch
- Fetch `data/registry.json` and `data/frameworks/*.json` from the tagged version
- Fetch `data/registry.json`, `data/frameworks/*.json`, and the canonical reference data files (see [Canonical Reference Data](#canonical-reference-data)) from the tagged version
- Store in a local `controls/` directory

**Git submodule** (recommended for .NET apps like M365-Remediate):
Expand Down
39 changes: 39 additions & 0 deletions data/role-tiers.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"$schema": "./role-tiers.schema.json",
"description": "Entra ID role tier classification based on Microsoft Enterprise Access Model. Tier-0 roles can compromise the entire directory. Tier-1 roles have significant blast radius over specific services. Tier-2 is everything else with an active assignment.",
"version": "1.0.0",
"tiers": {
"0": {
"label": "Control Plane",
"description": "Roles that can compromise the entire Entra ID directory or escalate to full control",
"roles": {
"62e90394-69f5-4237-9190-012177145e10": "Global Administrator",
"e8611ab8-c189-46e8-94e1-60213ab1f814": "Privileged Role Administrator",
"7be44c8a-adaf-4e2a-84d6-ab2649e08a13": "Privileged Authentication Administrator",
"d29b2b05-8046-44ba-8758-1e26182fcf32": "Directory Synchronization Accounts"
}
},
"1": {
"label": "Management Plane",
"description": "Roles with significant blast radius over specific M365 services or user populations",
"roles": {
"29232cdf-9323-42fd-ade2-1d097af3e4de": "Exchange Administrator",
"f28a1f50-f6e7-4571-818b-6a12f2af6b6c": "SharePoint Administrator",
"194ae4cb-b126-40b2-bd5b-6091b380977d": "Security Administrator",
"3a2c62db-5318-420d-8d74-23affee5d9d5": "Intune Administrator",
"fe930be7-5e62-47db-91af-98c3a49a38b1": "User Administrator",
"9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3": "Application Administrator",
"158c047a-c907-4556-b7ef-446551a6b5f7": "Cloud Application Administrator",
"c4e39bd9-1100-46d3-8c65-fb160da0071f": "Authentication Administrator",
"b1be1c3e-b65d-4f19-8427-f6fa0d97feb9": "Conditional Access Administrator",
"fdd7a751-b60b-444a-984c-02652fe8fa1c": "Groups Administrator",
"966707d0-3269-4727-9be2-8c3a10f19b9d": "Password Administrator",
"8835291a-918c-4fd7-a9ce-faa49f0cf7d9": "Teams Administrator",
"11648597-926c-4cf3-9c36-bcebb0ba8dcc": "Power Platform Administrator",
"729827e3-9c14-49f7-bb1b-9608f156bbb8": "Helpdesk Administrator",
"b0f54661-2d74-4c50-afa3-1ec803f12efe": "Billing Administrator",
"112f9a7f-7249-4951-bd88-c42b60cebe72": "Fabric Administrator"
}
}
}
}
45 changes: 45 additions & 0 deletions data/role-tiers.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/Galvnyz/CheckID/data/role-tiers.schema.json",
"title": "Entra ID Role Tiers",
"description": "Schema for role-tiers.json - canonical Entra ID directory-role tier classification (Microsoft Enterprise Access Model). Tier 0 = control plane (can compromise the directory); Tier 1 = management plane (significant blast radius). Referenced by PIM / privileged-access detection logic.",
"type": "object",
"required": ["$schema", "description", "version", "tiers"],
"additionalProperties": false,
"properties": {
"$schema": { "type": "string" },
"description": { "type": "string", "minLength": 1 },
"version": {
"type": "string",
"pattern": "^\\d+\\.\\d+\\.\\d+$",
"description": "Semantic version of the tier classification."
},
"tiers": {
"type": "object",
"minProperties": 1,
"propertyNames": { "pattern": "^[0-9]+$" },
"additionalProperties": { "$ref": "#/$defs/tier" },
"description": "Tier number (string key) to tier definition."
}
},
"$defs": {
"tier": {
"type": "object",
"required": ["label", "description", "roles"],
"additionalProperties": false,
"properties": {
"label": { "type": "string", "minLength": 1 },
"description": { "type": "string", "minLength": 1 },
"roles": {
"type": "object",
"minProperties": 1,
"propertyNames": {
"pattern": "^[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}$"
},
"additionalProperties": { "type": "string", "minLength": 1 },
"description": "Entra role template GUID to role display name."
}
}
}
}
}
222 changes: 222 additions & 0 deletions data/tier0-permissions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
{
"$schema": "./tier0-permissions.schema.json",
"description": "Microsoft Graph application permissions classified as Tier 0 -- each has a documented attack path to Global Administrator. Source: github.com/emiliensocchi/azure-tiering (MIT license).",
"version": "2025-05",
"permissions": [
{
"permission": "AdministrativeUnit.ReadWrite.All",
"category": "role-assignment",
"attackPath": "When combined with password reset access, can remove a Global Admin from a Restricted Management Administrative Unit (RMAU) and take it over."
},
{
"permission": "Application.ReadUpdate.All",
"category": "credential-injection",
"attackPath": "Can impersonate any SP with more privileged application permissions granted for MS Graph, and escalate to Global Admin."
},
{
"permission": "Application.ReadWrite.All",
"category": "credential-injection",
"attackPath": "Can impersonate any SP with more privileged application permissions granted for MS Graph, and escalate to Global Admin."
},
{
"permission": "Application.ReadWrite.OwnedBy",
"category": "credential-injection",
"attackPath": "Can impersonate owned SPs with more privileged permissions to escalate to Global Admin."
},
{
"permission": "AppRoleAssignment.ReadWrite.All",
"category": "self-escalation",
"attackPath": "Can assign RoleManagement.ReadWrite.Directory to itself without admin consent, then assign Global Admin."
},
{
"permission": "DelegatedAdminRelationship.ReadWrite.All",
"category": "cross-tenant",
"attackPath": "In CSP/MSP tenants, can add users to groups approved in GDAP relationships and assume Global Admin in customer tenants."
},
{
"permission": "DeviceManagementConfiguration.ReadWrite.All",
"category": "intune-exploitation",
"attackPath": "Can run arbitrary commands on an Intune-managed endpoint of a Global Administrator and steal their tokens."
},
{
"permission": "DeviceManagementRBAC.ReadWrite.All",
"category": "intune-exploitation",
"attackPath": "Can assign Intune roles enabling arbitrary command execution on Global Admin devices."
},
{
"permission": "DeviceManagementScripts.ReadWrite.All",
"category": "intune-exploitation",
"attackPath": "Can deploy scripts to Intune-managed devices of Global Administrators and steal tokens."
},
{
"permission": "Directory.ReadWrite.All",
"category": "group-manipulation",
"attackPath": "Can join non-role-assignable groups with privileged Azure permissions, and escalate via Azure resources."
},
{
"permission": "Domain.ReadWrite.All",
"category": "federation-abuse",
"attackPath": "Can add a federated domain and authenticate as any Global Admin without password or MFA."
},
{
"permission": "EntitlementManagement.ReadWrite.All",
"category": "policy-manipulation",
"attackPath": "Can modify access package policies to grant Global Admin without approval."
},
{
"permission": "Group-OnPremisesSyncBehavior.ReadWrite.All",
"category": "hybrid-abuse",
"attackPath": "Combined with on-premises DA, can convert a cloud group providing GA access to a synced group and add controlled accounts."
},
{
"permission": "Group.ReadWrite.All",
"category": "group-manipulation",
"attackPath": "Can join non-role-assignable groups with privileged Azure permissions, and escalate via Azure resources."
},
{
"permission": "GroupMember.ReadWrite.All",
"category": "group-manipulation",
"attackPath": "Can join non-role-assignable groups with privileged Azure permissions, and escalate via Azure resources."
},
{
"permission": "Organization.ReadWrite.All",
"category": "certificate-abuse",
"attackPath": "If Certificate Based Authentication (CBA) is enabled, can upload a trusted root certificate and impersonate a Global Admin."
},
{
"permission": "Policy.ReadWrite.AuthenticationMethod",
"category": "auth-method-takeover",
"attackPath": "Combined with UserAuthenticationMethod.ReadWrite.All, can enable TAP authentication method and take over any account."
},
{
"permission": "Policy.ReadWrite.ConditionalAccess",
"category": "tenant-availability",
"attackPath": "Can create a CA policy blocking all users for all apps, rendering the tenant unavailable (ransom vector)."
},
{
"permission": "Policy.ReadWrite.PermissionGrant",
"category": "self-escalation",
"attackPath": "Can create a permission grant policy for RoleManagement.ReadWrite.Directory and self-escalate to Global Admin."
},
{
"permission": "PrivilegedAccess.ReadWrite.AzureAD",
"category": "legacy",
"attackPath": "Legacy PIM permission -- kept for safety until completely removed by Microsoft."
},
{
"permission": "PrivilegedAccess.ReadWrite.AzureADGroup",
"category": "role-assignment",
"attackPath": "Can add users as owner or member of a group with an active Global Admin assignment."
},
{
"permission": "PrivilegedAccess.ReadWrite.AzureResources",
"category": "legacy",
"attackPath": "Legacy PIM permission -- kept for safety until completely removed by Microsoft."
},
{
"permission": "PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup",
"category": "role-assignment",
"attackPath": "Can add users as owner or member of a group with an active Global Admin assignment."
},
{
"permission": "PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup",
"category": "role-assignment",
"attackPath": "Can make a user eligible for a group with active GA assignment, then activate to escalate."
},
{
"permission": "RoleAssignmentSchedule.ReadWrite.Directory",
"category": "role-assignment",
"attackPath": "Can assign Global Admin to any user by creating an active PIM role assignment."
},
{
"permission": "RoleEligibilitySchedule.ReadWrite.Directory",
"category": "role-assignment",
"attackPath": "Can make any user eligible for Global Admin and activate it to escalate."
},
{
"permission": "RoleManagement.ReadWrite.Directory",
"category": "role-assignment",
"attackPath": "Can directly assign the Global Admin role to any principal."
},
{
"permission": "RoleManagementPolicy.ReadWrite.AzureADGroup",
"category": "policy-manipulation",
"attackPath": "Can remove MFA/approval constraints from PIM group assignments, enabling silent escalation."
},
{
"permission": "RoleManagementPolicy.ReadWrite.Directory",
"category": "policy-manipulation",
"attackPath": "Can remove MFA/approval constraints from Entra role assignments, enabling silent escalation."
},
{
"permission": "SecurityIdentitiesActions.ReadWrite.All",
"category": "tenant-availability",
"attackPath": "Can mark all accounts as compromised, disabling sign-in via CA policies (ransom vector)."
},
{
"permission": "SignInIdentifier.ReadWrite.All",
"category": "group-manipulation",
"attackPath": "Can edit UPN to join dynamic groups with privileged Azure permissions and escalate."
},
{
"permission": "Synchronization.ReadWrite.All",
"category": "hybrid-abuse",
"attackPath": "Untested -- potential to modify hybrid sync configuration. Kept for safety."
},
{
"permission": "User.DeleteRestore.All",
"category": "tenant-availability",
"attackPath": "Can delete all users in the tenant, rendering it unavailable (ransom vector)."
},
{
"permission": "User.EnableDisableAccount.All",
"category": "tenant-availability",
"attackPath": "Can disable all user accounts in the tenant, rendering it unavailable (ransom vector)."
},
{
"permission": "User.ReadWrite.All",
"category": "group-manipulation",
"attackPath": "Can edit user properties to join dynamic groups with privileged Azure permissions and escalate."
},
{
"permission": "User-PasswordProfile.ReadWrite.All",
"category": "credential-injection",
"attackPath": "Can reset passwords of non-admin users and escalate via group memberships or Azure resources."
},
{
"permission": "UserAuthenticationMethod.ReadWrite.All",
"category": "auth-method-takeover",
"attackPath": "Can generate a TAP for any user, including break-glass accounts, and authenticate as them."
},
{
"permission": "UserAuthMethod-HardwareOATH.ReadWrite.All",
"category": "auth-method-takeover",
"attackPath": "Can add a hardware OATH token to any user and authenticate with the TOTP."
},
{
"permission": "UserAuthMethod-Phone.ReadWrite.All",
"category": "auth-method-takeover",
"attackPath": "Can update any user's phone, enable SMS sign-in, and authenticate via SMS OTP."
},
{
"permission": "UserAuthMethod-QR.ReadWrite.All",
"category": "auth-method-takeover",
"attackPath": "Can generate a QR code + PIN for any user and authenticate as them."
},
{
"permission": "UserAuthMethod-TAP.ReadWrite.All",
"category": "auth-method-takeover",
"attackPath": "Can generate a Temporary Access Pass for any user and authenticate as them."
}
],
"tier1DataAccess": [
"Mail.ReadWrite",
"Mail.Send",
"Files.ReadWrite.All",
"Sites.FullControl.All",
"Sites.ReadWrite.All",
"MailboxSettings.ReadWrite",
"Calendars.ReadWrite",
"Contacts.ReadWrite"
]
}
54 changes: 54 additions & 0 deletions data/tier0-permissions.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/Galvnyz/CheckID/data/tier0-permissions.schema.json",
"title": "Tier 0 Microsoft Graph Permissions",
"description": "Schema for tier0-permissions.json - Microsoft Graph application permissions classified as Tier 0 (each has a documented attack path to Global Administrator), plus a Tier 1 high-impact data-access list. Referenced by app/service-principal privilege detection.",
"type": "object",
"required": ["$schema", "description", "version", "permissions"],
"additionalProperties": false,
"properties": {
"$schema": { "type": "string" },
"description": { "type": "string", "minLength": 1 },
"version": {
"type": "string",
"minLength": 1,
"description": "Revision marker (the source list is dated, e.g. '2025-05')."
},
"permissions": {
"type": "array",
"minItems": 1,
"items": { "$ref": "#/$defs/permission" },
"description": "Graph application permissions classified as Tier 0."
},
"tier1DataAccess": {
"type": "array",
"uniqueItems": true,
"items": { "type": "string", "minLength": 1 },
"description": "Graph permissions granting high-impact data access (Tier 1)."
}
},
"$defs": {
"permission": {
"type": "object",
"required": ["permission", "category", "attackPath"],
"additionalProperties": false,
"properties": {
"permission": {
"type": "string",
"pattern": "^[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)+$",
"description": "Microsoft Graph permission name (e.g. 'RoleManagement.ReadWrite.Directory')."
},
"category": {
"type": "string",
"minLength": 1,
"description": "Attack-path category (e.g. 'role-assignment', 'credential-injection')."
},
"attackPath": {
"type": "string",
"minLength": 1,
"description": "Documented path from this permission to Global Administrator."
}
}
}
}
}
Loading
Loading