- Rewrote get-token.sh: tiered app system (investigator/exchange-op/user-manager/tenant-admin/defender) - Updated SKILL.md, command, gotchas, checklist, graph-endpoints for new app suite - Cascades breach check: mailbox clean, inbound phishing received by John, DMARC gap noted Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
49 lines
5.0 KiB
Markdown
49 lines
5.0 KiB
Markdown
# Breach-Check Rubric
|
|
|
|
How to interpret the outputs from `user-breach-check.sh` and `tenant-sweep.sh`.
|
|
|
|
## Single-user check — the 10 points
|
|
|
|
| # | Check | What "clean" looks like | Red flags |
|
|
|---|---|---|---|
|
|
| 1 | Inbox rules (Graph) | Empty, or only benign filters | ForwardTo / RedirectTo / ForwardAsAttachmentTo set; DeleteMessage+MarkAsRead combos; rules filtered on "password", "bank", "invoice", "CEO name", "security"; rules with name like "." or " " (attacker hiding) |
|
|
| 2 | Mailbox settings / auto-reply | Auto-reply disabled or legitimate | Auto-reply active with external audience + unfamiliar message body |
|
|
| 3 | Exchange REST (hidden rules, delegates, SendAs, Get-Mailbox forwarding fields) | Only SELF in permissions; no forwarding | **Hidden** inbox rule moving to RSS/Notes/Conversation History; non-SELF FullAccess/SendAs; ForwardingAddress or ForwardingSmtpAddress set to external |
|
|
| 4 | OAuth consents + app role assignments | Legitimate apps only (Teams, Outlook mobile, BlueMail, etc.); dates match user history | New consent in attack window; unknown app with `Mail.ReadWrite`, `Files.ReadWrite`, `offline_access`; publisher not verified |
|
|
| 5 | Auth methods | All methods predate the attack window | New phone/Authenticator registered within hours of first suspicious sign-in; duplicate entries with the same device name but different createdDateTime |
|
|
| 6 | Sign-ins 30d | Consistent US IPs, user's known geography | Any successful sign-in from a country the user never visits; IMAP/POP/Authenticated SMTP client apps (legacy auth); sign-ins from TOR exit nodes or known residential-proxy ranges |
|
|
| 7 | Directory audits | Only legit admin/system actions | `Update user` by non-admin principal; password reset the user didn't initiate; auth method change from `Microsoft Substrate Management` is normal but repeated changes are not |
|
|
| 8 | Risky users / risk detections | `riskLevel: none` | Any `medium` or `high`; `riskDetail: userPerformedSecuredPasswordChange` just means resolved — check the original detection |
|
|
| 9 | Sent items (recent 25) | Normal business correspondence | Blast emails to random external recipients; forwards of internal financial/HR info externally; anything after-hours from an unusual client app |
|
|
| 10 | Deleted items (recent 25) | Marketing/spam, routine notifications | Deleted security alerts, password-reset emails, MFA notifications, bounce notices the user wouldn't delete — all signs of attacker cleanup |
|
|
|
|
### Cross-check rule
|
|
|
|
If inbox rules and forwarding are clean **but** sign-ins show successful foreign access — attacker may have used OAuth-based access (check OAuth grants) or already extracted data and cleaned up. Pull sent items + deleted items aggressively and check `/auditLogs/signIns/beta` for non-interactive sign-ins.
|
|
|
|
## Tenant-wide sweep — priorities
|
|
|
|
| Priority | Signal | Action |
|
|
|---|---|---|
|
|
| P1 | User with ≥20 failed sign-ins from ≥2 foreign countries | Likely active credential-stuffing target. Reset password, disable SMTP AUTH, monitor. |
|
|
| P1 | Successful sign-in from non-US | Verify with user immediately. If not them: force password reset + revoke sessions + full breach check. |
|
|
| P2 | New OAuth consent to unfamiliar app in attack window | Review app publisher, scopes, and requesting user. Revoke if unknown. |
|
|
| P2 | B2B guest invite to personal email domain (gmail.com, outlook.com, yahoo.com) | Confirm with inviter it's intentional. Guest invites are a known persistence mechanism. |
|
|
| P3 | Transport rule created/modified by a non-admin | Transport rules can redirect mail tenant-wide. Review body/actions carefully. |
|
|
| P3 | Service principal added by non-admin or by "PowerApps Service" unexpectedly | Usually benign, but worth noting. |
|
|
| P4 | Isolated wrong-password attempt from foreign IP | Record and move on. Single attempts are noise unless repeated. |
|
|
|
|
## False positives to filter out
|
|
|
|
- `sysadmin@<tenant>` failures during onboarding (error 65001 against any **ComputerGuru** app — Security Investigator, Exchange Operator, User Manager, Tenant Admin, or Defender Add-on).
|
|
- `Microsoft Substrate Management` and `Azure MFA StrongAuthenticationService` routinely update user records — those are not attacker activity.
|
|
- Our own consent attempts show up as `Consent to application` in directory audits. Filter `sysadmin` + target matching any "ComputerGuru" app display name during the onboarding window.
|
|
- `error 50140` "Keep me signed in interrupt" is a browser prompt, not a failed auth.
|
|
|
|
## When to escalate beyond this tool
|
|
|
|
- Data exfiltration suspected -> pull Unified Audit Log via Purview (this tool does not access UAL).
|
|
- Tenant-wide phishing campaign -> enable Purview Content Search, quarantine messages.
|
|
- Domain-joined workstation compromise -> GuruRMM + Bitdefender workflow (see `clients/ace-portables/reports/` for past example).
|
|
- Attacker still active and exfiltrating -> consider disabling the user via the `remediate` subcommand and rotating the mailbox password at the same time.
|