Dfrank77/entra-attack-path-visualizer
GitHub: Dfrank77/entra-attack-path-visualizer
通过 Microsoft Graph 自动扫描 Entra ID 租户,检测直接角色分配、嵌套组成员身份及 PIM 符合条件分配形成的权限提升路径并生成 HTML 报告的云身份安全审计工具。
Stars: 0 | Forks: 0
# Entra ID 攻击路径可视化工具
通过 Microsoft Graph 扫描 Microsoft Entra ID 租户,检测通过直接角色分配、组成员身份以及 PIM 符合条件的分配形成的权限提升路径,并生成结构化的 HTML 报告。
**注意:** 已在故意植入错误配置的实验室租户中进行了验证(包括过多的特权分配、嵌套组提升路径以及休眠的 PIM 资格)。扫描结果仅反映该种子环境,而非生产租户。
这是基于共享库 [`entra-security-report`](https://github.com/Dfrank77/entra-security-report) 构建的三件套工具组合的一部分,与 [`entra-workload-identity-scanner`](https://github.com/Dfrank77/entra-workload-identity-scanner) 和 [`entra-zt-policy-engine`](https://github.com/Dfrank77/entra-zt-policy-engine) 配套使用。

## 存在的问题
企业往往难以追踪在 Entra ID 中谁拥有管理员权限:
- **影子管理员** 通过嵌套组成员身份继承了管理员权限,却无人察觉
- **PIM 盲区**:拥有符合条件的(尚未激活)角色的用户不会出现在标准的目录角色查询中,但他们可以随时将其激活为管理员
- **角色泛滥**:多个用户和组被不必要地分配了特权角色
- **人工审查遗漏间接路径**:如果某个用户所在的组被分配了全局管理员,那么该用户就是全局管理员,但这并不会显示在该用户的直接角色分配中
每季度对数百个用户和组进行人工审查需要耗费 40 多个小时。而本工具只需不到 5 分钟即可自动完成。
## 检测内容
每一条提升路径都会作为一个结构化的发现输出,并在多次扫描中保持稳定的标识,这使得该工具能够回答“自上次运行以来有什么新变化”以及“修复了什么”。
| 规则 | 严重程度 | 含义 |
|---|---|---|
| direct-role-assignment (HIGH-risk role) | critical | 用户直接持有诸如全局管理员或特权角色管理员之类的 tier-0 管理员角色 |
| direct-role-assignment (MEDIUM-risk role) | high | 用户直接持有中层级管理员角色 |
| transitive-role-via-group (HIGH-risk role) | critical | 用户通过组成员身份继承了 tier-0 角色 |
| transitive-role-via-group (MEDIUM-risk role) | high | 用户通过组成员身份继承了中层级角色 |
| pim-eligible-direct (HIGH-risk role) | high | 用户符合 tier-0 角色的 PIM 条件,拥有他们可以随时激活的休眠特权 |
| pim-eligible-via-group (HIGH-risk role) | high | 用户通过组成员身份符合 PIM 条件 |
| pim-eligible-direct 或 pim-eligible-via-group (MEDIUM-risk) | medium | 与上述相同,适用于中层级角色 |
这些发现会通过共享报告库持久化保存在 `.findings/` 目录下的多次扫描中。重新运行扫描器会自动生成差异对比:`自上次运行以来新增 X 条`,`自上次运行以来修复 Y 条`。
## 输出
生成一个产物:`output/privilege_report.html` —— 这是一份结构化的卡片式报告,与另外两款工具保持一致。每个主体(用户)对应一张卡片,发现结果按最高严重程度分组,并根据层级着色。
## 安装说明
### 前置条件
- Python 3.10+
- 具有管理员读取权限的 Microsoft Entra ID 租户
- Entra ID P2 许可证(用于扫描符合条件的 PIM 角色)
### 设置
```
git clone https://github.com/Dfrank77/entra-attack-path-visualizer.git
cd entra-attack-path-visualizer
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
pip install git+https://github.com/Dfrank77/entra-security-report.git
```
如果您在本地拥有该共享库,请改用 `pip install -e ../entra-security-report`。
### 所需的 Microsoft Graph 权限
| 权限 | 原因 |
|---|---|
| User.Read.All | 读取所有用户配置文件 |
| Group.Read.All | 读取所有组成员身份 |
| Directory.Read.All | 读取目录数据 |
| RoleManagement.Read.All | 读取角色分配 |
| RoleManagement.Read.Directory | 读取目录角色定义 |
| RoleEligibilitySchedule.Read.Directory | 读取符合条件的 PIM 角色分配 |
## 运行说明
```
source venv/bin/activate
python entra_scanner.py
python visualizer.py
open output/privilege_report.html
```
### 执行流程
1. 扫描器通过浏览器进行身份验证,枚举用户、组、活动角色分配以及符合条件的 PIM 分配。每一条提升路径都会成为一个 `Finding` 对象,其严重程度根据角色层级和分配类型进行映射。这些发现会被持久化到 `.findings/` 中。
2. 可视化工具从存储中读取最新的扫描结果,并通过共享的 `render()` 函数渲染出结构化的 HTML 报告。
## 架构
- `entra_scanner.py`:扫描器,生成 Finding 对象,并将其持久化到共享存储中
- `visualizer.py`:读取最新的扫描结果,生成结构化的 HTML 报告
- `output/`:生成的报告(已通过 gitignore 忽略)
- `.findings/`:持久化的发现结果和扫描历史记录(已通过 gitignore 忽略)
### 值得说明的设计决策
**发现结果是结构化的,而非简单的显示字符串。** 每条路径都是一个 Finding,包含主体(用户)、证据(完整的路径数组及类型),以及根据高风险/中风险与活动/符合条件的分配相映射得出的严重程度。工作负载扫描器和 ZT 引擎会生成相同 schema 的发现结果,这正是实现跨工具关联的基础。
**严重程度映射规则。** 高风险角色 + 活动 = critical。高风险角色 + 符合条件 = high。中风险角色 + 活动 = high。中风险角色 + 符合条件 = medium。这将“直接 + 特权 = 紧急,休眠 + 中层级 = 关注”的逻辑在代码中明确体现,而不是仅停留在文本上。
**PIM 查询直接使用 aiohttp。** Graph SDK 对 `roleEligibilitySchedules` 的支持不够稳定。扫描器没有选择去与 SDK 的 bug 妥协,而是使用 aiohttp 并携带原始 bearer token 直接发起 REST 调用。之所以必须使用异步,是因为 Graph SDK 强制要求仅支持异步操作。
## 作者
**Darius Frank** — IAM 与云安全
- GitHub: [@Dfrank77](https://github.com/Dfrank77)
- LinkedIn: [Darius Frank](https://www.linkedin.com/in/darius-frank/)
## 许可证
MIT — 请参阅 [LICENSE](LICENSE)
## 免责声明
本工具仅用于授权的安全评估和合规审计。您必须拥有适当的权限才能扫描您的 Entra ID 环境。未经授权访问系统是违法行为。
标签:Microsoft Entra ID, 协议分析, 多模态安全, 攻击路径可视化, 权限提升, 身份与访问管理, 逆向工具, 黑客工具