微软门户网站 https://msportals.io/
官方工具安装 Azure PowerShell 是用于管理 Azure 资源的官方 Microsoft PowerShell 模块集合的产品名称,可以枚举 Entra ID 和 Azure 资源
// 查看powershell版本 $PSVersionTable.PSVersion // 安装 PowerShellGet Install-Module -Name PowerShellGet -Force [Y] Yes [N] No [S] Suspend [?] Help (default is "Y"): Y // 放宽PowerShell策略 Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A // 安装 Azure PowerShell 模块 Install-Module -Name Az -Repository PSGallery -Force // 验证 Get-InstalledModule -Name Az -AllVersions // 更新 Azure PowerShell Update-Module -Name Az -Force
Graph PowerShell Microsoft Graph PowerShell SDK 是 Microsoft Graph API 的 API 封装器,将整个 API 集暴露给 PowerShell 使用,建议用于与 Microsoft Entra ID 进行交互
// 放宽PowerShell策略 Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A // 为当前用户安装 Install-Module Microsoft.Graph -Scope CurrentUser [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A // 验证 Get-InstalledModule Microsoft.Graph
在Windows Powershell 环境下安装了 Microsoft.Graph 2.x 版本后,Az 和 Graph 会出现函数找不到的兼容问题,例如:
Get-MgGroup : 找不到方法:Void Microsoft.Graph.Authentication.AzureIdentityAccessTokenProvider..ctor
Azure CLI 是一款跨平台命令行工具,用于连接到 Azure 并通过交互式命令或脚本管理 Azure 资源
// 安装 $ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest -Uri https://aka.ms/installazurecliwindows -OutFile .\AzureCLI.msi; Start-Process msiexec.exe -Wait -ArgumentList '/I', 'AzureCLI.msi', '/quiet'; Remove-Item .\AzureCLI.msi // 验证 az --version
凭证登录 Azure Powershell // 弹出来门户登录 Connect-AzAccount // 用户账号密码登录 $pass = ConvertTo-SecureString '<PASSWORD>' -AsPlainText -Force $cred = New-Object System.Management.Automation.PSCredential("<UserPrincipalName>", $pass) Connect-AzAccount -Credential $cred // 服务主体密钥登录 $pass = ConvertTo-SecureString '<SECRET>' -AsPlainText -Force $cred = New-Object System.Management.Automation.PSCredential("<CLIENTID>", $pass) Connect-AzAccount -ServicePrincipal -Tenant "<TENANTID>" -Credential $cred // Token登录 Connect-AzAccount -AccessToken "<eyJ0......>" -AccountId "<ANY_NAME>"
Graph PowerShell // 弹出来门户登录 Connect-MgGraph // Token登录 $pass = ConvertTo-SecureString "<PASSWORD>" -AsPlainText -Force $cred = New-Object System.Management.Automation.PSCredential("<User>", $pass) Connect-AzAccount -Credential $cred $Token = (Get-AzAccessToken -ResourceTypeName MSGraph).Token Connect-MgGraph -AccessToken $Token // 添加权限范围 Connect-MgGraph -Scopes "User.Read.All","Group.Read.All","Directory.Read.All","Application.Read.All"
Azure Cli az login --user "<username>" --password "<password>"
Portal 门户 https://portal.azure.com/
REST API 纯拿Token访问API,可以写python脚本
GET /v1.0/users HTTP/1.1 Host: graph.microsoft.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Authorization: Bearer <Token> Accept: application/json Connection: close
常用命令 这里只偏向记录Entra ID的命令,完整官方档案:
Az Ps 断开连接
命令格式,关于Azure AD格式均为 AzAD
获取为当前用户授权的所有租户
当前身份上下文元数据
获取Graph的 Access Token
(Get-AzAccessToken -AsSecureString -ResourceTypeName MSGraph).Token
列出所有 Azure RBAC 角色分配
获取Entra ID用户信息
// 所有用户信息 Get-AzADUser // 数量 (Get-AzADUser -Select 'DisplayName').Count // 获取当前登录用户 Get-AzADUser -SignedIn // 模糊搜索 Get-AzADUser -UserPrincipalName [email protected] Get-AzADUser | ?{$_.Displayname -match "admin"} // 前10个 Get-AzADUser -First 10
获取Group信息
// 所有组信息 Get-AzADGroup // 数量 (Get-AzADGroup -Select DisplayName).Count // 模糊搜索 Get-AzADGroup -ObjectId 783a312d-0de2-4490-92e4-539b0e4ee03e Get-AzADGroup | ?{$_.Displayname -match "admin"} // 组成员 Get-AzADGroupMember -GroupObjectId xxx
Application(App Registration,应用注册)信息
// 所有app详细信息 Get-AzADApplication Get-AzADApplication -Select DisplayName,Id,AppId // 数量 (Get-AzADApplication -Select DisplayName).Count // 模糊搜索 Get-AzADApplication -ObjectId a1333e88-1278-41bf-8145-155a069ebed0 Get-AzADApplication | ?{$_.DisplayName -match "app"} // 查询所有存在 Client Secret 的app Get-AzADApplication -Select DisplayName,Id,AppId,PasswordCredentials | Where-Object { $_.PasswordCredentials } // 查询所有存在 Certificate 的app Get-AzADApplication -Select DisplayName,Id,AppId,KeyCredentials | Where-Object { $_.KeyCredentials }
Application 的凭据
Get-AzADAppCredential -ObjectId xxx Get-AzADAppCredential -DisplayName xxx Get-AzADAppCredential -ApplicationId xxx
ServicePrincipal(Enterprise Application,服务主体)信息
// 所有主体 Get-AzADServicePrincipal Get-AzADServicePrincipal -Select DisplayName,Id,AppId // 数量 (Get-AzADServicePrincipal -Select DisplayName).Count // 模糊搜索 Get-AzADServicePrincipal -ObjectId a1333e88-1278-41bf-8145-155a069ebed0 Get-AzADServicePrincipal | ?{$_.DisplayName -match "app"} // 查询所有存在 Client Secret 的主体 Get-AzADServicePrincipal -Select DisplayName,Id,AppId,PasswordCredentials | Where-Object { $_.PasswordCredentials } // 查询所有存在 Certificate 的主体 Get-AzADServicePrincipal -Select DisplayName,Id,AppId,KeyCredentials | Where-Object { $_.KeyCredentials }
从 ServicePrincipal 获取 appRoleAssignments
Get-AzADServicePrincipalAppRoleAssignment
ServicePrincipal的的凭据
Get-AzADSpCredential -ObjectId xxx
Graph Ps 断开连接
当前身份上下文
Get-MgContext (Get-MgContext).Scopes
用户
// 所有用户 Get-MgUser -All // 模糊搜索 Get-MgUser -UserId [email protected] Get-MgUser -All | ?{ $_.Displayname -match "admin" } Get-MgUser -Search '"DisplayName:admin"' -ConsistencyLevel eventual // 用户所有属性 Get-MgUser -UserId [email protected] | fl * Get-MgUser -UserId [email protected] | % { $_.PSObject.Properties.Name } // 搜索指定属性的用户 Get-MgUser -All | % { $Properties = $_; $Properties.PSObject.Properties.Name | % { if ($Properties.$_ -match 'password') { "$($Properties.UserPrincipalName) - $_ - $($Properties.$_)" } } } // 所有本地同步用户 Get-MgUser -All | ? { $_.OnPremisesSecurityIdentifier -ne $null } // 所有Entra Id用户 Get-MgUser -All | ? { $_.OnPremisesSecurityIdentifier -eq $null } // 用户创建的对象 Get-MgUserCreatedObject -UserId [email protected] | fl * // 用户拥有的对象 Get-MgUserOwnedObject -UserId [email protected] | fl * // 用户所属组和角色 (Get-MgUserMemberOf -UserId [email protected] ).AdditionalProperties
组
// 所有组 Get-MgGroup -All // 指定组 Get-MgGroup -GroupId xxxx // 动态组 Get-MgGroup | ? { $_.GroupTypes -eq 'DynamicMembership' } // 模糊查找 Get-MgGroup -ConsistencyLevel eventual -Search '"DisplayName:Admin"' // 所有本地同步组 Get-MgGroup -All | ? { $_.OnPremisesSecurityIdentifier -ne $null } // 所有Entra Id组 Get-MgGroup -All | ? { $_.OnPremisesSecurityIdentifier -eq $null } // 组成员 Get-MgGroupMember -GroupId xxx // 组owner Get-MgGroupOwner
角色
// 所有可用的角色模板 Get-MgDirectoryRoleTemplate // 启用角色 Get-MgDirectoryRole // 模糊查询 Get-MgRoleManagementDirectoryRoleDefinition -Filter "DisplayName eq 'AS-ADCRADLC8'" | Format-List // 所有被分配了角色的用户 $RoleId = (Get-MgDirectoryRole -Filter "DisplayName eq 'Global Administrator'").Id (Get-MgDirectoryRoleMember -DirectoryRoleId $RoleId).AdditionalProperties // 角色拥有的权限 (Get-MgRoleManagementDirectoryRoleDefinition -Filter "DisplayName eq 'AS-ADCRADLC8'").RolePermissions.AllowedResourceActions
设备
// 所有已加入和已注册的 Azure 设备 Get-MgDevice –All | fl * // 活动设备 Get-MgDevice –All | ? { $_.ApproximateLastSignInDateTime -ne $null } // 所有设备的注册所有者 $Ids = (Get-MgDevice –All).Id; foreach($i in $Ids) { (Get-MgDeviceRegisteredOwner -DeviceId $i).AdditionalProperties } $Ids = (Get-MgDevice –All).Id; foreach($i in $Ids) { (Get-MgDeviceRegisteredOwner -DeviceId $i).AdditionalProperties.userPrincipalName } // 所有设备的注册用户 $Ids = (Get-MgDevice –All).Id; foreach($i in $Ids) { (Get-MgDeviceRegisteredUser -DeviceId $i).AdditionalProperties } $Ids = (Get-MgDevice –All).Id; foreach($i in $Ids) { (Get-MgDeviceRegisteredUser -DeviceId $i).AdditionalProperties.userPrincipalName } // 用户拥有的设备 (Get-MgUserOwnedDevice -UserId [email protected] ).AdditionalProperties // 用户注册设备 (Get-MgUserRegisteredDevice -UserId [email protected] ).AdditionalProperties // Intune 管理的设备 Get-MgDevice -All | ? { $_.IsCompliant -eq "True" } | fl *
Application
Get-MgApplication -All // 指定app Get-MgApplicationByAppId -AppId f072c4a6-b440-40de-983f-a7f3bd317d8f | fl * // 模糊搜索 Get-MgApplication -All | ? { $_.DisplayName -match "app" } // app拥有者 (Get-MgApplicationOwner -ApplicationId 35589758-714e-43a9-be9e-94d22fdd34f6).AdditionalProperties.userPrincipalName // 某个用户被授予了哪些应用权限 Get-MgUserAppRoleAssignment -UserId [email protected] | fl * // 某个组被授予了哪些应用权限 Get-MgGroupAppRoleAssignment -GroupId 57ada729-a581-4d6f-9f16-3fe0961ada82 | fl *
ServicePrincipal
Get-MgServicePrincipal -All // 指定服务主体 Get-MgServicePrincipal -ServicePrincipalId fd518680-b290-4db2-b92a-5dbd025c6791 | fl * // 模糊搜索 Get-MgServicePrincipal –All | ? { $_.DisplayName -match "app" } // 服务主体的拥有者 (Get-MgServicePrincipalOwner -ServicePrincipalId fd518680-b290-4db2-b92a-5dbd025c6791).AdditionalProperties.userPrincipalName // 服务主体拥有的对象 Get-MgServicePrincipalOwnedObject -ServicePrincipalId fd518680-b290-4db2-b92a-5dbd025c6791 // 服务主体创建的对象 Get-MgServicePrincipalCreatedObject -ServicePrincipalId fd518680-b290-4db2-b92a-5dbd025c6791 // 服务主体的组成员身份和角色成员身份 Get-MgServicePrincipalMemberOf -ServicePrincipalId fd518680-b290-4db2-b92a-5dbd025c6791 | fl *
身份验证 Microsoft Identity Platform(微软身份平台)使用两种不同的协议完成两件不同的事
OpenID Connect(OIDC):身份验证(Authentication)即 你是谁
OAuth2:授权(Authorization)即 你能做什么
Token 微软通常会同时返回三种token
ID Token :客户端从授权服务器接收此令牌,它包含用户的基本信息,用作登录身份
Access Token :客户端向资源服务器提供此令牌以访问资源,它只能用于特定的用户、客户端和资源组合,并且在过期前(默认为 1 小时)无法撤销,用作通过API进行资源访问
Refresh Token :用于获取新的 Access Token 和 ID Token,非活跃刷新令牌的默认过期时间为 90 天,活跃令牌没有过期时间,可以被撤销
攻击流程 按 Recon → Initial Access → Post-Ex → Persistence → 横向移动 → 特殊攻击(SAML/MFA) 分层整理
External Reconnaissance Initial Access Token Acquisition Internal Enumeration Privilege Escalation Lateral Movement Persistence Defense Evasion Data Exfiltration --- 外部侦察 初始访问 令牌获取 内部枚举 权限提升 横向移动 持久化 防御规避 数据泄露
信息收集/枚举 目标:摸清 Entra ID / Azure / O365 结构
AzureHound:类似 BloodHound,但针对 Azure / Entra ID
ROADtools(ROADrecon)
枚举 Azure AD / Entra ID(非常核心)
支持 Graph API、token 操作
Stormspotter
MicroBurst
o365recon / o365creeper
初始访问 云红队最常见:账号攻击
工具
MSOLSpray
o365spray
TrevorSpray
CredMaster(配合代理)
主要攻击:
Password spraying
用户名枚举
MFA 疲劳攻击
权限提升/后渗透 获取 token 后才是真正开始
工具
GraphRunner
Microsoft Graph API 后渗透框架
GraphSpy
GUI 操作 O365 数据(邮件 / OneDrive / Teams)
APEX
Azure 后渗透框架(整合 ROADtools 等)
PowerZure
凭证获取/Token攻击 Azure 和传统 AD 最大区别:Token 即权限
工具
AADInternals
获取 token、dump 信息、滥用 Azure AD
adconnectdump
EntraTokenAid(社区工具)
获取 access / refresh token(红队常用)
持久化 云环境 persistence 很隐蔽
技术
Service Principal backdoor
恶意 App 注册
Guest 用户植入
相关工具:
ROADtools
GraphRunner
AADInternals
攻击方式示例:
创建隐藏角色绑定
添加高权限应用
修改 API 权限
横向移动 在云里 = 权限链移动
工具
AzureHound + BloodHound
Stormspotter
核心思想:
找 ‘谁可以控制谁’
利用 RBAC / App / Role 关系
O365 专用攻击工具 偏数据窃取
MailSniper
GraphSpy
跨 OneDrive / SharePoint / Teams 搜索
github.com/admindroid-community/powershell-scripts
高级攻击 这部分是云红队精髓
Evilginx
反向代理钓鱼
窃取 session cookie
绕过 MFA
云红队必备
Golden SAML
伪造 SAML token
直接登录 O365 / Azure
类似 Kerberos Golden Ticket(云版)
MFA 攻击
MFASweep
MFA fatigue(骚扰认证)
综合工具链总结 Recon: AzureHound + ROADrecon Initial Access: o365spray / MSOLSpray Post-Ex: GraphRunner / AADInternals Persistence: App backdoor / Service Principal Data Access: GraphSpy / MailSniper Advanced: Evilginx2 / Golden SAML
重点深入这几个方向
Microsoft Graph API 攻击面
OAuth / Token 滥用
App Registration 攻击
Conditional Access 绕过
PRT(Primary Refresh Token)攻击
Reference https://learn.microsoft.com/en-us/powershell/azure/
https://learn.microsoft.com/en-us/powershell/microsoftgraph/
https://learn.microsoft.com/en-us/cli/azure/
https://johnermac.github.io/notes/cartp/cartp1/
https://johnermac.github.io/notes/cartp/cartp2/
https://johnermac.github.io/notes/cartp/cartp3/