prodfail/M365IR

GitHub: prodfail/M365IR

一个经过测试的 M365 安全事件响应 PowerShell 模块,提供只读调查、Playbook 编排和 token 门控的封禁隔离机制。

Stars: 0 | Forks: 0

# M365IR:Microsoft 365 事件响应 PowerShell 模块 一个用于调查 Microsoft 365 安全事件的只读 PowerShell 模块:网络钓鱼、BEC、账户接管、AiTM/MFA 绕过、OAuth 滥用和数据外发。专为在凌晨 2 点处理事件的分析师而构建:每个查询都会完整分页,每个日期限制都会在造成影响前进行验证,并且每个发现都会作为带哈希值的证据保存在磁盘上。 **安全姿态:** `M365IR` 模块对租户是只读的。写入/封禁操作特意放在一个独立的 `M365IR.Containment` 模块中,该模块受到随机 token 确认机制的限制。这种隔离是由测试强制执行的,而非依靠约定。 ## 为什么选择 v2 v1 是一个复制粘贴的操作手册(保留在 [docs/RUNBOOK.md](docs/RUNBOOK.md) 中)。v2 将其转换为一个经过测试的模块,并增加了操作手册无法做到的功能: - **Playbook 编排:** `Invoke-IRPlaybook -Type AiTM` 运行整个调查序列并将每一步导出为证据。 - **仅应用证书认证**,用于自动化,以及应对管理员账户就是那个被盗用账户的情况。 - **每日安全扫描**(`Invoke-IRDailySweep`):高风险用户、新的收件箱规则、同意授权、设备注册、传统认证命中、审计健康状态,全部快照到磁盘。集轻量级检测层和持续监控证据于一体。 - **MailItemsAccessed 违规范围界定**,内置对 bind/sync/throttling 的解析。 - **自动处理 Microsoft 限制的邮件跟踪:** 自动将时间窗口切分为 10 天的查询,自动对 5000 行上限进行分页,在 5 分钟 100 次的限流下休眠,拒绝超过 90 天上限的窗口。 - **默认提供监管链:** 案件文件夹、会话记录、SHA256 哈希的 CSV+JSON 导出,以及一份清单。 - **离线测试套件** (Pester),涵盖窗口切分、输入验证、确认门控以及只读/写入模块分离。 ## 仓库结构 ``` src/M365IR/ M365IR.psd1 Module manifest M365IR.psm1 Read-only investigation module (24 functions) M365IR.Containment.psm1 Write operations, token-gated (import deliberately) tests/M365IR.Tests.ps1 Pester tests (offline, no tenant needed) docs/RUNBOOK.md v1 copy-paste runbook (still valid for ad hoc work) docs/CONTAINMENT-RUNBOOK.md v1 containment runbook ``` ## 要求 - macOS、Windows 或 Linux 上的 PowerShell 7.0+ (`pwsh`) - `ExchangeOnlineManagement` **3.7.0+** (Get-MessageTraceV2 基线) - `Microsoft.Graph` 2.0+ - 可选:用于 `Get-IRFlowPersistence` 的 `Microsoft.PowerApps.Administration.PowerShell` `Test-IRPreflight` 会检查所有这些条件并提供门控安装。 ## 快速开始(交互式) ``` git clone https://github.com/prodfail/m365-ir-toolkit.git cd m365-ir-toolkit Import-Module ./src/M365IR/M365IR.psd1 Test-IRPreflight Connect-IRTenant -AdminUPN admin@example.com # Scope 设置一次;每个 function 都会继承它 Set-IRScope -TargetUser user@example.com -StartDate (Get-Date).AddDays(-3) # 运行完整 playbook:打开 case,运行每个 step,导出 hashed evidence Invoke-IRPlaybook -Type AiTM # 或者逐个 function 执行 New-IRCase Get-IRSignInActivity -Kind NonInteractive | Export-IREvidence -Name SignIns_NonInt Get-IRMailItemsAccessed | ForEach-Object { $_.Sessions } | Export-IREvidence -Name MIA_Sessions Get-IRMailboxForensics | Export-IREvidence -Name MailboxForensics # 包含预填充 evidence inventory 的报告骨架 New-IRReportDraft -IncidentTitle "AiTM compromise of user@example.com" Close-IRCase ``` ## 仅应用(证书)认证 用于自动化,并且因为交互式认证往往会在你最需要它的时候失败。一次性设置: 1. **创建证书**(自签名证书即可用于此目的): $cert = New-SelfSignedCertificate -Subject "CN=M365IR" -CertStoreLocation Cert:\CurrentUser\My ` -KeyExportPolicy NonExportable -KeySpec Signature -KeyLength 2048 Export-Certificate -Cert $cert -FilePath ./m365ir.cer (macOS/Linux:使用 `openssl` 生成并导入到证书存储,或者对导入的 PEM 证书使用 `-CertificateThumbprint`。) 2. **在 Entra ID 中注册应用**:App registrations > New。在 Certificates & secrets 下上传 `m365ir.cer`。 3. **Graph 应用权限**(只读集),然后授予管理员同意: `AuditLog.Read.All`, `Directory.Read.All`, `User.Read.All`, `Policy.Read.All`, `SecurityEvents.Read.All`, `IdentityRiskyUser.Read.All`, `MailboxSettings.Read` 4. **Exchange Online 应用访问:** 添加 `Office 365 Exchange Online > Exchange.ManageAsApp` 应用程序权限,然后为应用分配最小特权的 Exchange 角色。首选:Exchange RBAC for Applications,将应用的服务主体放在 **View-Only Organization Management** 中。备选方案(权限比需要的宽):为服务主体分配 Entra **Global Reader** 角色;除非你也打算通过它运行封禁操作,否则请避免使用 Exchange Administrator。 5. **连接:** Connect-IRTenant -TenantId -AppId ` -CertificateThumbprint -Organization example.com ## 每日扫描(主动模式) ``` Connect-IRTenant -TenantId $tid -AppId $app -CertificateThumbprint $thumb -Organization example.com Invoke-IRDailySweep ``` 检查过去 24 小时内的:审计健康状态下降、活跃的高风险用户、收件箱规则更改、新的 OAuth 授权、设备注册和传统认证登录。每次运行写入一个 JSON 快照并打印调查结果摘要。安排它的执行: ``` # cron (Linux/macOS),工作日 07:00 0 7 * * 1-5 /usr/local/bin/pwsh -NoProfile -File /path/to/sweep.ps1 ``` 其中 `sweep.ps1` 导入模块,以仅应用方式连接,并调用 `Invoke-IRDailySweep`。在 macOS 上首选 launchd plist;在 Windows 上首选 Task Scheduler。 ## 功能参考 | 功能 | 用途 | |---|---| | `Test-IRPreflight` | 版本/模块检查,带门控安装 | | `Connect-IRTenant` | EXO + Graph,交互式或仅应用证书 | | `Set-IRScope` | 默认目标用户 + 调查窗口 | | `New-IRCase` / `Export-IREvidence` / `Close-IRCase` | 案件文件夹、记录、带哈希的证据清单 | | `Search-IRAuditLog` | 完全分页的 UAL 搜索 (ReturnLargeSet) | | `Test-IRAuditHealth` | UAL 摄取 + 每个邮箱的审计验证 | | `Get-IRAccountBaseline` | 账户状态、MFA 方法、角色、最近登录 | | `Get-IRSignInActivity` | `-Kind Interactive` / `NonInteractive` / `Risky` / `ServicePrincipal` / `ManagedIdentity` / `LegacyAuth` | | `Get-IRDirectoryAudit` | 密码重置、MFA 注册、设备注册、角色/CA 更改、同意授权 | | `Get-IRMailItemsAccessed` | 违规范围界定:bind/sync 解析、会话汇总、限流警告 | | `Get-IRMailboxForensics` | 规则、转发、代理,带有可疑标记 | | `Get-IRMessageTrace` | V2 跟踪,带自动切分、分页、限流处理 | | `Get-IROAuthGrants` | 用户授权、最近的应用注册、凭据化的 SP | | `Get-IRSecurityAlerts` | 高风险用户 + alerts_v2,通过证据匹配进行目标范围界定 | | `Get-IRSharePointActivity` / `Get-IRTeamsActivity` | 工作负载 UAL 取证 | | `Get-IRFlowPersistence` | Power Automate 持久化排查 | | `Get-IRCAGapAnalysis` | CA 状态、排除清单、传统认证覆盖范围 | | `Get-IRThreatIntel` | ThreatFox + OTX + OpenPhish 富化(缓存的 feed) | | `Invoke-IRPlaybook` | `-Type AccountTakeover` / `AiTM` / `BEC` / `Phishing` / `DataExfil` | | `Invoke-IRDailySweep` | 带快照的主动每日检测扫描 | | `New-IRReportDraft` | 从案件清单生成报告骨架 | ## 封禁(独立模块,特意设计) ``` Import-Module ./src/M365IR/M365IR.Containment.psm1 # deliberate act Connect-MgGraph -Scopes "User.ReadWrite.All","User.RevokeSessions.All","Application.ReadWrite.All" Invoke-IRPasswordReset -TargetUser user@example.com Invoke-IRSessionRevocation -TargetUser user@example.com Disable-IRInboxRule -TargetUser user@example.com -RuleName "Sync" # disable first Disable-IRInboxRule -TargetUser user@example.com -RuleName "Sync" -Remove # remove after evidence Clear-IRMailForwarding -TargetUser user@example.com Disable-IROAuthApp -ServicePrincipalId -GrantId Block-IRSender -Entry attacker@evil.example Invoke-IRMailPurge -Subject "Invoice overdue" -SenderAddress attacker@evil.example # stage 1: search Invoke-IRMailPurge -Subject "Invoice overdue" -SenderAddress attacker@evil.example -SearchName -ExecutePurge ``` 每个功能:支持 `-WhatIf`,需要输入一个随机的 4 字母 token(区分大小写,不依赖肌肉记忆输入 Y),并遵循模块头部中的行动规则:先授权,封禁前先获取证据,遵循重置后撤销的顺序。邮件清除分为两个阶段,在搜索和 SoftDelete 之间强制要求进行审查;HardDelete 被特意未实现。 ## 数据保留限制 | 来源 | 保留期 | |---|---| | Entra 登录 / 目录审计 (Graph) | 30 天 (P1/P2);免费层 7 天 | | 统一审计日志 | 180 天 (Audit Standard);1 年 (Premium) | | 邮件跟踪 V2 | 总共 90 天;每次查询 10 天(自动处理) | | 隔离区 | 30 天 | 在保留窗口之外的空结果意味着“没有可用数据”,而不是“什么也没发生”。`Get-IRMessageTrace` 会强制执行其上限;在界定范围时请注意其他限制。 ## 测试 ``` Install-Module Pester -MinimumVersion 5.0 -Scope CurrentUser Invoke-Pester ./tests ``` 所有测试均离线运行(不需要租户)。它们涵盖:导出的功能接口、只读保证、日期窗口切分计算、邮件跟踪输入验证、证据导出行为、封禁确认门控(错误的 token、区分大小写),以及每个封禁功能上的 `-WhatIf` 支持。CI 会在每次推送时运行它们。 ## 许可证 MIT。详见 [LICENSE](LICENSE)。按“原样”提供用于防御性安全用途,不提供任何形式的保证。
标签:AI合规, IPv6, Libemu, Microsoft 365, PowerShell, 取证, 安全运营, 扫描框架, 数据泄露, 网络调试, 自动化