# Runbook: Incident response — suspected compromise of a consumer Google (Gmail) account > For qualified IT professionals, on systems they are authorized to administer. > Provided as-is, without warranty — verify it fits your environment. See LICENSE. **Applies to:** A **personal `@gmail.com` account** used for practice business at ``. **Not Google Workspace.** There is no Admin console, no Admin SDK, no GAM, no audit-log export, and no vendor phone support for this account type. Every recovery path is Google's automated self-service flow. **Goal:** Evict an attacker who holds a stolen **session cookie** (not just a password), preserve evidence while doing it, and hand a clean factual record to the people who make the legal calls. **Assume:** the mailbox contains PHI, a breach risk assessment may follow, and **this document may become evidence.** > [!IMPORTANT] > **This runbook is not a compliance determination.** > Nothing here decides whether a reportable breach occurred, whether notification is required, or what any deadline is. Those are legal determinations. Where this runbook reaches one, it tells you to **stop, document, and escalate** to the practice's compliance contact or counsel. Work the technical steps; do not opine on the legal ones — not in this document, not in email, not verbally to the client. > [!WARNING] > **This repo is public-read.** This file is a **template with placeholders only**. Do not fill it in here and do not commit incident particulars, real account names, phishing domains, hostnames, or timestamps to this repo. Clone it to the **private tier** (private repo or Bitwarden secure note) and work the filled-in copy there. See [CONTRIBUTING.md](CONTRIBUTING.md). --- ## Threat model — read this before you touch anything The reported initial vector is an **adversary-in-the-middle (AiTM) credential phishing kit** that used a `blob:` URI to render a spoofed Google sign-in page **locally in the victim's browser** (so there is no attacker URL in the address bar to recognize) and relayed the victim's input to an attacker-controlled browser session in real time. Three consequences drive the entire ordering of this runbook: | Fact | Consequence | |---|---| | The kit relays a **real** sign-in, so the attacker receives the **post-authentication session cookie**. | **2FA did not prevent this and will not evict it.** The attacker's session is already authenticated; a second factor is never re-prompted. | | A session cookie is a **bearer token** independent of the password. | **A password reset alone does not evict the attacker.** You must explicitly invalidate sessions. | | Session hijack looks identical, from the mailbox side, to an **infostealer** stealing cookies off an endpoint. | Treat the endpoint vector as **unruled-out** until Phase 4 clears it. If it was an infostealer, the password reset you just did was captured too. | **Corollary:** containment is not "change the password." It is "invalidate every credential and every persistence mechanism, in an order that doesn't lock you out first." ## Placeholders Fill from the private tier at run time. Never commit filled-in values. | Placeholder | Meaning | |---|---| | `` | Practice / site identifier | | `` | Operator working the incident (initials in log tables) | | `` | The compromised `@gmail.com` address | | `` | Your incident identifier, e.g. `IR-YYYYMMDD-01` | | `` | Evidence folder, e.g. `E:\IR\` — encrypted, off the affected endpoints | | `` | A workstation under investigation | | `` | Attacker domain(s) recovered from the phishing message | | `` | The practice's HIPAA/compliance contact (Privacy or Security Officer) | | `` | The practice's attorney / breach counsel | | `` | Practice owner / decision maker | --- # Preconditions and safety warnings — what NOT to do first Work this section before Phase 0. Every item here is something a well-meaning responder does reflexively and regrets. - [ ] **DO NOT sign out of devices, revoke sessions, or "sign out of all other sessions" yet.** > **Why:** a device somewhere may still hold a **live authenticated session** for `` — the client's phone, an old tablet, a browser profile on a workstation. If the attacker has already changed the password and the recovery email/phone, that live session may be **the only remaining path back into the account**, and it can be used to reset the password from inside. Revoking sessions destroys it and drops you into Google's automated recovery flow with an attacker-controlled recovery address. **Locate a live session first (Phase 1). Revoke in Phase 2, in order.** - [ ] **DO NOT let anyone "just try the password" repeatedly** or hand the account to a family member to poke at. Failed sign-ins and unfamiliar devices can add friction to a later recovery attempt. - [ ] **DO NOT power off, reimage, "clean up," or run a remediating antivirus scan on any suspect endpoint yet.** Phase 0 captures volatile state and Phase 4 reviews existing detection history. A remediation scan destroys the artifacts that establish scope. - Isolating an endpoint from the network is acceptable and often correct. **Isolate ≠ power off.** Prefer GravityZone network isolation or unplugging the cable over a shutdown, which discards memory and can trigger cleanup-on-shutdown behavior. - [ ] **DO NOT delete the phishing email.** It is the primary evidence of initial vector. Preserve it with full headers (Phase 0). - [ ] **DO NOT call any phone number found by searching for "Google support."** There is **no free-tier Google phone support for consumer accounts.** Search results and sponsored ads for Google support numbers are overwhelmingly **scam call centers** that specialize in exactly this moment. Google will never call about account security, and never asks for a password or a verification code by phone. ([Google — account security scam calls](https://support.google.com/faqs/answer/17170932?hl=en)) - [ ] **DO NOT change the recovery email or phone before reading the current values.** Record what is there first — an attacker-planted recovery address is evidence, and it is also the thing that will silently defeat your recovery attempt. - [ ] **DO NOT make any statement to the client about whether this is "a breach," whether it is reportable, or what any deadline is.** Say: *"I'm containing it and documenting it. The determination is a legal question for `` / ``."* - [ ] **DO NOT backdate, alter, or reconstruct any document, log, note, ticket, or timestamp — ever, for any reason, including "fixing" an obvious typo in a time.** > **Why:** this record may be evidence. An altered record can convert a defensible incident into an indefensible one, and the alteration is usually more damaging than whatever it concealed. If you got something wrong, **append a correction with the current timestamp** saying what was wrong and what is right. Never edit history. This applies to your notes, your invoices, your ticket system, and this file. - [ ] **Confirm authorization to act.** You are a business associate by function. Confirm with `` that you are authorized to lock the account, disconnect endpoints, and take systems offline, and **note the time and person who authorized it.** Do this by message so it is written. --- # Phase 0 — Evidence preservation **Estimated duration:** 20–40 minutes. **Exit criterion:** `` exists on encrypted storage, contains a hashed manifest, and everything below is either captured or explicitly recorded as "not available." Nothing in the account or on any endpoint has been changed yet. > **Why before containment:** containment overwrites the evidence. Google's "Recent security activity" shows a limited window and prunes; device lists change the moment you revoke; Gmail filters disappear when you delete them. Consumer Gmail has **no audit-log export** — screenshots and saved pages *are* the log. Capture is the only chance you get. ### 0.1 Set up the evidence container - [ ] Create `` on **encrypted** removable or server storage that is **not** one of the suspect endpoints. It will contain PHI-adjacent material and attacker artifacts; treat it as PHI. - [ ] Record the operator, the incident ID, and the clock offset of the machine you are capturing from: ```powershell # Run from the machine doing the capture. Records UTC, local, and clock skew. $dir = "" New-Item -ItemType Directory -Path $dir -Force | Out-Null @" Incident : Operator : Capture host : $env:COMPUTERNAME UTC now : $((Get-Date).ToUniversalTime().ToString('o')) Local now : $((Get-Date).ToString('o')) Time zone : $((Get-TimeZone).Id) w32tm status : $(w32tm /query /status 2>&1 | Out-String) "@ | Set-Content "$dir\CAPTURE-CONTEXT.txt" -Encoding UTF8 ``` > **Why the clock:** every timestamp you cite later is only as good as the clock that produced it. If the capture host's clock is skewed, record the skew now rather than discovering it during a reconstruction. ### 0.2 Capture the account state (before any change) Use **full-page screenshots** and, where possible, browser **"Save page as → Webpage, Complete"** or print-to-PDF. Include the URL bar and a visible clock in the capture where you can. - [ ] **Recent security activity** — Google Account > **Security** > **Recent security activity**. Capture every entry, expanded. This is your best proxy for a sign-in log. - [ ] **Your devices** — Google Account > **Security** > **Your devices** > **Manage all devices** ([myaccount.google.com/device-activity](https://myaccount.google.com/device-activity)). Capture **every** device, expanded to show last activity, location, and session detail. Note which you recognize. - [ ] **Third-party app access** — [myaccount.google.com/permissions](https://myaccount.google.com/permissions). Capture the full list **and each grant's detail page** (scopes + date granted). A grant dated during the compromise window is a finding. - [ ] **App passwords** — [myaccount.google.com/apppasswords](https://myaccount.google.com/apppasswords) (only present when 2-Step Verification is on). Capture names and creation dates. - [ ] **2-Step Verification settings** — [myaccount.google.com/signinoptions/two-step-verification](https://myaccount.google.com/signinoptions/two-step-verification). Capture enrolled methods, **including any phone number or authenticator you don't recognize**. - [ ] **Passkeys and security keys** — [myaccount.google.com/signinoptions/passkeys](https://myaccount.google.com/signinoptions/passkeys). An attacker-enrolled passkey is durable persistence and a high-signal finding. - [ ] **Recovery phone** — [myaccount.google.com/signinoptions/rescuephone](https://myaccount.google.com/signinoptions/rescuephone) and **recovery email** — [myaccount.google.com/recovery/email](https://myaccount.google.com/recovery/email). **Record the current values before changing them.** - [ ] **Gmail persistence surfaces** (capture, do not change yet) — Gmail > **Settings** (gear) > **See all settings**: - **Filters and Blocked Addresses** — capture the whole list. Also **export** it: *Filters and Blocked Addresses* > select all > **Export** → save the XML to ``. This is the one native export you get; take it. - **Forwarding and POP/IMAP** — forwarding addresses and their verification state, POP status, IMAP status. - **Accounts and Import** — **Send mail as** entries, **Grant access to your account** (delegation), **Check mail from other accounts**. - **General** > **Vacation responder / Automatic reply**, and **Signature** (attackers edit signatures to insert payment-redirect language). - [ ] **Gmail last account activity** — bottom of the Gmail inbox, the **Details** link under "Last account activity." Capture the full table (IP, access type, time). On consumer Gmail this is often the **only** IP-level evidence available. Capture it before session revocation changes it. - [ ] Note the **compromise window** as currently understood: earliest suspicious indicator → now, in **UTC and local**. Mark it explicitly as *provisional*. > **Flagged uncertainty:** Google changes these UI paths and labels without notice. The `myaccount.google.com/...` deep links above are the durable part; the menu wording drifts. If a path doesn't match, navigate from **[myaccount.google.com](https://myaccount.google.com) > Security** and **record the path you actually used** in the decision log rather than guessing or silently substituting. ### 0.3 Capture the initial vector - [ ] Preserve the phishing message **with full headers**. In Gmail: open the message > **⋮ (More)** > **Show original** > **Download Original** (`.eml`) → ``. Also **Copy to clipboard** the raw source into a `.txt`. - [ ] Record `` — every domain and URL in the message, and the domain the `blob:` page relayed to if recoverable from browser history. **Write them defanged** (`hxxps://evil[.]example`) in notes so nobody clicks them later. - [ ] Ask the user, and write down verbatim: what they clicked, when (their best estimate, in local time), **what they typed**, whether they approved a 2FA prompt or entered a code, and whether they saw anything unusual afterward. Record it as *user-reported*, not as fact. - [ ] Determine whether the same message went to **other users** at the practice. If yes, each recipient is a separate potential victim — enumerate them now; they feed Phase 4. ### 0.4 Seal the capture - [ ] Hash everything and write a manifest. Do this **before** you add anything else to the folder, and repeat (as a new manifest file) after each later capture: ```powershell $dir = "" $stamp = (Get-Date).ToUniversalTime().ToString('yyyyMMddTHHmmssZ') Get-ChildItem $dir -Recurse -File | Where-Object { $_.Name -notlike 'MANIFEST-*' } | Get-FileHash -Algorithm SHA256 | Select-Object Hash, @{n='File';e={$_.Path.Replace($dir,'')}}, @{n='Bytes';e={(Get-Item $_.Path).Length}} | Sort-Object File | Export-Csv "$dir\MANIFEST-$stamp.csv" -NoTypeInformation -Encoding UTF8 ``` - [ ] Record in the decision log: capture start/end in **UTC and local**, operator, manifest filename, and the SHA-256 of the manifest itself. - [ ] **Never modify a file already in ``.** Additional captures go in as **new** files with new timestamps. --- # Phase 1 — Access triage **Estimated duration:** 15 minutes (Branch A) to several days, wall-clock (Branch B). **Exit criterion:** you have either (A) an authenticated session you control and a password you set, or (B) a documented, in-progress recovery attempt with the attempt times recorded — and you have chosen a branch deliberately rather than by accident. ## The decision ``` Is ANY device anywhere still signed in to ? (client's phone, spouse's tablet, an old browser profile, a signed-in Chrome profile on a workstation, the Gmail app on a retired device) │ ├── YES ──> BRANCH A. Do not touch that device's session. │ Use it to reset the password. Go to 1.A. │ └── NO / unsure ──> Verify before concluding "no". Go to 1.B. ``` ### 1.0 Find a live session before concluding there isn't one - [ ] Check the client's **primary phone** — Gmail app, YouTube app, Google Photos, Play Store. Any signed-in Google app implies a live token. - [ ] Check **every** workstation for a signed-in Chrome profile using `` (Chrome > profile avatar). A stale profile on a back-office PC is a common survivor. - [ ] Check tablets, a home computer, a retired phone in a drawer, a smart TV. - [ ] **Do not sign out of anything you find. Do not "refresh" it. Do not clear cookies.** - [ ] If found, **put that device in airplane mode / offline only if you must move it**, and get to it physically before doing anything else. ## Branch A — a live session exists **Fastest and by far the best outcome.** The live session is your credential of record; treat it as fragile. - [ ] From the live session, go to [myaccount.google.com/signinoptions/password](https://myaccount.google.com/signinoptions/password) and **set a new strong password**, generated by and stored in the password manager. Do this **from the live session**, not from a fresh sign-in. - [ ] Record the time (UTC + local) of the password change. - [ ] Confirm you can now sign in **on your own clean machine** with the new password. Keep the original live session untouched until that confirmation succeeds. - [ ] **Now proceed to Phase 2 and follow it in order.** Do not revoke sessions from inside Branch A until Phase 2 tells you to — you still need the account to be reachable if a step goes wrong. - [ ] If the password change is rejected or the session dies mid-flow, you have fallen into Branch B. Document the transition and its time. ## Branch B — no live session; account recovery required Consumer account recovery is **entirely automated**. There is no human to appeal to, no ticket, no escalation path. Success depends on presenting Google with enough signals that you are the legitimate owner. Optimize for those signals deliberately — a careless attempt is not free, because a pattern of failed attempts from unfamiliar contexts makes later attempts harder. **Set the conditions before you start:** - [ ] Attempt from a **device the account was previously used on** — the client's own laptop or phone, not your technician machine. - [ ] Use the **browser they normally used** (Chrome vs Safari matters), with their normal profile if it exists. - [ ] Attempt from the **network they normally sign in from** — the practice LAN or their home, **not** your hotspot, not a VPN, not a cellular tether. ([Google — tips to complete account recovery steps](https://support.google.com/accounts/answer/7299973?hl=en)) - [ ] Attempt at a **normal time of day** for that user. **Run the attempt:** - [ ] Start at [accounts.google.com/signin/recovery](https://accounts.google.com/signin/recovery). - [ ] **Answer every prompt. Do not skip.** Google's own guidance is that skipping hurts and a wrong guess does not eject you from the flow — a best guess beats a skip. - [ ] When asked for **the last password you remember**, give the most recent one you can, even if unsure. Older-but-certain beats recent-but-wrong. Check the password manager's **password history** for prior values. - [ ] Watch case and typos in every answer. - [ ] Provide the **account creation month/year** if asked; check the password manager entry's creation date or the oldest mail in the mailbox for a hint if you have any read access. - [ ] **Check the prior recovery email inbox and the prior recovery phone's SMS** for Google security notifications ("Your password was changed," "Recovery email changed," "New sign-in"). These notifications commonly include a **link to revert the change or secure the account** — that link can be the fastest route back in and it **expires**, so check immediately and check spam. > **Flagged uncertainty:** the presence, wording, and validity window of a revert link varies by change type and by how long ago it happened. Treat it as "check, it may be there," not "there will be one." - [ ] Record **every** attempt: timestamp (UTC + local), device, browser, network, and the exact rejection message. **If recovery fails:** - [ ] Retry after a delay from an even more familiar device/network combination. Repeated attempts are permitted. - [ ] Note Google's documented lag: **changes to account recovery info can take up to 7 days to take effect**, and recovery attempts may need to be retried after a few days. If the attacker changed recovery info, this cuts both ways — it may also delay *their* lock-in. ([Google — recover your account](https://support.google.com/accounts/answer/7682439?hl=en)) - [ ] **If the account has an active Google One subscription, use Google One support** — [one.google.com/support](https://one.google.com/support) — which offers **chat, email, and callback** to members. This is the only legitimate live human support channel available to a consumer account, and it is **subscription-gated**. Verify the subscription is on `` itself. > If `` has no Google One subscription, **subscribing now is a legitimate, cheap option worth considering** to open a support channel. Flag it as an option to ``; do not expect it to guarantee account recovery — Google One support cannot override the automated recovery decision, but it can advise. - [ ] **There is no free-tier Google phone support.** If you find a "Google support number," it is a scam. See the preconditions. Do not call it, and tell the client not to. **If recovery ultimately fails — stop and escalate:** - [ ] Document the failure completely: every attempt, every timestamp, the final state. - [ ] **A permanently attacker-controlled mailbox containing PHI is a materially different situation from one you regained control of.** Do not characterize it. **Escalate to `` and `` immediately**, in writing, with the factual record. - [ ] Continue with **Phase 3 (blast radius)** and **Phase 4 (endpoints)** regardless — losing the mailbox makes the downstream account work *more* urgent, not less, because the attacker holds the password-reset channel for every service registered to ``. --- # Phase 2 — Containment **Estimated duration:** 45–90 minutes. **Exit criterion:** every session, grant, app password, and Gmail persistence mechanism has been enumerated and either verified-legitimate or removed; a phishing-resistant factor is enrolled; and you have re-checked the Gmail settings **after** the password reset and found them unchanged. **Follow this order exactly. Each step exists because the previous one made it safe or effective.** ### Why the order is what it is | # | Step | Why here | |---|---|---| | 1 | Revoke sessions/devices | The stolen **cookie** is the live access. Nothing else you do matters while it works. | | 2 | Revoke OAuth grants | A third-party grant is a **token that survives session revocation and password reset**. Revoking after the password looks tidy but leaves a door open in the interim. | | 3 | Revoke app passwords | Same reason — an app password is a standing credential that **ignores 2FA entirely**. | | 4 | Reset password | **Only now.** See below. | | 5 | Enroll phishing-resistant 2FA | Prevents the *same attack* from working on the *new* password. Must come after the reset so the reset can't be done with a weak factor. | | 6 | Gmail persistence sweep | Do it last **and repeat it**, because sweeping before eviction just tells the still-connected attacker you're onto them and lets them re-plant. | > ### Why password reset is step 4, not step 1 > Resetting the password first is the reflex, and it is wrong here for three reasons: > 1. **It doesn't evict the attacker.** They hold a session cookie. Session cookies are bearer tokens that remain valid after a password change until the session is explicitly invalidated. You would feel finished while the attacker still reads the mailbox. > 2. **It tips them off while they still have access.** A password-change notification lands in a mailbox the attacker is watching. The predictable response is to burn the access loudly — mass-forward, exfiltrate, change recovery info, lock you out — *before* you've removed the other doors (OAuth grants, app passwords) that would have survived anyway. > 3. **It can lock you out.** In Branch A the live session is your only access; a reset flow that forces re-authentication on an untrusted device can strand you. > > Revoke access first, close the standing-credential doors, **then** change the password so the attacker's rediscovery attempt fails at every entrance simultaneously. > > **Exception:** if you have direct evidence of **active exfiltration in progress** (mail being sent right now, files being downloaded right now), speed beats sequence — reset immediately, then work steps 1–3 and 5–6. Record that you deviated, and why, in the decision log. ### 2.1 Revoke active sessions and devices - [ ] Google Account > **Security** > **Your devices** > **Manage all devices** ([myaccount.google.com/device-activity](https://myaccount.google.com/device-activity)). - [ ] For each device you do **not** recognize (and each you cannot positively attribute to a person and a physical device): open it and select **Sign out**. - [ ] Sign out **stale but legitimate** devices too — a retired phone with a live token is an unmanaged credential. - [ ] Keep exactly one device signed in: the one you are working from. Sign the rest out. - [ ] Re-capture the device list to `` after the revocation, as a **new** timestamped file. ### 2.2 Revoke third-party OAuth grants - [ ] Go to [myaccount.google.com/permissions](https://myaccount.google.com/permissions) ("Your connections to third-party apps & services" / "Apps with access to your account" — wording varies). - [ ] For **every** entry: if it is not positively identified as a business-necessary integration the practice knowingly authorized, **Remove access**. > **Why aggressive:** an OAuth refresh token grants mailbox access **independent of the password and independent of 2FA**, and it is the single most common way an attacker retains access after a "successful" cleanup. A wrongly-removed legitimate app costs one re-authorization; a missed malicious grant costs the whole incident. - [ ] Pay particular attention to anything granting **Gmail read/send** or **Drive** scopes, and anything granted **during the compromise window**. - [ ] Record each removal (name, scopes, date granted) in the decision log **before** removing it. ### 2.3 Revoke app passwords - [ ] Go to [myaccount.google.com/apppasswords](https://myaccount.google.com/apppasswords). - [ ] **Revoke all of them.** Re-create only what is provably needed, after the incident, one at a time. > **Why all:** an app password is a 16-character standing credential that **bypasses 2-Step Verification by design**. You cannot tell a legitimate one from an attacker-created one by looking at it. Revoking is cheap; the affected device simply prompts again. - [ ] Note that legacy mail clients, scanners, and copier scan-to-email may break here. Expect it, and be ready to re-provision — that is the correct trade. ### 2.4 Reset the password - [ ] [myaccount.google.com/signinoptions/password](https://myaccount.google.com/signinoptions/password). - [ ] Use a **password-manager-generated** password, unique, never used anywhere else, stored only in the password manager. - [ ] **Do not reuse any element** of the old password. Assume the old one is public. - [ ] If prompted, take the option to **sign out of other sessions**. Confirm it applied by re-checking the device list. - [ ] Record the time (UTC + local). ### 2.5 Enroll phishing-resistant 2FA - [ ] **Preferred: a passkey** — [myaccount.google.com/signinoptions/passkeys](https://myaccount.google.com/signinoptions/passkeys). Bind it to a device the practice controls (the owner's phone with biometrics, or a hardware security key). - [ ] **Equally good: a FIDO2 hardware security key.** For a practice account, enroll **two** keys and store the backup in the safe — losing the only key on a consumer account means re-entering the recovery flow you just escaped. > **Why phishing-resistant specifically:** passkeys and security keys are **origin-bound**. The AiTM kit works by relaying credentials from a page the user believes is Google; an origin-bound credential will not release to the attacker's origin, so the relay breaks. **SMS codes, TOTP codes, and Google prompts do not stop this attack** — the kit relays them in real time. Re-enrolling the same weak factor leaves you exposed to a repeat of the exact incident you are cleaning up. - [ ] Verify 2-Step Verification is on: [myaccount.google.com/signinoptions/two-step-verification](https://myaccount.google.com/signinoptions/two-step-verification). - [ ] **Remove any 2FA method you do not recognize** — an unfamiliar phone number, an unknown authenticator, an attacker-enrolled passkey. Capture it first. - [ ] Regenerate **backup codes**, invalidating the old set (the attacker may hold them). Store in the password manager, not on paper at the front desk. ### 2.6 Gmail persistence sweep **Do this after eviction, and then do it again 24 hours later.** Filters are the most commonly missed persistence and the most damaging: a filter that auto-deletes and auto-forwards keeps the attacker reading mail — including password-reset mail — long after "the account is secured," and the user never sees a thing. Gmail > **Settings** (gear) > **See all settings**: - [ ] **Filters and Blocked Addresses** — review **every** filter. Delete any not created by the user. Scrutinize especially: - filters with a **Forward to** action → active exfiltration - filters that **Delete it** → hiding security notifications and reset emails - filters that **Mark as read** / **Skip the Inbox (Archive it)** → hiding activity in plain sight - filters keyed on words like *password, security, verify, invoice, payment, bank, remittance, wire, ACH, statement, claim* - filters with **no criteria** or absurdly broad criteria - [ ] **Forwarding and POP/IMAP**: - Remove **every** forwarding address you cannot attribute. Note that a forwarding address requires confirmation — a **pending/unconfirmed** entry is still a finding. - **Disable POP.** **Disable IMAP** unless a specific, identified, still-needed client requires it. IMAP with an app password is silent, complete mailbox access. - [ ] **Accounts and Import**: - **Grant access to your account** (delegation) — remove **every** delegate that is not explicitly authorized. Delegation lets another Google account read and send as this mailbox with no password at all. - **Send mail as** — remove any address that isn't the user's. An attacker alias here enables convincing fraud from the real mailbox. - **Check mail from other accounts** — remove anything unrecognized. - [ ] **General** > **Vacation responder** — off unless intentional (auto-responders leak and confirm liveness). - [ ] **General** > **Signature** — confirm unaltered; attackers insert changed remittance/payment details. - [ ] **Recovery email** ([myaccount.google.com/recovery/email](https://myaccount.google.com/recovery/email)) and **recovery phone** ([myaccount.google.com/signinoptions/rescuephone](https://myaccount.google.com/signinoptions/rescuephone)) — set both to addresses/numbers the practice controls **now**. Remove attacker-planted values. - [ ] **Alternate email addresses** on the account profile — remove anything unrecognized. - [ ] Run Google's own **Security Checkup** ([myaccount.google.com/security-checkup](https://myaccount.google.com/security-checkup)) as a backstop and capture the result. It is a useful second pass, **not** a substitute for the manual sweep above — it does not surface every filter or delegation issue. - [ ] **Re-run this entire sweep 24 hours later** and record the result either way. Re-appearance of any removed item means the attacker still has access — **return to 2.1 and treat the eviction as failed.** --- # Phase 3 — Blast radius **Estimated duration:** 3–8 hours, plus follow-up over several days. **Exit criterion:** every downstream account reachable via `` has been enumerated and prioritized; the top-priority tier is secured; a written inventory of what the mailbox exposed exists and has gone to ``. > **Why this phase is not optional and not last:** the mailbox is not the prize. It is the **master key**. Every service that will email a password reset to `` was compromised the moment the mailbox was, whether or not the attacker used it yet. ### 3.1 Determine what the attacker saw and did - [ ] **Sent** folder — any mail the user didn't send. Attackers send from real mailboxes for fraud and for spreading the same phish to the contact list. - [ ] **Trash** — attackers delete their sent mail and the security notifications. Review before Gmail's ~30-day auto-purge. Capture, then restore items to preserve them. - [ ] **Spam** — for hidden security notifications. - [ ] **All Mail** — catches messages archived out of the inbox by a filter you have now deleted. - [ ] **Drafts** — staged fraud messages. - [ ] Search for exfiltration-shaped activity, and capture the result counts for the record: ``` in:anywhere after:YYYY/MM/DD has:attachment in:sent after:YYYY/MM/DD in:trash after:YYYY/MM/DD in:anywhere after:YYYY/MM/DD subject:(password OR verify OR "reset your" OR "security alert" OR "new sign-in") ``` - [ ] **Assess the PHI exposure factually:** what categories of protected health information were reachable in the mailbox and attachments (patient names, DOB, treatment, insurance, SSN, imaging), and roughly how many individuals. **Describe; do not conclude.** Whether this constitutes a reportable breach is ``'s determination, not yours. ### 3.2 Downstream accounts — work in this priority order The ordering is deliberate: it runs from *irreversible and account-fatal* to *recoverable*. - [ ] **1. Domain registrar and DNS** — **first, before anything else.** > **Why first:** losing the domain loses the practice's email and web presence **and every account that depends on domain-verified email**, and registrar transfers are slow, adversarial, and sometimes irreversible. It is the only item on this list that can put the practice permanently out of reach of its own identity. - Change password, enable phishing-resistant 2FA, verify **registrar-lock / transfer-lock is on**, verify the registrant/admin **contact email** is not attacker-controlled, review **DNS records** (especially MX, SPF, DKIM, DMARC) for changes. - [ ] **2. Banking and financial** — practice operating accounts, business credit cards, any personal accounts sharing the address. Change credentials, enroll strong 2FA, **call the bank on a number from the back of the card** (never a number from an email), request review of pending transfers and payees. - [ ] **3. Merchant services / payment processing** — card-present and card-not-present processors, patient payment portals. Verify **deposit/settlement bank account details are unchanged** — silently changing the payout account is the standard monetization. - [ ] **4. Payroll and HR** — direct deposit destinations are a primary target. - [ ] **5. Practice management and imaging vendors** — Open Dental support portal, imaging vendor portals, any vendor remote-support account. Verify no new support-access sessions or added users. - [ ] **6. Insurance and claims portals** — clearinghouse, individual payer portals, eligibility services. These hold PHI directly and are attractive for fraudulent claims. - [ ] **7. State licensing and regulatory** — dental board, DEA registration, state prescription monitoring, CMS/NPPES (an altered NPPES record redirects payments). - [ ] **8. Everything else** — Amazon, supply vendors, utilities, phone/ISP, social, review sites. For **each** account, in this order: **check for attacker-added recovery addresses and MFA methods first**, then change the password, then enroll strong 2FA, then review recent activity for unauthorized changes. > **Why recovery-first:** changing the password while an attacker-planted recovery address remains just hands them the reset link for the password you set. ### 3.3 Password reuse - [ ] Identify every account sharing the Gmail password or a variant. **All are compromised.** If a password manager is in use, run its reuse/breach report. - [ ] If an **infostealer** is confirmed in Phase 4, this expands drastically: **every credential saved in that browser profile is burned**, whether or not it was reused. See Phase 4. - [ ] If the practice does not use a password manager, this incident is the argument for deploying one. Note it as a post-incident recommendation, not an incident step. ### 3.4 Google Drive and other Google services - [ ] **Drive** — review contents for PHI and practice documents. Check [drive.google.com](https://drive.google.com) > **Shared with me** and, for owned files, **Manage access** on anything sensitive. Look for **new sharing links** ("Anyone with the link"), new editors, and files copied out. - [ ] Check **Drive activity** for mass downloads or bulk sharing during the compromise window. - [ ] **Google Photos, Contacts, Calendar** — Photos frequently holds photographed documents; Contacts is the phishing target list; Calendar can hold patient names and reasons for visit. - [ ] **Google Pay / saved payment methods** — review for added cards or changed details. - [ ] **Chrome sync** — if the account was signed into Chrome with sync on, the attacker may have obtained **synced saved passwords, bookmarks, and history**. Check [passwords.google.com](https://passwords.google.com) for what was stored. Treat every stored credential as exposed. ### 3.5 Contact notification - [ ] Identify who received attacker mail from `` (from Sent/Trash, before it was cleaned). - [ ] Notify those contacts that mail from `` during the window may be fraudulent, **with a factual, non-speculative message**. Send it from a **different, verified channel** — not the compromised mailbox. - [ ] **Do not send any notification to patients, and do not make any statement characterizing this as a breach, without `` / `` sign-off.** Patient-facing notification is a regulated act with defined content requirements. **Stop and escalate** — this is a hard boundary in this runbook. - [ ] Warn contacts explicitly if any attacker mail requested a payment, a wire, or changed banking details. --- # Phase 4 — Endpoint investigation **Estimated duration:** 2–4 hours per endpoint. **Exit criterion:** every endpoint that could have handled the phish or the account has been triaged; the infostealer hypothesis is either confirmed (→ reimage) or documented as not-supported-by-evidence; GravityZone policy has been verified as actually protecting, not just installed. > **Why endpoints matter even though this looks like pure phishing:** an AiTM session theft and an infostealer produce **identical mailbox-side symptoms**. If it was an infostealer, the account cleanup you just completed is worthless — the new password went into the same stealer. You cannot skip this. ### 4.1 Scope: which endpoints? - [ ] The endpoint where the phish was clicked (from user report and Phase 4.7 network logs). - [ ] Every endpoint where `` was ever signed into a browser. - [ ] Every endpoint belonging to any other recipient of the same phishing message. - [ ] Any endpoint sharing credentials or a browser profile with the above. ### 4.2 GravityZone: review history BEFORE you scan **Look at what the console already knows before you generate new noise.** - [ ] In **GravityZone Control Center**, review for the compromise window and the preceding 90 days: - **Incidents / Detections** — anything on ``, including items marked resolved or blocked. A *blocked* detection still proves the endpoint was targeted and reached. - **Quarantine** — the quarantine list, with original file paths and detection times. **Do not empty quarantine.** Quarantined items are evidence. - **Reports** — Malware Status, Blocked Websites, Blocked Applications, Network Incidents for the affected endpoints. - **Events / notifications** — module-disabled events, policy-change events, uninstall or tamper-protection events. - [ ] Note any **gap**: an endpoint that stopped reporting, an agent that went offline, or a period with no telemetry. A silent agent is a finding, not an absence of findings. - [ ] Export these views to `` **before** running new scans. > **Why before:** a new scan writes new events that push older detections out of default retention windows and out of the first page of every view. Capture history first. ### 4.3 GravityZone: verify the policy actually protects An installed agent with modules disabled is a false sense of safety. Check the **policy actually applied to the endpoint**, not the default policy. - [ ] Confirm these are **on** in the applied policy: - **Antimalware** — On-Access scanning, and On-Demand scanning configured - **Advanced Threat Control (ATC)** — behavioral detection; set to block, not just report - **Network Attack Defense** - **Web traffic scanning** / Web Protection — including **anti-phishing** and **scan SSL/HTTPS traffic**, without which a phishing page over TLS is invisible to the agent - **Ransomware Mitigation**, **HyperDetect** (if licensed), **Device Control**, **Firewall** as applicable - [ ] **Audit the exclusions list.** Enumerate every path, process, and hash exclusion in the applied policy. Ask of each: who added it, when, and why. A broad exclusion (`C:\`, `%TEMP%`, `*.exe`, an entire user profile) is either a legacy mistake or attacker tampering — **either way it is a finding.** > **Why exclusions specifically:** overly broad exclusions are the single most common reason a fully-licensed EDR misses an infostealer. They are also a known attacker action. - [ ] Confirm **tamper protection / uninstall password** is enabled and the agent version is current. - [ ] Record any change you make to policy, with time and reason. > **Flagged uncertainty:** GravityZone module names and console navigation vary across versions and between GravityZone Business Security / Business Security Premium / Enterprise. Verify names in your console rather than assuming the labels above; record what you actually found. ### 4.4 Scans - [ ] Run a **Full Scan** from GravityZone — **not** a Quick Scan. > **Why full:** Quick Scan covers common infection points and running processes. Infostealer remnants, dropped archives, staged exfil data, and dormant persistence live outside that set. - [ ] **Second-opinion scanning** — no single engine is sufficient, and an on-box engine may already be subverted. Use at least one, ideally from outside the running OS: - **Malwarebytes** (free on-demand scanner) - **ESET Online Scanner** - **Microsoft Safety Scanner** (`MSERT`) — standalone, expires after 10 days, always re-download - **Bitdefender Rescue Environment** — boots outside Windows; the strongest option, because a rootkit or a stealer with kernel-level persistence can hide from anything running inside the OS - [ ] **Do not use Kaspersky tooling** (including the Kaspersky Rescue Disk, KVRT, or Kaspersky Free) — US distribution and use restrictions apply. Excluded deliberately; do not "helpfully" substitute it back in. - [ ] Running two real-time AV products simultaneously causes conflicts — the second-opinion tools above are **on-demand or boot-time**, which is why they're the ones listed. ### 4.5 Manual persistence hunting Automated scanning misses tailored and living-off-the-land persistence. Hunt manually. **Sysinternals Autoruns** (`autoruns64.exe`, run as administrator): - [ ] **Options > Scan Options > Check VirusTotal.com** — enable. Optionally **Submit Unknown Images**. > Submitting an unknown binary uploads it to a third party. On a healthcare endpoint, **do not submit** anything that could be a document or contain PHI — submit hashes only, and prefer reviewing the hash-lookup result rather than uploading files. - [ ] **Options > Hide Microsoft Entries** (and Hide Windows Entries) — collapses thousands of signed OS entries so anomalies surface. - [ ] Work these tabs: **Logon**, **Scheduled Tasks**, **Services**, **Drivers**, **Winlogon**, **Explorer**, **Image Hijacks**, **AppInit**, **KnownDLLs**, **Office**. - [ ] Investigate: unsigned entries; VirusTotal hits; entries in `%APPDATA%`, `%LOCALAPPDATA%`, `%TEMP%`, `%PUBLIC%`, `%PROGRAMDATA%`; random-looking names; entries created during the compromise window; anything masquerading as a Windows component but not in `System32`. **Sysinternals Process Explorer** (`procexp64.exe`, run as administrator): - [ ] **Options > VirusTotal.com > Check VirusTotal.com**. - [ ] Enable **Verify Image Signatures** and add the **Verified Signer** column. - [ ] Look for: unsigned processes, processes with no icon/description, browsers or `svchost` with unexpected parents, processes running from user-writable paths, unexpected network activity (add the **TCP/IP** tab detail). **Command-line sweeps** (elevated PowerShell — read-only, safe to run): ```powershell # Scheduled tasks not shipped by Microsoft Get-ScheduledTask | Where-Object { $_.TaskPath -notlike '\Microsoft\*' } | Select-Object TaskPath, TaskName, State, @{n='Action';e={($_.Actions | ForEach-Object { $_.Execute + ' ' + $_.Arguments }) -join ' | '}}, @{n='Author';e={$_.Author}} | Format-Table -AutoSize -Wrap # Services with binaries outside System32, and all auto-start non-Microsoft services Get-CimInstance Win32_Service | Where-Object { $_.PathName -notmatch 'System32|SysWOW64' } | Select-Object Name, DisplayName, State, StartMode, PathName, StartName | Format-Table -AutoSize -Wrap # Local accounts + when passwords were last set (new or recently reset accounts) Get-LocalUser | Select-Object Name, Enabled, LastLogon, PasswordLastSet, Description | Format-Table -AutoSize # Members of privileged local groups 'Administrators','Remote Desktop Users','Backup Operators' | ForEach-Object { "`n=== $_ ==="; Get-LocalGroupMember -Group $_ -ErrorAction SilentlyContinue | Select-Object Name, PrincipalSource, ObjectClass | Format-Table -AutoSize } # Software installed during the compromise window Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*', 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*', 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*' -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName } | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | Sort-Object InstallDate -Descending | Format-Table -AutoSize # Persistence: Run keys Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run', 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run', 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce', 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce' -ErrorAction SilentlyContinue # Current outbound connections with owning process Get-NetTCPConnection -State Established | Select-Object LocalAddress, LocalPort, RemoteAddress, RemotePort, @{n='Process';e={(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).Name}}, @{n='Path';e={(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).Path}} | Sort-Object RemoteAddress | Format-Table -AutoSize ``` **Security event log** — set the window to cover the compromise period: ```powershell $start = Get-Date '' # start of compromise window, local time # 4720 new user account | 4732 member added to a security-enabled local group Get-WinEvent -FilterHashtable @{LogName='Security'; ID=4720,4732; StartTime=$start} -ErrorAction SilentlyContinue | Select-Object TimeCreated, Id, Message | Format-List # 4624 successful logon, LogonType 10 = RemoteInteractive (RDP) Get-WinEvent -FilterHashtable @{LogName='Security'; ID=4624; StartTime=$start} -ErrorAction SilentlyContinue | Where-Object { $_.Message -match 'Logon Type:\s+10' } | Select-Object TimeCreated, @{n='Msg';e={($_.Message -split "`n")[0..25] -join "`n"}} | Format-List # Supporting: 4625 failed logons, 4672 special privileges, 1102 audit log cleared Get-WinEvent -FilterHashtable @{LogName='Security'; ID=4625,4672,1102; StartTime=$start} -ErrorAction SilentlyContinue | Group-Object Id | Select-Object Name, Count ``` - [ ] **4720** (user account created) — any account you did not create is a finding. - [ ] **4732** (member added to a security-enabled local group) — additions to Administrators especially. - [ ] **4624 with Logon Type 10** (RemoteInteractive/RDP) — correlate every one against known admin activity. An unattributed type-10 logon is a serious finding. - [ ] **1102** (audit log cleared) — an attacker action; note it and its time immediately. - [ ] Also check **Active Directory**: run the 4720/4732 queries on the **domain controllers**, not just the workstation, and review recent changes to Domain Admins, Enterprise Admins, and any GPO modified during the window. > Local-only checking misses domain-level persistence entirely, and the DC is where an attacker who escalated will have acted. ### 4.6 Browser extensions and remote-access tooling - [ ] **Browser extensions** — for every browser and **every profile** on the endpoint: review installed extensions, sorted by install date. Remove anything not explicitly needed and known. Extensions can read every page including webmail, and a malicious extension is a durable session-theft mechanism. - Chrome: `chrome://extensions` (enable Developer mode to see IDs), and check the profile's `Extensions` folder timestamps. - Check **Enterprise/force-installed** extensions too — verify they match what GPO actually deploys. - [ ] **RustDesk** — verify the installed instance **matches the GPO-deployed configuration**: expected version, expected relay/rendezvous server, expected permanent-password/access settings, expected config file contents. **A RustDesk instance pointed at a server you don't control is an attacker's remote access wearing a familiar name** — one of the easiest things to miss when your own RMM is RustDesk. - [ ] **Hunt for unauthorized remote access / RMM tooling.** Check installed programs, services, scheduled tasks, `Program Files`, `%APPDATA%`, and listening ports for: **AnyDesk, TeamViewer, ScreenConnect (ConnectWise Control), Atera, Splashtop**, and also LogMeIn, GoToAssist, Supremo, Ammyy Admin, DWAgent, MeshCentral, Chrome Remote Desktop, ngrok, and Quick Assist abuse. ```powershell $rmm = 'anydesk|teamviewer|screenconnect|connectwise|atera|splashtop|logmein|gotoassist|supremo|ammyy|dwagent|meshagent|meshcentral|ngrok|rustdesk|remoteutilities|radmin|tightvnc|ultravnc|realvnc' "=== Installed ===" Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*', 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*', 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*' -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -match $rmm } | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate, InstallLocation "=== Services ===" Get-CimInstance Win32_Service | Where-Object { $_.Name -match $rmm -or $_.PathName -match $rmm } | Select-Object Name, DisplayName, State, StartMode, PathName "=== Processes ===" Get-Process | Where-Object { $_.Name -match $rmm } | Select-Object Name, Id, Path "=== On-disk traces ===" Get-ChildItem 'C:\Program Files','C:\Program Files (x86)','C:\ProgramData',"$env:APPDATA","$env:LOCALAPPDATA" ` -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -match $rmm } | Select-Object FullName, CreationTime, LastWriteTime ``` - [ ] For anything found: **do not just uninstall it.** Record it, capture its config and logs (most RMM tools log connection history with source addresses — that is high-value evidence), *then* remove it. ### 4.7 Network: which endpoint actually clicked? - [ ] In **UniFi Network**, review firewall and traffic logs for the compromise window for outbound connections to `` and its resolved IPs. Identify the **internal source IP**, then map it to a device and a user via the UniFi client list and DHCP leases. - [ ] Check UniFi's threat management / IPS/IDS alerts for the window, if enabled. - [ ] Correlate the timing against the user's reported click time and against endpoint browser history. - [ ] Review DNS query logs if you have them. > **Flagged uncertainty:** UniFi's on-device log retention is short and its DNS query logging is limited or absent depending on the gateway model, firmware, and whether a syslog target or a DNS filtering service was configured in advance. **If the logs aren't there, record that they aren't there** — "no evidence of X" and "no logging capable of showing X" are very different statements and must not be conflated in the record. Post-incident, configuring syslog export is a recommendation worth making. - [ ] Block `` at the gateway/DNS layer, and check whether **any other internal host** also connected — that finds the victims who never reported clicking. ### 4.8 The infostealer determination **State this plainly, because it drives an expensive decision:** > **If an infostealer is confirmed on an endpoint, every credential ever saved in every browser profile on that endpoint is compromised** — saved passwords, session cookies, autofill data, credit cards, and any authenticated session the browser held — **regardless of whether the user "used that site recently."** Modern stealers take the entire credential store and cookie database in seconds, and the theft usually completes before the first detection. - [ ] If confirmed: **reimage the endpoint. Do not clean it.** > **Why reimage:** infostealers are commonly delivered by loaders that install additional payloads, and a "cleaned" machine that still holds an unnoticed loader re-infects and re-steals every credential you just rotated. The cost of reimaging is bounded and known; the cost of a false all-clear is another full incident. **A remediated detection is not a cleared endpoint.** - [ ] After reimaging, **rotate every credential that was stored in that browser profile** — not only the Google account. This is a superset of Phase 3.3 and it is the real cost of this finding. - [ ] If **not** confirmed, record exactly that: *"No evidence of infostealer compromise was found on `` as of `` using ``."* **Do not write "the endpoint is clean."** Absence of evidence, stated precisely, is defensible; an unsupported all-clear is not. --- # Phase 5 — Documentation and handoff **Estimated duration:** 1–2 hours, plus ongoing. **Exit criterion:** a complete, contemporaneous, unaltered record exists; the evidence inventory is hashed and stored; and the handoff package has been delivered **in writing** to `` with receipt acknowledged. > [!WARNING] > **Never backdate, alter, delete, or "clean up" any record, note, log, ticket, invoice, or timestamp relating to this incident — at any point, for any reason.** If something is wrong, **append a dated correction**; never edit the original. Altering a record is far more damaging than any error it would have concealed, and it converts a technical incident into a credibility problem. This applies to everything you touch, including this document. ### 5.1 Contemporaneous timeline Write entries **as you go**, not at the end. Every row carries **UTC and local**. Mark every entry as **Observed** (you saw it in a log/screen), **Reported** (someone told you), or **Action** (you did it) — the distinction is the whole value of the document. ```markdown ## Incident timeline — Account: Client: Operator: Timezone for "Local": Clock source/skew: | UTC | Local | Type | Description | Source / evidence file | By | |---|---|---|---|---|---| | 2026-01-01T14:03:00Z | 2026-01-01 09:03 | Reported | User reports clicking sign-in page from email; entered password | user statement, verbal | | | 2026-01-01T14:31:00Z | 2026-01-01 09:31 | Observed | Unrecognized device in Your devices, last active 08:52 local | 0-devices-1431Z.png | | | 2026-01-01T15:02:00Z | 2026-01-01 10:02 | Action | Revoked 3 unrecognized sessions | 2-devices-after-1502Z.png | | | 2026-01-01T15:20:00Z | 2026-01-01 10:20 | Action | Password reset from live session | decision log #4 | | ### Corrections | UTC of correction | Corrects entry | What was wrong | What is correct | |---|---|---|---| ``` - [ ] Record **unknowns explicitly** — "no logging available for X," "user could not recall Y." Gaps recorded are defensible; gaps papered over are not. - [ ] Never delete a row. Corrections go in the corrections table. ### 5.2 Evidence inventory - [ ] Produce a final inventory of ``: filename, SHA-256, size, what it shows, when captured (UTC), by whom, and the tool used. - [ ] Re-run the manifest command from Phase 0.4 and store the final manifest. - [ ] Store `` on **encrypted** media, with access limited and logged. It contains PHI-adjacent material — it is subject to the same protections as production. - [ ] Record a chain of custody: who has held the media, when, and where it is stored. - [ ] **Do not destroy anything.** A litigation or investigative hold may apply. Retention decisions belong to ``, not to you. ### 5.3 Handoff package to `` / `` Deliver **in writing**, factually, with no legal characterization: - [ ] The **timeline** (5.1) and **evidence inventory** (5.2). - [ ] **What was accessed or accessible** — mailbox, Drive, and downstream accounts, described in categories, with the basis for each statement (observed vs. inferred). - [ ] **PHI categories present** in the exposed surfaces and an **approximate count of individuals**, described factually. - [ ] **Containment actions taken**, with times. - [ ] **What could not be determined, and why** — especially the absence of a consumer-Gmail audit log, and any missing network/DNS logging. State this plainly; it is a material limitation on any assessment built on this record. - [ ] **Open items and residual risk** — anything unresolved, any endpoint pending reimage, any account not yet secured. - [ ] **Explicitly state what you are not doing:** *"This is a factual technical record. It is not a breach risk assessment and makes no determination about notification obligations."* - [ ] Get **written acknowledgment of receipt** and record its time in the timeline. - [ ] **Stop here on anything legal.** If asked "do we have to notify?", "is this reportable?", "what's the deadline?", or "should we tell patients?" — the answer is that the determination belongs to `` / ``, and you will provide any technical fact they need. ### 5.4 Your own position as a business associate - [ ] Review your **BAA** with `` for its notification-to-covered-entity terms and timing, and comply with them. Note that you did. - [ ] Notify your **E&O / cyber insurance carrier** per your policy's terms. Many policies require prompt notice and many provide breach-response counsel; late notice can void coverage. - [ ] Keep your incident records the same way you keep the client's: contemporaneous, unaltered, complete. ### 5.5 Post-incident (after containment is confirmed, not during) - [ ] **Move practice business off the consumer Gmail account.** A personal `@gmail.com` handling PHI has no admin console, no audit log, no eDiscovery, no retention control, no vendor support, and cannot be covered by a BAA. **Google does not offer a BAA for consumer accounts.** This is the single highest-value recommendation from this incident — put it in writing to ``. - [ ] Deploy phishing-resistant MFA (passkeys/FIDO2) across all practice accounts. - [ ] Deploy a password manager; eliminate reuse. - [ ] Add DNS filtering and configure UniFi **syslog export** so the next incident has logs. - [ ] Security awareness training covering AiTM phishing specifically — including that a correct-looking Google page and a working 2FA prompt prove nothing. - [ ] Verify Duplicati backups are intact, versioned, and **not reachable with any credential exposed in this incident**; confirm the Open Dental/MariaDB backup chain per [`od-backup-verify.md`](od-backup-verify.md). --- # Appendix A — Decision log template One row per decision, **written when you make it.** This is where you justify anything you did out of order, skipped, or judged. ```markdown ## Decision log — | # | UTC | Local | Decision | Options considered | Why this one | Who decided | Authorized by | |---|---|---|---|---|---|---|---| | 1 | | | Did not revoke sessions before locating live session | Revoke immediately / locate first | Live session may be only access path (runbook precondition) | | — | | 2 | | | Removed all OAuth grants incl. 2 unverified-but-plausible | Remove all / remove unknown only | Cannot distinguish; re-auth is cheap, missed grant is not | | | | 3 | | | Reimaged rather than cleaning | Clean / reimage | Infostealer confirmed; loader may persist | | | | 4 | | | | | | | | ### Deviations from runbook | # | UTC | Step deviated from | What was done instead | Why | |---|---|---|---|---| ### Escalations | # | UTC | Escalated to | Trigger | Delivered how | Acknowledged (UTC) | |---|---|---|---|---|---| ``` --- # Appendix B — Contact and escalation list Fill from the private tier. **Verify every number out-of-band before an incident** — during one is too late, and a number pulled from an email during an incident may be the attacker's. ```markdown ## Contacts — | Role | Name | Phone | Email | Notes | |---|---|---|---|---| | Practice owner / decision maker | | | | Authorizes downtime & reimaging | | HIPAA compliance / Privacy Officer | | | | **All legal determinations route here** | | Breach counsel / attorney | | | | Engage before any patient-facing statement | | Account owner (the user) | | | | Needed for recovery: familiar device/network | | IT consultant (you) | | | | | | Vendor / service | Contact | Verified number source | Account ref | |---|---|---|---| | Domain registrar | | from registrar site, logged in | **Phase 3 priority 1** | | Bank — practice operating | | back of card / statement | | | Merchant services | | statement | | | Payroll provider | | portal | | | Open Dental support | | opendental.com | | | Imaging vendor | | | | | Insurance clearinghouse | | | | | Bitdefender / GravityZone support | | partner portal | | | UniFi / network vendor | | | | | Cyber / E&O insurance carrier | | policy document | **Notify per policy terms** | | Google One support (if subscribed) | one.google.com/support | Google One app/site only | Only legitimate live channel | | Reporting channel | Where | Notes | |---|---|---| | FBI IC3 | ic3.gov | Consider; discuss with first | | Local FBI field office | | For significant financial loss | | State authorities | | ** determines applicability — not you** | > **No legitimate Google phone support exists for consumer accounts.** Any "Google support number" from a search result or ad is a scam. Google never calls about account security. ``` --- # Appendix C — On the volatility of these UI paths Google changes consumer account UI wording and navigation frequently and without notice. In this runbook: - **Deep links** (`myaccount.google.com/...`) are the durable part and are the primary reference throughout. - **Menu wording** ("Security & sign-in" vs "Security", "Apps with access to your account" vs "Your connections to third-party apps & services") **drifts**. If a path doesn't match what you see: navigate from **[myaccount.google.com](https://myaccount.google.com)** or Gmail **Settings > See all settings**, find the equivalent setting, complete the step, and **record the actual path you used** in the decision log. Then fix this runbook — in a normal commit, with a normal date. Never retroactively. **Do not skip a step because you cannot find its exact UI path.** A skipped OAuth review or filter sweep is how attackers stay in. Find the equivalent, or escalate that you could not. --- ## References - Google — Secure a hacked or compromised Google Account: - Google — Investigate suspicious activity on your account: - Google — See devices with account access: - Google — How to recover your Google Account or Gmail: - Google — Tips to complete account recovery steps (same device/browser/location; don't skip questions): - Google — Sign in with a passkey: - Google — Use a security key for 2-Step Verification: - Google — Sign in with app passwords (bypasses 2SV by design): - Google — Gmail security tips: - Google — Account security scam calls (Google never calls about your account): - Google — Avoid and report scams: - Google One — Get help with Google One support (chat/phone/email for members): - Microsoft — Microsoft Safety Scanner download: - Sysinternals — Autoruns: - Sysinternals — Process Explorer: - Companion runbook — backup integrity after an incident: [`od-backup-verify.md`](od-backup-verify.md)