检测 Azure 横向移动:基于 Microsoft Graph API 与 Sentinel KQL 的实战检测指南
【免费下载链接】Anthropic-Cybersecurity-Skills817 structured cybersecurity skills for AI agents · Mapped to 6 frameworks: MITRE ATT&CK, NIST CSF 2.0, MITRE ATLAS, D3FEND, NIST AI RMF & MITRE F3 (Fight Fraud) · agentskills.io standard · Works with Claude Code, GitHub Copilot, Codex CLI, Cursor, Gemini CLI & 20+ platforms · 29 security domains · Apache 2.0项目地址: https://gitcode.com/GitHub_Trending/an/Anthropic-Cybersecurity-Skills
在 Azure AD / Entra ID 环境中,攻击者的横向移动与本地域环境截然不同:他们不再依赖 SMB/RDP 会话,而是通过 OAuth 应用同意授权(consent grant)、服务主体(service principal)凭据滥用、跨租户访问与令牌窃取来实现身份层面的横向跳板。本文以 Anthropic-Cybersecurity-Skills 仓库中 detecting-azure-lateral-movement 技能的 API 参考文档为骨架,完整覆盖 Microsoft Graph API 审计端点、客户端凭据认证流程、Sentinel KQL 检测查询与 MITRE ATT&CK 技术映射,并结合仓库内的自动化检测脚本 scripts/agent.py 深入讲解每类横向移动指标的底层判定逻辑。读完本文,你将能够在 Microsoft Sentinel 中构建针对 OAuth 滥用、SP 凭据篡改、令牌重放与跨租户访问的检测规则,并用 Python 脚本将 Graph 审计数据转化为带 MITRE 映射的结构化风险报告。
为什么云身份横向移动需要专门的检测手段
本地环境的横向移动往往表现为端口扫描、SMB 会话或 RDP 连接等网络层行为;而 Azure AD 是身份平面,攻击者通过以下方式在身份层面横向移动:
- OAuth 应用同意授权:诱导或滥用权限授予未知应用,获取对目录资源的委派访问;
- 服务主体凭据篡改:向服务主体添加新凭据,从而以该应用身份长期驻留并移动;
- 令牌重放:窃取访问令牌/刷新令牌后,从不同 IP 或不同用户代理组合中重放;
- 跨租户访问:通过 B2B 协作或跨租户策略进入资源租户(T1078.004)。
按照 SKILL.md 中的描述,检测这些行为需要关联Microsoft Graph API 审计日志、Azure AD 登录日志与 Entra ID 风险事件,再通过 Microsoft Sentinel 的 KQL 查询进行相关性分析。这与本地环境仅依赖网络流量的检测方式完全不同,也是该技能的核心价值所在。
Microsoft Graph API 端点速查
api-reference.md 给出了检测所需的核心 Graph 端点清单。检测脚本 scripts/agent.py 正是基于这些端点进行数据采集:
| 端点 | 方法 | 用途 |
|---|---|---|
/v1.0/auditLogs/directoryAudits | GET | Azure AD 目录审计事件(consent、凭据变更等) |
/v1.0/auditLogs/signIns | GET | 交互式登录日志 |
/beta/auditLogs/signIns | GET | 非交互式登录 + 服务主体(SP)登录日志 |
/v1.0/identityProtection/riskDetections | GET | 身份保护风险检测事件 |
/v1.0/servicePrincipals | GET | 枚举服务主体 |
/v1.0/oauth2PermissionGrants | GET | 委派权限授权(OAuth 授权记录) |
在 scripts/agent.py 中,审计日志与登录日志的查询分别落到/v1.0/auditLogs/directoryAudits与/v1.0/auditLogs/signIns,并携带$filter(按activityDateTime/createdDateTime过滤时间窗口)、$top(限制 500 条)与$orderby(按时间倒序)参数,保证在 24 小时回看窗口内高效拉取数据。/beta/auditLogs/signIns之所以单列,是因为非交互式登录与服务主体登录在v1.0中并未完整覆盖,而这些恰恰是横向移动检测(如 SP 登录、令牌重放)的关键数据源。
客户端凭据流认证(Client Credentials Flow)
Graph API 的调用需要应用注册(App Registration)身份。API 参考文档提供了标准的 OAuth 2.0 客户端凭据流令牌获取方式:
curl -X POST "https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token" \ -d "grant_type=client_credentials" \ -d "client_id={app_id}" \ -d "client_secret={secret}" \ -d "scope=https://graph.microsoft.com/.default"其中:
{tenant}为 Azure AD 租户 ID;{app_id}为应用注册的 Client ID;{secret}为应用注册的客户端密钥;scope=https://graph.microsoft.com/.default表示请求 Graph API 的默认应用权限范围(即应用注册时授予的全部 Application 权限)。
scripts/agent.py 中的get_graph_token()函数用 Python 实现了完全相同的流程:向https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token发起 POST,携带grant_type=client_credentials、client_id、client_secret与.defaultscope,返回的 JSON 中提取access_token作为后续请求的Authorization: Bearer头。注意该令牌用于应用身份(非用户身份),因此只能访问通过应用权限(Application Permission)授予的数据,无法代表具体用户操作。
所需 Graph API 权限
要读取上述数据,应用注册需要以下 Application 类型权限(见 api-reference.md):
| 权限 | 类型 | 用途 |
|---|---|---|
AuditLog.Read.All | Application | 读取审计日志 |
Directory.Read.All | Application | 读取目录数据 |
SecurityEvents.Read.All | Application | 读取风险检测事件 |
Policy.Read.All | Application | 读取条件访问策略 |
这些权限与 SKILL.md 前置条件一节的要求一致(AuditLog.Read.All、Directory.Read.All、SecurityEvents.Read.All)。特别提醒:审计日志类权限属于高特权权限,需要租户管理员显式授予,部分场景还需要在 Azure AD 中启用「允许访问 Azure AD 审计日志」的数据访问策略,且SecurityEvents.Read.All依赖 Entra ID P2 许可。
Sentinel KQL 横向移动检测查询
api-reference.md 提供了四类可直接落地为 Sentinel 分析规则的 KQL 查询,每一类都对应一个具体的 MITRE ATT&CK 技术。
OAuth 应用同意授权(T1550.001 – Application Access Token)
AuditLogs | where OperationName == "Consent to application" | extend InitiatedBy = tostring(InitiatedBy.user.userPrincipalName) | extend AppName = tostring(TargetResources[0].displayName) | project TimeGenerated, InitiatedBy, AppName, Result该查询在目录审计日志中筛选「Consent to application」操作,提取发起人(InitiatedBy.user.userPrincipalName)与目标应用(TargetResources[0].displayName)。在 scripts/agent.py 的detect_oauth_consent_abuse()中,判定逻辑完全对应:遍历审计日志、匹配activityDisplayName是否包含"Consent to application"、读取首个targetResources的displayName与initiatedBy.user.userPrincipalName,输出严重级别为high的oauth_consent_grant发现项,映射 MITRET1550.001。落地规则时建议叠加「非预期应用」或「高风险应用」的基线,降低误报。
服务主体凭据添加(T1098.001 – Account Manipulation)
AuditLogs | where OperationName has_any ("Add service principal credentials", "Update application") | extend Actor = tostring(InitiatedBy.user.userPrincipalName) | extend Target = tostring(TargetResources[0].displayName) | project TimeGenerated, Actor, Target, OperationName服务主体凭据添加是攻击者建立身份持久化并横向移动的高价值指标。scripts/agent.py 的detect_service_principal_changes()将可疑操作扩展为三类:Add service principal credentials、Add service principal、Add app role assignment to service principal,任一命中即标记为critical级别的service_principal_credential_add,映射T1098.001。从源码结构看,这一扩展覆盖了「建主体、加凭据、加角色分配」的完整提权链,比单条操作名的匹配更能捕捉组合攻击。
令牌重放检测(T1528 – Steal Application Access Token)
SigninLogs | summarize IPCount=dcount(IPAddress), IPs=make_set(IPAddress) by UserPrincipalName, bin(TimeGenerated, 1h) | where IPCount >= 5 | sort by IPCount desc该查询以 1 小时为窗口、按用户聚合去重 IP 数,IP 数 ≥ 5 视为可疑。这与 scripts/agent.py 的detect_token_replay()完全同构:脚本先按用户分组所有登录会话(记录 IP、用户代理与时间),再统计唯一 IP 数量,>= 5即判定为critical级别的token_replay(映射T1528)。文档建议将 IP 与用户代理组合作为进一步的特征维度——同一用户短时间内从 5 个以上不同 IP 或不同 UA 组合出现,强烈暗示令牌在多个终端间流转。
跨租户访问(T1078.004 – Cloud Accounts)
SigninLogs | where ResourceTenantId != HomeTenantId | project TimeGenerated, UserPrincipalName, IPAddress, ResourceTenantId, AppDisplayName跨租户登录表示用户访问了非本租户的资源租户,是 B2B/跨租户横向移动的直接信号。scripts/agent.py 的detect_cross_tenant_signins()用resourceTenantId != home_tenant_id做同源比较,输出high级别的cross_tenant_signin(映射T1078.004),并附带源 IP 与资源租户 ID 供研判。落地时建议先建立合法跨租户协作白名单,避免对正常 B2B 业务产生噪声。
结合源码理解完整的检测流水线
除了上述检测函数,scripts/agent.py 还展示了一条可复制的端到端检测流水线:
- 指标字典集中声明(agent.py#L14-L21):
LATERAL_MOVEMENT_INDICATORS将六类指标(OAuth 同意授权、SP 凭据添加、跨租户登录、邮箱委派、令牌重放、条件访问绕过)统一映射到 MITRE 技术与严重级别,覆盖了 api-reference.md 中的四类技术并扩展到 T1098.002(邮箱委派)与 T1556.007(条件访问绕过); - 数据采集:
get_graph_token()→query_audit_logs()/query_signin_logs(); - 关联判定:各
detect_*()函数独立产出发现项; - 报告生成:
generate_report()(agent.py#L136-L149)输出 JSON 报告,包含回看窗口、发现总数、各指标计数与总体风险等级(critical>high>low); - 命令行运行:通过
--tenant-id、--client-id、--client-secret、--hours(默认 24)、--output(默认azure_lateral_movement_report.json)五个参数驱动。
这与 SKILL.md 中四个步骤(配置日志摄入 → 构建检测查询 → 事件关联 → 自动化响应)一一对应:其中「事件关联」正是「将多个低置信度指标链式组合为高置信度横向移动检测」——脚本内各detect_*()结果的聚合与risk_level汇总即是最小实现;「自动化响应」对应 Sentinel Playbook(Logic Apps)自动吊销可疑 OAuth 授权、禁用受损服务主体并强制逐步认证。
MITRE ATT&CK 技术映射对照
api-reference.md 给出了四类核心技术的官方映射:
| 技术 | ID | Azure 侧检测指标 |
|---|---|---|
| Application Access Token(应用访问令牌) | T1550.001 | OAuth 同意授权 |
| Account Manipulation(账户操纵) | T1098.001 | SP 凭据添加 |
| Cloud Accounts(云账户) | T1078.004 | 跨租户登录 |
| Steal Application Access Token(窃取应用访问令牌) | T1528 | 多 IP 来源令牌 |
SKILL.md 的 frontmatter 进一步将本技能映射到完整的 ATT&CK 集合:T1078.004、T1550.001、T1021.007(云服务远程会话)、T1098.003(额外云凭据)与T1528,同时对齐 NIST CSF 2.0 的PR.IR-01、ID.AM-08、GV.SC-06、DE.CM-01。在整个仓库层面,MITRE ATT&CK 映射说明 指出该映射体系支持威胁知情防御、差距分析与紫队演练,而 coverage-summary.md 中也明确将「云特定横向移动(T1550.001)」列为待进一步扩展的覆盖方向——这正是本技能所属的领域。若需将检测覆盖可视化,可参考仓库提供的 attack-navigator-layer.json(其中 T1528 被评分 4 并关联到技能引用)。
前置条件与落地建议
在将上述查询与脚本投入生产前,请核对以下前提(源自 SKILL.md):
- 已配置 Azure 订阅与 Microsoft Sentinel 工作区;
- 具备 Azure AD P2 / Entra ID P2 许可,以支撑基于风险的登录检测;
- 已完成 Graph API 权限授予:
AuditLog.Read.All、Directory.Read.All、SecurityEvents.Read.All; - Log Analytics 工作区已摄入
AuditLogs、SigninLogs、AADServicePrincipalSignInLogs三类表; - 团队具备 KQL 基础。
日志摄入方面,通过诊断设置将以下数据流式传输至 Log Analytics:交互式与非交互式登录日志、目录审计日志(目录变更与应用同意)、服务主体登录日志、预配日志、有风险用户与风险检测。数据就位后,即可按上文 KQL 创建 Sentinel 分析规则,或用仓库脚本在授权环境中执行自动化狩猎,并最终产出包含横向移动指标、关联事件链、受影响身份、建议遏制动作与 MITRE 技术映射的 JSON 报告。
【免费下载链接】Anthropic-Cybersecurity-Skills817 structured cybersecurity skills for AI agents · Mapped to 6 frameworks: MITRE ATT&CK, NIST CSF 2.0, MITRE ATLAS, D3FEND, NIST AI RMF & MITRE F3 (Fight Fraud) · agentskills.io standard · Works with Claude Code, GitHub Copilot, Codex CLI, Cursor, Gemini CLI & 20+ platforms · 29 security domains · Apache 2.0项目地址: https://gitcode.com/GitHub_Trending/an/Anthropic-Cybersecurity-Skills
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考