Files
claudetools/clients/kittle/session-logs/2026-06/2026-06-08-mike-bec-incident-remediation.md
Mike Swanson 57e7251dbc sync: auto-sync from GURU-BEAST-ROG at 2026-06-08 16:23:44
Author: Mike Swanson
Machine: GURU-BEAST-ROG
Timestamp: 2026-06-08 16:23:44
2026-06-08 16:23:48 -07:00

262 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Session Log — Kittle BEC Incident Remediation
## User
- **User:** Mike Swanson (mike)
- **Machine:** GURU-BEAST-ROG
- **Role:** admin
---
## Session Summary
Full BEC (Business Email Compromise) investigation and remediation on kittlearizona.com tenant (ID: `3d073ebe-806a-4a5e-9035-3c7c4a264fc0`). Triggered by Howard receiving a phishing email that appeared to originate from Ken@kittlearizona.com. Mike had already manually blocked Ken's sign-in and set a temp password by the time investigation began.
Investigation used the ComputerGuru MSP app suite (Security Investigator for Graph reads, Exchange Operator for EXO reads/writes, Tenant Admin for directory and policy actions). Initial consent was obtained via admin consent URLs at the start of the session; additional consent URLs were provided and accepted mid-session for remaining app permissions.
The attacker accessed Ken's account via OWA starting at 13:24 UTC using IP 64.44.131.168 (Chicago, Nexeon Technologies — a VPN/hosting provider). They harvested contacts via python-httpx/0.28.1 from Azure IP 40.126.41.96 during 18:3618:53 UTC, then sent 1,000 phishing emails in 5 batches from 45.134.224.220 (Kansas City, PacketHub S.A.) between 21:1421:26 UTC. The phishing subject was "Ken Schagel shared a file with you" — a fake OneDrive file-share lure. 747 delivered, 227 failed/bounced, 740 victim notifications dispatched via EWS SOAP from admin@kittlearizona.com.
Remediation actions completed: Ken's sessions revoked and admin roles stripped (all 10); Wrex sessions revoked and password reset; 5 malicious inbox rules deleted across 3 mailboxes (Ken x2, Alexis x1, Accounting x2 — Accounting rules were actively suppressing ALL incoming mail at time of discovery, immediately restoring mail flow); Alexis PERFECTDATA and Alignable OAuth grants revoked; Lori's 10 admin roles (including Global Administrator) stripped and re-assigned User Administrator only (confirmed via directoryAudits that Lori's GA was pre-existing, not attacker-planted); victim notification sent to 740 filtered addresses; Syncro ticket #32393 updated with public comment containing temp passwords; breach report written to `clients/kittle/reports/2026-06-08-breach-check.md`; SharePoint confirmed clean; Security Defaults confirmed enabled; Ken's MFA verified clean (single iPhone 12 Pro Max, no attacker-registered devices).
---
## Key Decisions
- **EXO hidden rule sweep used Exchange Operator (not Security Investigator):** `Get-InboxRule -IncludeHidden:true` requires `Exchange.ManageAsApp` permission, which only the Exchange Operator app holds. Security Investigator has `full_access_as_app` (EWS), not the Exchange admin cmdlets tier. Switched on first 401.
- **Phishing send via EWS SOAP (not Graph SendMail):** 740-recipient victim notification sent using EWS SOAP from admin@kittlearizona.com. Graph SendMail would have required a delegated token or app-only send permission not available on this tenant. EWS worked with Exchange Operator EXO token. HTML body wrapped in `<![CDATA[...]]>` to prevent schema validation errors on `<br>` tags.
- **Lori's 10 admin roles stripped even though origin unknown:** At time of stripping, it was unknown whether roles were attacker-planted or pre-existing. Decision to strip all and re-assign legitimate scope afterward. Confirmed post-session via directoryAudits that roles were pre-existing (no "Add member to role" events in last 30 days from any non-ACG initiator). Re-assigned User Administrator as legitimate scope.
- **Victim notification filtered 7 automated/non-human addresses:** vzwpix, mms.att.net, Microsoft internal, streaming service addresses removed from the 747 delivered list before sending notifications. 740 addresses used.
- **Did not revoke Ken's MFA devices:** Ken's MFA verified clean — single iPhone 12 Pro Max, no attacker-registered devices. Advised Ken to verify at mysignins.microsoft.com himself; no forced MFA reset needed.
- **Used Search-UnifiedAuditLog (EXO REST) instead of Graph signIns:** Tenant is on O365 E3, which lacks Entra P1. Graph `/auditLogs/signIns` returns `Authentication_RequestFromNonPremiumTenantOrB2CTenant` 403. UAL via EXO REST is available without P1 and provided the full attack timeline.
- **Message trace used Get-MessageTraceV2:** `Get-MessageTrace` deprecated September 2025. Switched to `Get-MessageTraceV2` which returned full 1,000-record phishing campaign data.
- **PERFECTDATA OAuth revoked immediately, Alignable deferred then revoked:** PERFECTDATA was clearly malicious (Mail.ReadWrite, Files.ReadWrite scopes, unknown publisher). Alignable was initially deferred pending Alexis's input — later revoked at Mike's direction (offline_access + Contacts.Read, unverified publisher).
---
## Problems Encountered
- **EXO /adminapi/beta 401 with Security Investigator token:** `full_access_as_app` is an EWS permission, not the Exchange admin cmdlets tier. Fixed by switching to Exchange Operator token which holds `Exchange.ManageAsApp`. HTTP 200 after switch.
- **Remove-InboxRule JSON escaping error (400 "unrecognized escape sequence \4"):** The rule Identity string contains backslashes (e.g. `Ken\4160878082195980289`). Passing via shell variable without escaping caused malformed JSON. Fixed using `jq -n --arg identity "$IDENTITY"` to properly escape.
- **Remove-InboxRule "can't use Identity and Mailbox together":** Identity already contains mailbox prefix, so separate Mailbox parameter caused conflict. Fixed by removing Mailbox parameter from the payload.
- **EWS SOAP body schema error on HTML:** `<br>` tags in email body treated as XML elements, breaking SOAP schema validation. Fixed by wrapping body in `<![CDATA[...]]>`.
- **Sign-in logs 403 from all token tiers:** Tenant Admin lacked `AuditLog.Read.All` in manifest. Security Investigator has `AuditLog.Read.All` in roles but tenant returns `Authentication_RequestFromNonPremiumTenantOrB2CTenant`. O365 E3 does not include Entra P1 — sign-in log API requires P1. No fix available. Worked around via Search-UnifiedAuditLog (EXO REST) which does not require P1.
- **Get-MessageTrace deprecated:** Returned deprecation warning. Switched to Get-MessageTraceV2. Also removed PageSize parameter (invalid for V2).
- **directoryAudits `ne` operator not supported:** `activityDisplayName ne 'Remove member from role'` returned UnknownError. Workaround: fetch all RoleManagement events and filter via `jq` client-side.
- **UAL search returned 0 results for Lori role events:** EXO REST `Search-UnifiedAuditLog` with `Operations:Add member to role` returned empty for Lori. Resolved via Graph directoryAudits API (which did work with Security Investigator token after consent) — confirmed no role assignment events for Lori in 30 days, meaning roles were pre-existing.
---
## Configuration Changes
- **Created:** `vault/clients/kittle/m365-ken-schagel-incident.sops.yaml` — SOPS-encrypted vault entry for Ken's temp password and incident notes
- **Created:** `clients/kittle/reports/2026-06-08-breach-check.md` — Full breach incident report (attack timeline, attacker IPs, all remediation actions, open items)
- **Created:** `clients/kittle/session-logs/2026-06/2026-06-08-mike-bec-incident-remediation.md` — this file
---
## Credentials & Secrets
**Ken Schagel temp password:** `B/947405806521av`
- Vaulted at: `vault/clients/kittle/m365-ken-schagel-incident.sops.yaml`
- Communicated to Mike via Syncro ticket #32393 (public comment with temp passwords for Ken + Wrex)
- Ken's account re-enabled by Mike mid-session
**Wrex password reset:** `Kittle@1426Wrx!47E742`
- Communicated via Syncro ticket #32393
---
## Infrastructure & Servers
| Item | Value |
|------|-------|
| Tenant | kittlearizona.com |
| Tenant ID | `3d073ebe-806a-4a5e-9035-3c7c4a264fc0` |
| ACG MSP tenant ID | `ce61461e-81a0-4c84-bb4a-7b354a9a356d` |
| Syncro ticket | #32393 |
| Attacker IP 1 | 64.44.131.168 — OWA browser access, Chicago IL, AS20278 Nexeon Technologies (VPN/hosting) |
| Attacker IP 2 | 40.126.41.96 — Contact scraping via python-httpx, Microsoft Azure |
| Attacker IP 3 | 45.134.224.220 — Bulk phishing send, Kansas City MO, AS147049 PacketHub S.A. |
| Attacker tool | python-httpx/0.28.1, OAuth token for Microsoft Desktop app `d3590ed6-52b3-4102-aeff-aad2292ab01c` |
| Attacker AAD session | `0031c64a-94a8-7629-20ad-c42db69d76c7` |
| Compromise window | 13:2421:41 UTC 2026-06-08 |
### MSP App Credentials Used
| App | Client ID |
|-----|-----------|
| Security Investigator | `bfbc12a4-f0dd-4e12-b06d-997e7271e10c` |
| Exchange Operator | `b43e7342-5b4b-492f-890f-bb5a4f7f40e9` |
| User Manager | `64fac46b-8b44-41ad-93ee-7da03927576c` |
| Tenant Admin | `709e6eed-0711-4875-9c44-2d3518c47063` |
---
## Commands & Outputs
### Attack timeline (from UAL + message trace)
```
09:03 UTC Normal Outlook sync (Microsoft IPs) — pre-compromise
13:24 UTC [BREACH START] OWA login — 64.44.131.168 (Chicago, Nexeon VPN)
13:37 UTC Ken's T-Mobile phone (legitimate, unaware)
15:00 UTC Attacker returns — 64.44.131.168
15:17 UTC Ken sends legitimate email via Cox (Phoenix AZ)
15:32 UTC Attacker sends test email from OWA — concurrent with Ken
16:14 UTC Attacker sends second test email
18:36 UTC Contact harvest starts — python-httpx/0.28.1 from Azure 40.126.41.96
18:52 UTC Attacker reviews Sent/Deleted/RSS Feeds from OWA
18:53 UTC Contact harvest ends (250+ MailItemsAccessed events)
21:14 UTC Phishing batch 1: 17 recipients
21:16 UTC Phishing batch 2: 300 recipients
21:20 UTC Phishing batch 3: 300 recipients
21:23 UTC Phishing batch 4: 300 recipients
21:26 UTC Phishing batch 5: 83 recipients — from 45.134.224.220 (PacketHub)
21:27 UTC Ken's SSPR password reset attempt
~21:30 UTC Howard (ACG) receives phishing email — incident detected
21:41 UTC Mike manually blocks Ken sign-in in portal, sets temp password
~22:00 UTC ACG investigation and remediation begins
22:05 UTC ACG removes Lori's 10 admin roles (Tenant Admin app)
22:06 UTC Lori sessions revoked
```
### Malicious inbox rules deleted
```
Ken@kittlearizona.com "." Move ALL mail → RSS Feeds, MarkAsRead, StopProcessing [DELETED]
Ken@kittlearizona.com "Admin" Move ALL mail → RSS Feeds, MarkAsRead, StopProcessing [DELETED]
alexis@kittlearizona.com "..." Move ALL mail → RSS Feeds, MarkAsRead, StopProcessing [DELETED]
Accounting@kittlearizona.com ".." Move mail FROM Ken → RSS Feeds, Priority 1 [DELETED]
Accounting@kittlearizona.com "..." Move ALL mail → RSS Feeds, Priority 2 [DELETED]
```
Note: Accounting ".." + "..." were actively suppressing ALL incoming mail at time of discovery.
### Phishing campaign stats
```
Total sent: 1,000
Delivered: 747
Failed/bounced: 227
Pending: 25
Notifications sent: 740 (7 automated addresses filtered)
Subject: "Ken Schagel shared a file with you"
```
### OAuth grants revoked
```
PERFECTDATA app Mail.ReadWrite, Files.ReadWrite, offline_access [REVOKED]
Alignable app offline_access, User.Read, Contacts.Read [REVOKED]
Grant ID: jB3LklISEEOHpW2kH5IbQLz8wKqAnj1KmLeBzb1HLJrh6qF03cBERamPOhj4CXha
Client SP: 92cb1d8c-1252-4310-87a5-6da41f921b40
```
### Lori role changes
```
Stripped (all pre-existing): Global Administrator, Exchange Administrator, User Administrator,
Teams Administrator, SharePoint Administrator, Helpdesk Administrator, AI Administrator,
Global Reader, Service Support Administrator, User Experience Success Manager
Re-assigned: User Administrator (roleTemplateId: fe930be7-5e62-47db-91af-98c3a49a38b1)
Role object ID in tenant: 1321d5cd-17bb-40de-891b-1e85667e1c5a
Lori user ID: 5817629b-5832-43c6-b74c-86a05c29c852
```
### Key user IDs
```
Ken Schagel Ken@kittlearizona.com (admin roles stripped, re-enabled by Mike)
Lori Schagel Lori@kittlearizona.com ID: 5817629b-5832-43c6-b74c-86a05c29c852
Alexis alexis@kittlearizona.com ID: 74a1eae1-c0dd-4544-a98f-3a18f809785a
Wrex Wrex@kittlearizona.com (sessions revoked, password reset)
```
---
## Pending / Incomplete Tasks
1. **Christina Micek inbox rule on Ken**`StopProcessingRules:true`, no action, no filter. Unknown if legitimate or attacker-planted. Needs Ken to confirm. Delete if he doesn't recognize it.
2. **Re-add admin roles to Ken** — All 10 stripped during containment. Ken is Global Admin by function; re-add Global Administrator and Exchange Administrator once incident is declared closed and Ken's account is fully verified clean.
3. **Lori GA access review** — Confirmed pre-existing (not attacker-planted). Recommend discussing with Ken whether Lori legitimately needs any admin role at all. Downscoped to User Administrator for now.
4. **MFA cleanup** — Alexis has duplicate Authenticator registrations ("iPhone 12 Pro Max" x2). Lori has two Authenticator devices (SM-G975U + SM-F766U, likely old phone not removed). Users can self-serve at mysignins.microsoft.com or ACG can reset.
5. **Phishing URL unknown** — Email body purged when Ken's account was disabled. Send IP 45.134.224.220 (PacketHub S.A., AS147049) is known. Submit to threat intel if needed.
6. **Entra P1 licensing** — Sign-in logs blind without it. Tenant on O365 E3, not M365 E3. Recommend Entra P1 add-on or upgrade. Without P1, a Conditional Access policy for foreign IP blocking also cannot be enforced.
7. **DKIM/DMARC** — Not configured on kittlearizona.com. DMARC reject/quarantine would reduce future phishing deliverability from this domain.
8. **Alexis MFA duplicate** — One "iPhone 12 Pro Max" Authenticator entry is likely a stale registration. Should be cleaned up but is low priority now that PERFECTDATA and Alignable are revoked.
---
## Reference Information
- **Syncro ticket:** #32393 (public comment added with temp passwords for Ken + Wrex)
- **Breach report:** `clients/kittle/reports/2026-06-08-breach-check.md`
- **Vault entry:** `vault/clients/kittle/m365-ken-schagel-incident.sops.yaml`
- **Victim notification:** sent from admin@kittlearizona.com via EWS SOAP, 3 batches, 740 recipients
- **Attacker OAuth app (Microsoft Desktop):** `d3590ed6-52b3-4102-aeff-aad2292ab01c`
- **Attacker AAD session:** `0031c64a-94a8-7629-20ad-c42db69d76c7`
- **Security Defaults:** enabled (`isEnabled: true`) on this tenant
- **SharePoint:** clean — no attacker-created files, pages, or external sharing links
- **EXO REST endpoint:** `https://outlook.office365.com/adminapi/beta/{tenantId}/InvokeCommand`
- **EWS endpoint:** `https://outlook.office365.com/EWS/Exchange.asmx`
- **Graph directoryAudits:** confirmed working with Security Investigator token (no P1 needed for this endpoint)
- **Graph signIns:** blocked — requires Entra P1 (`Authentication_RequestFromNonPremiumTenantOrB2CTenant`)
---
## Update: 16:23 PT — Post-save follow-up actions
### Additional actions completed after initial save
**Alignable OAuth on Alexis — revoked:**
At Mike's direction, revoked the Alignable OAuth grant on alexis@kittlearizona.com.
- Grant ID: `jB3LklISEEOHpW2kH5IbQLz8wKqAnj1KmLeBzb1HLJrh6qF03cBERamPOhj4CXha`
- App SP client ID: `92cb1d8c-1252-4310-87a5-6da41f921b40`
- Scopes: `offline_access User.Read Contacts.Read`
- HTTP 204 [OK]
**Lori Schagel — downscoped to User Administrator:**
All 10 pre-existing admin roles had been stripped during containment. Re-assigned User Administrator only (confirmed pre-existing GA was unnecessary exposure, not attacker-planted).
- Lori user ID: `5817629b-5832-43c6-b74c-86a05c29c852`
- User Administrator role object ID: `1321d5cd-17bb-40de-891b-1e85667e1c5a`
- roleTemplateId: `fe930be7-5e62-47db-91af-98c3a49a38b1`
- HTTP 204 [OK]
**Lori role assignment timing — confirmed pre-existing:**
directoryAudits query (last 30 days, all RoleManagement events) returned only ACG-initiated removals. Zero "Add member to role" events from any other initiator in the 30-day window. Lori's GA was assigned more than 30 days before the incident — pre-existing, not attacker-planted. Breach report updated to reflect this finding.
**Victim notification confirmed sent:**
Mike asked explicitly — confirmed 740 emails sent via EWS SOAP from admin@kittlearizona.com in 3 batches. All NoError. 747 delivered by phishing campaign; 7 automated addresses filtered (vzwpix, att.net MMS, Microsoft internal, streaming service) before notification send.
**All consent links accepted by Mike** — confirmed all 5 MSP apps (Security Investigator, Exchange Operator, User Manager, Tenant Admin, Defender Add-on) have admin consent in Kittle tenant.
**Thread deletion failed:** Bot received HTTP 403 Missing Permissions attempting to delete Discord thread 1513652236444504197. Thread remains open.
### Breach report updates
`clients/kittle/reports/2026-06-08-breach-check.md` updated with:
- Lori role assignment confirmed pre-existing (not attacker-planted)
- Alignable OAuth revocation added to remediation table
- Lori User Administrator re-assignment added to remediation table
- Open items updated to reflect resolved items (Ken MFA clean, Lori role timing resolved)
- New open item: Lori GA access review (recommend discussing with Ken whether she needs any admin role)