From 2f0bc654a10347d5962ac0b4bbd477ed5c940873 Mon Sep 17 00:00:00 2001 From: Howard Enos Date: Mon, 20 Apr 2026 14:15:02 -0700 Subject: [PATCH] sync: auto-sync from ACG-TECH03L at 2026-04-20 14:15:01 Author: Howard Enos Machine: ACG-TECH03L Timestamp: 2026-04-20 14:15:01 --- .../scripts/user-breach-check.sh | 4 +- clients/cascades-tucson/PROJECT_STATE.md | 2 +- .../2026-04-20-eight-user-breach-check.md | 207 ++++++++++++++++++ 3 files changed, 210 insertions(+), 3 deletions(-) create mode 100644 clients/cascades-tucson/reports/2026-04-20-eight-user-breach-check.md diff --git a/.claude/skills/remediation-tool/scripts/user-breach-check.sh b/.claude/skills/remediation-tool/scripts/user-breach-check.sh index e28854b..bfdfeee 100644 --- a/.claude/skills/remediation-tool/scripts/user-breach-check.sh +++ b/.claude/skills/remediation-tool/scripts/user-breach-check.sh @@ -11,8 +11,8 @@ TENANT_INPUT="${1:?usage: user-breach-check.sh }" UPN="${2:?usage: user-breach-check.sh }" TENANT_ID=$("$SCRIPT_DIR/resolve-tenant.sh" "$TENANT_INPUT") -GT=$("$SCRIPT_DIR/get-token.sh" "$TENANT_ID" graph) -EXO=$("$SCRIPT_DIR/get-token.sh" "$TENANT_ID" exchange) || EXO="" +GT=$("$SCRIPT_DIR/get-token.sh" "$TENANT_ID" investigator) +EXO=$("$SCRIPT_DIR/get-token.sh" "$TENANT_ID" investigator-exo) || EXO="" USER_SLUG=$(echo "$UPN" | tr '@.' '__') OUT="/tmp/remediation-tool/$TENANT_ID/user-breach/$USER_SLUG" diff --git a/clients/cascades-tucson/PROJECT_STATE.md b/clients/cascades-tucson/PROJECT_STATE.md index 612da1d..e34c785 100644 --- a/clients/cascades-tucson/PROJECT_STATE.md +++ b/clients/cascades-tucson/PROJECT_STATE.md @@ -10,7 +10,7 @@ | Session | Working On | Status | Started | |---------|-----------|--------|---------| -| _(none active)_ | | | | +| ACG-TECH03L/Claude (Howard) | Intune Phase B-1: Android compliance policy | IN_PROGRESS | 19:15 UTC 2026-04-20 | **How to claim a lock:** Add a row before starting work. Remove it when done. Locks older than 2 hours with no update are considered stale. diff --git a/clients/cascades-tucson/reports/2026-04-20-eight-user-breach-check.md b/clients/cascades-tucson/reports/2026-04-20-eight-user-breach-check.md new file mode 100644 index 0000000..642b804 --- /dev/null +++ b/clients/cascades-tucson/reports/2026-04-20-eight-user-breach-check.md @@ -0,0 +1,207 @@ +# Cascades Tucson — 8-User Breach Check (Read-Only) + +**Date:** 2026-04-20 (UTC) +**Tenant:** Cascades Tucson (cascadestucson.com, `207fa277-e9d8-4eb7-ada1-1064d2221498`) +**Scope:** Read-only breach check across all 7 users targeted in Mike's 04-20 phishing sweep + JD Martin (named by Howard; previously a false-positive) +**App used:** Legacy `Claude-MSP-Access` Graph API app (`fabb3421-8b34-484b-bc17-e46de9703418`). New tiered `ComputerGuru Security Investigator` app vault files do not yet exist in `D:/vault/msp-tools/` — provision those before next run. +**Operator:** Howard Enos (ACG-TECH03L) +**Posture:** Investigate + document only. No remediation actions taken. + +--- + +## Per-User Verdicts + +| User | Verdict | Immediate action needed? | +|---|---|---| +| John Trozzi | CLEAN | No (re-confirms 04-20 AM check) | +| Megan Hiatt | CLEAN **but actively attacked via SMTP AUTH** | Yes — disable SMTP AUTH | +| Dax Howard | CLEAN, 1 disabled external-forward rule to verify | Clarify w/ Dax | +| Lois Lane | CLEAN | No | +| Meredith Kuhn | CLEAN, 1 dormant rule with attacker-signature name | Yes — delete `....` rule | +| Anna Pitzlin | Account **disabled/offboarded**; stale risky-user record | Low — clean up Identity Protection | +| Ann Dery | CLEAN **but no MFA, 0 recent sign-ins, stale risky-user record** | Yes — enroll MFA or disable | +| JD Martin | CLEAN | No (confirms false-positive exclusion from sweep) | + +**Bottom line:** No active compromise on any of the 8 mailboxes. Two dormant concerns to resolve (Meredith's `....` rule, Dax's disabled forward). Two account-hygiene gaps (Ann no-MFA, Anna stale offboarding state). One active attack vector that needs tenant-level control (SMTP AUTH credential stuffing against Megan). + +--- + +## 10-Point Check Matrix + +All checks per `.claude/skills/remediation-tool/references/checklist.md`. `[OK]` = within normal parameters, `[!]` = needs attention, `[?]` = ambiguous. + +| # | Check | John | Megan | Dax | Lois | Meredith | Anna | Ann | JD | +|---|---|---|---|---|---|---|---|---|---| +| 01 | Visible inbox rules (Graph) | 0 OK | 1 OK | 3 OK | 0 OK | 3 OK | 0 OK | 0 OK | 0 OK | +| 02 | Auto-reply | off | off | off | off | off | **alwaysEnabled** (legit offboarding) | off | off | +| 03a | Hidden inbox rules (EXO REST) | 1 system | 4 OK | **4 (1 flag)** | 1 system | **6 (1 flag)** | 3 system | 3 system | 1 system | +| 03b | Non-SELF mailbox permissions | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| 03c | Non-SELF SendAs | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| 03d | Mailbox forwarding fields | null | null | null | null | null | null | null | null | +| 04a | OAuth grants | 2 OK | 4 OK | 1 OK | 0 | 2 OK | 1 OK | 2 OK | 0 | +| 04b | App role assignments | 1 (BlueMail) | 3 (iOS/Alignable/Adobe) | 3 (SurveyMonkey/Zoom/CalendarBridge) | 0 | 2 (iOS/ReadMtg) | 1 (Template.net `[?]`) | 1 (BlueMail) | 0 | +| 05 | Auth methods | 5 (phone, Auth, FIDO2) | 2 (pw, Auth) | 2 (pw, Auth) | 2 (pw, Auth) | 2 (pw, Auth) | 1 (pw only) | **1 (pw only) [!]** | 2 (pw, Auth) | +| 06 | Interactive sign-ins 30d (non-US / legacy) | 12 / 0 / 0 | **122 / 106 / 108** | 0 / 0 / 0 | 11 / 0 / 0 | 0 / 0 / 0 | 0 / 0 / 0 | 0 / 0 / 0 | 0 / 0 / 0 | +| 07 | Directory audits 30d | 41 (our 04-16 reset) | 1 | 2 | 2 | 1 | 4 | 0 | 0 | +| 08 | Risky user / detections | none / 0 | none / 0 | none / 0 | none / 0 | none / 0 | **low/atRisk stale 2023-11** | **low/atRisk stale 2020-12** | none / 0 | +| 09 | Sent items recent 25 | normal | normal | normal | normal | normal | none post-disable | normal | normal | +| 10 | Deleted items recent 25 | normal | normal | normal | normal | normal | none post-disable | normal | normal | + +No MFA-challenge, password-reset, sign-in-alert, or bounce-notification messages found in any Deleted Items across the 8 accounts (would indicate attacker cleanup). All legitimate sign-ins are from US IPs — for those who signed in interactively during the 30-day window. + +--- + +## Detailed Findings + +### 1. John Trozzi — CLEAN (re-verified) + +Matches Mike's 04-20 AM breach check. 12 interactive sign-ins all US/Phoenix (`184.191.143.62`). 5 auth methods (phone, 2x Authenticator, FIDO2). 41 directory audits — all from our 04-16 remediation cycle (password reset, disable/re-enable). Phishing emails from 04-20 were deleted in the sweep. + +### 2. Megan Hiatt — CLEAN mailbox, ACTIVE credential-stuffing attack + +**Mailbox state:** No malicious rules, no forwarding, no non-SELF delegates. 14 successful sign-ins all from her two known US IPs (`184.191.143.62`, `72.211.21.217`) via Browser. + +**Active attack:** 108 `Authenticated SMTP` sign-in attempts over 30 days, geographically distributed: + +| Country | Attempts | Failure codes | +|---|---|---| +| GB (UK) | 48 | 50053 (smart lockout) | +| DE (Germany) | 30 | 50053 | +| NL (Netherlands) | 18 | 50053 | +| LT (Lithuania) | 6 | 50053 / 50126 (bad password) | +| CH (Switzerland) | 4 | 50053 | +| US | 2 | 50053 | + +Every single attempt failed. Smart lockout (50053) triggered repeatedly — Entra is correctly blocking. BUT: if the attacker ever guesses a correct password, SMTP AUTH **bypasses MFA** because it uses Basic Authentication. This is the highest-risk attack surface still exposed on this tenant. + +### 3. Dax Howard — CLEAN, dormant external-forward rule + +3 inbox rules total: +- **Two** "Arizona ALFA" rules forwarding newsletters from `info+azalfa.org@ccsend.com` (Constant Contact) to Meredith Kuhn — legitimate business. Duplicate (one is `(1)`) — consolidation opportunity, not a security issue. +- **One disabled** rule "Copy of which is a meeting invitation or update" forwarding meeting requests to `dax@megaloscapital.com`. Currently OFF. `megaloscapital.com` is Megalos Capital — likely Dax's personal/other-company email. Needs user confirmation. + +0 interactive sign-ins in 30d, auth methods include Authenticator but with `createdDateTime: null` (possible duplicate-entry pattern like John had). Authenticator creation date null is low-risk but worth cleaning up. + +### 4. Lois Lane — CLEAN + +No custom rules. 11 interactive sign-ins all US. 2 auth methods (password, Authenticator). No anomalies. + +### 5. Meredith Kuhn — CLEAN, DORMANT attacker-signature rule + +**Primary flag — rule named `....`:** +- Disabled (`Enabled: false`) +- Action: mark as read, move to `RSS Subscriptions`, stop processing more rules +- No `From` / `SubjectContainsWords` filter — applies to **everything** if re-enabled +- Owner: `meredith.kuhn` +- Priority: 3 + +This matches the textbook attacker-persistence pattern (short-or-blank name, silent move to obscure folder, stop further processing). **BUT it is disabled.** `Get-InboxRule` doesn't return creation date, so we can't confirm whether this was ever active or when it was turned off. Two possibilities: +- **(A)** Someone (Meredith, prior IT) found it and disabled it but didn't delete it. +- **(B)** Meredith created it herself and gave up on it — Outlook occasionally ships templates that can produce odd-named rules. + +Either way, leaving it in place is a latent risk: if her account is ever compromised, re-enabling it is one click away. **Recommend deleting it outright after confirming with Meredith she didn't create it.** + +Other 5 hidden rules: system defaults (Junk, 2 disabled OOF templates) + two disabled legitimate rules (`support@focushr.net`, `results@j2labs.com`). + +### 6. Anna Pitzlin — ACCOUNT DISABLED (offboarded) + +- `accountEnabled: false` +- `lastPasswordChangeDateTime: null` +- Auto-reply set to "We regret to inform you that Anna Pitzlin is no longer employed here. Please direct any future correspondence to Meredith Kuhn." (effective 04-20 18:00 UTC → 04-21 18:00 UTC; almost certainly configured then left indefinitely with a non-terminal schedule) +- Risky-user record: `low / atRisk`, last updated **2023-11-16** — this is stale. Identity Protection never cleared the signal after offboarding. + +Anna received 2 phishing emails in the 04-20 sweep because the account is still licensed and accepting inbound mail for the auto-reply. **Not a compromise vector** (no interactive auth possible, no MFA method configured, password disabled). The stale `atRisk` signal is noise. + +**Side issue:** Verify with Mike whether Anna should be converted to a shared mailbox (cheaper, no license) or fully deleted after the retention window expires. Keeping a disabled user account licensed just to run an auto-reply is not standard. + +### 7. Ann Dery — CLEAN mailbox, unused/unprotected account + +- `accountEnabled: true`, `lastPasswordChangeDateTime: null` — account never had a password changed (implying it predates the forced-change policy or was exempted) +- **Only 1 auth method: password.** No MFA, no Authenticator, no FIDO2. +- 0 interactive sign-ins in 30d. +- Risky-user: `low / atRisk`, last updated **2020-12-07** — 5+ year old stale signal. +- 2 OAuth grants to BlueMail (same as John) — likely from original device pairing, dormant. + +This is a dormant, enabled, non-MFA-protected account that received 2 phishing messages. If an attacker ever gets her password, there's no second factor to stop them. **Recommend Mike confirm whether Ann still uses this account:** +- If yes → enforce MFA enrollment +- If no → disable the account (don't delete — keep mailbox for historical access) + +### 8. JD Martin — CLEAN + +No custom rules, no forwarding, 0 non-SELF permissions, normal OAuth (none). Confirms JD was NOT targeted in the phishing campaign — his presence in the sweep was the false-positive HR-thread reply Mike correctly excluded. The HR thread from Ashley Jensen (`HRPYDBRUNFOC...xlsx`) was and remains legitimate internal payroll correspondence. + +--- + +## Why this keeps happening — root causes + +Howard's question was "what can we do to prevent this." The phishing is landing because four layers of defense are not fully engaged: + +| Gap | Impact | Fix | +|---|---|---| +| **DMARC is `p=none`** | Receiving servers (Microsoft) have no instruction to junk/reject mail that spoofs `cascadestucson.com`. SPF fails silently, mail lands. | Publish `p=quarantine pct=25` for 1 week → observe DMARC reports → `p=reject`. See `_dmarc.cascadestucson.com` TXT. | +| **SMTP AUTH still enabled** | Megan is being credential-stuffed daily across 5 countries. 108 attempts in 30d. An eventual guess bypasses MFA entirely. | `Set-TransportConfig -SmtpClientAuthenticationDisabled $true` (tenant-wide) + per-mailbox `Set-CASMailbox -SmtpClientAuthenticationDisabled $true`. Coordinate with any legacy scanners/MFPs on-site first. | +| **No tenant-wide anti-impersonation/anti-phish policy tuned for `cascadestucson.com`** | Lookalike-domain tricks (`zoom.nl` instead of `zoom.us`) and display-name spoofing get through. | Defender for Office 365 anti-phishing policy → add `cascadestucson.com` as protected domain + key users (Meredith, CEO/admin tier) as protected users. Requires Defender P1 or M365 Business Premium. | +| **No URL/IP blocklist from this campaign** | Same attacker infrastructure can hit again tomorrow on different users. | Exchange TABL: IP block `139.28.37.117`, `104.168.101.10`, `207.189.10.75`, `91.244.70.212`. URL block `zoom.nl`, `*.awstrack.me`. | + +**User-level hygiene also matters:** + +- **Ann Dery** — no MFA method at all. If her account is active, enroll MFA today. If inactive, disable. +- **Anna Pitzlin** — offboard cleanup: convert to shared mailbox or remove license. +- **Meredith Kuhn** — delete the dormant `....` inbox rule. +- **Dax Howard** — confirm the `dax@megaloscapital.com` external-forward rule is Dax's own, still disable/delete either way. +- **Megan, Meredith, Ann, Anna** — none have FIDO2 or hardware tokens. Authenticator-push is sufficient for most, but for Meredith (finance/admin role) consider FIDO2 like John has. + +--- + +## Prioritized Action List + +### P1 — Tenant-level prevention (highest leverage) + +1. **Publish DMARC `p=quarantine pct=25`** → 1 week observation → `p=reject`. Coordinate with Meredith and verify DKIM signing is healthy first. Blocks ~all external-hosting spoofs going forward. +2. **Disable SMTP Client Authentication tenant-wide.** Megan's active attack ends the moment this is off. Check first with Mike whether any on-site devices (copier, HR scanner) use SMTP AUTH to send — if so, migrate them to App Password / Modern Auth or SMTP relay. +3. **Add TABL IP blocks + URL blocks** from the 04-20 sweep (4 IPs + `zoom.nl` + `*.awstrack.me`). + +### P2 — User-level cleanup (read-only; ask before acting) + +4. **Delete Meredith's `....` inbox rule** after a 30-second confirmation with Meredith that she didn't create it. +5. **Enroll Ann Dery in MFA** (or disable account if she's no longer using it). +6. **Clarify Dax's `megaloscapital.com` forwarding** — delete the disabled rule regardless once confirmed benign. +7. **Offboarding tidy-up for Anna Pitzlin** — consider converting to shared mailbox; clear the stale `atRisk` signal. + +### P3 — Defensive posture + +8. **Defender for Office 365 anti-phishing policy** for `cascadestucson.com` (needs SKU confirmation — does Cascades have M365 Business Premium or E3+Defender?). +9. **Baseline sweep of remaining 38 mailboxes** not hit this month (per sweep report recommendation — attackers may cycle to fresh targets). +10. **Template.net OAuth grant** (Anna Pitzlin) — publisher not verified. Low severity because account is disabled, but review if that app pattern appears on any active accounts during a re-sweep. + +--- + +## Raw Artifacts + +All 8 users' raw JSON under: +``` +/tmp/remediation-tool/207fa277-e9d8-4eb7-ada1-1064d2221498/user-breach/{user}_cascadestucson_com/ +``` + +Files per user: +- `00_user.json` — profile +- `01_inbox_rules.json` — Graph visible rules +- `02_mbox_settings.json` — mailbox settings (auto-reply) +- `03a_hidden_rules.json` — EXO Get-InboxRule with `-IncludeHidden` +- `03b_mbox_perms.json` — Get-MailboxPermission +- `03c_recip_perms.json` — Get-RecipientPermission (SendAs) +- `03d_mailbox.json` — Get-Mailbox (forwarding fields) +- `04a_oauth.json` — oauth2PermissionGrants +- `04b_approles.json` — appRoleAssignments +- `05_auth_methods.json` — authentication/methods +- `06_signins.json` — 30d interactive sign-in log +- `07_audits.json` — 30d directoryAudits where user is target +- `08a_risky.json` — identityProtection/riskyUsers +- `08b_risk_det.json` — identityProtection/riskDetections +- `09_sent.json` — last 25 sentitems +- `10_deleted.json` — last 25 deleteditems + +## Tooling notes for next session + +- **Fixed in this session:** `user-breach-check.sh` referenced old tier names `graph`/`exchange`; updated to `investigator`/`investigator-exo` to match the rewritten `get-token.sh`. +- **Not fixed:** the new tiered app vault files (`computerguru-security-investigator.sops.yaml` et al) do not exist at `D:/vault/msp-tools/`. The skill's new 5-app architecture is not provisioned yet. This session fell back to inline curl calls using the legacy `Claude-MSP-Access` app. Mike should provision the new vault files before retiring the legacy app.