<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
<!-- NERF is a trademark of defconxt. -->

# Email Forensics Deep Reference

`[MODE: BLUE]` | NERF Training Module | Email Header Analysis, BEC Investigation, Phishing Forensics

---

## Table of Contents

1. [Email Header Anatomy](#1-email-header-anatomy)
2. [Received Header Chain Analysis](#2-received-header-chain-analysis)
3. [Authentication Result Analysis](#3-authentication-result-analysis)
4. [Common Header Manipulation Techniques](#4-common-header-manipulation-techniques)
5. [Attachment Analysis Methodology](#5-attachment-analysis-methodology)
6. [URL Analysis in Emails](#6-url-analysis-in-emails)
7. [BEC Investigation Playbook](#7-bec-investigation-playbook)
8. [Microsoft 365 Email Forensics](#8-microsoft-365-email-forensics)
9. [Google Workspace Email Forensics](#9-google-workspace-email-forensics)
10. [Email as Evidence](#10-email-as-evidence)
11. [Tools Reference](#11-tools-reference)

---

## 1. Email Header Anatomy

### 1.1 How Email Headers Work

Email headers are metadata lines prepended to a message as it traverses the mail delivery chain. Each Mail Transfer Agent (MTA) adds headers. Headers are read **bottom-to-top** — the bottom-most `Received:` header is the originating hop; the top-most is the final delivery server.

Key RFC: **RFC 5322** (Internet Message Format), **RFC 5321** (SMTP).

### 1.2 Core Header Fields (RFC 5322bis / IANA Registry)

#### Envelope and Routing Headers

| Header | Purpose | Trace Header | RFC |
|--------|---------|:---:|-----|
| `Received` | Records each MTA hop with timestamp, IP, protocol | Yes | RFC 5322 |
| `Return-Path` | Envelope sender (MAIL FROM), set by final delivery MTA | Yes | RFC 5322 |
| `Delivered-To` | Final recipient mailbox (added by delivery agent) | — | RFC 9228 |
| `Envelope-To` | Envelope recipient (non-standard, some MTAs) | — | — |

#### Originator Headers

| Header | Purpose | RFC |
|--------|---------|-----|
| `From` | Author address displayed to recipient (RFC 5322 address) | RFC 6854 |
| `Sender` | Actual sending entity when different from `From` | RFC 6854 |
| `Reply-To` | Preferred reply address | RFC 5322 |
| `Date` | Message composition timestamp (RFC 2822 format) | RFC 5322 |
| `Message-ID` | Globally unique message identifier (`<local@domain>`) | RFC 5322 |

#### Destination Headers

| Header | Purpose | RFC |
|--------|---------|-----|
| `To` | Primary recipient(s) | RFC 5322 |
| `Cc` | Carbon copy recipient(s) | RFC 5322 |
| `Bcc` | Blind carbon copy (stripped before delivery) | RFC 5322 |

#### Content and MIME Headers

| Header | Purpose | RFC |
|--------|---------|-----|
| `Subject` | Message subject line | RFC 5322 |
| `MIME-Version` | MIME version (always `1.0`) | RFC 2045 |
| `Content-Type` | Media type and parameters (charset, boundary) | RFC 2045 |
| `Content-Transfer-Encoding` | Encoding (base64, quoted-printable, 7bit, 8bit) | RFC 2045 |
| `Content-Disposition` | Inline or attachment; filename parameter | RFC 2183 |
| `Content-ID` | Identifies MIME part for inline references (`cid:`) | RFC 2045 |
| `Content-Description` | Human-readable description of MIME part | RFC 2045 |

#### Thread and Reference Headers

| Header | Purpose | RFC |
|--------|---------|-----|
| `In-Reply-To` | Message-ID of parent message | RFC 5322 |
| `References` | Ordered list of Message-IDs in thread chain | RFC 5322 |
| `Keywords` | Message keywords/tags | RFC 5322 |
| `Comments` | Free-form comments | RFC 5322 |

#### Authentication Headers

| Header | Purpose | RFC |
|--------|---------|-----|
| `Authentication-Results` | SPF/DKIM/DMARC/ARC results from receiving MTA | RFC 8601 |
| `Received-SPF` | SPF check result from receiving MTA | RFC 7208 |
| `DKIM-Signature` | DKIM cryptographic signature | RFC 6376 |
| `ARC-Authentication-Results` | ARC chain authentication results | RFC 8617 |
| `ARC-Message-Signature` | ARC message-level signature | RFC 8617 |
| `ARC-Seal` | ARC chain validation seal | RFC 8617 |

#### Mailing List Headers

| Header | Purpose | RFC |
|--------|---------|-----|
| `List-ID` | Mailing list identifier | RFC 2919 |
| `List-Unsubscribe` | Unsubscribe URL or mailto | RFC 2369 |
| `List-Unsubscribe-Post` | One-click unsubscribe via POST | RFC 8058 |
| `List-Archive` | List archive URL | RFC 2369 |
| `List-Help` | List help URL | RFC 2369 |
| `List-Post` | Posting address | RFC 2369 |
| `List-Subscribe` | Subscribe URL or mailto | RFC 2369 |
| `List-Owner` | List owner contact | RFC 2369 |

#### Notification and Delivery Headers

| Header | Purpose | RFC |
|--------|---------|-----|
| `Disposition-Notification-To` | Request read receipt | RFC 3798 |
| `Disposition-Notification-Options` | Options for disposition notifications | RFC 3798 |
| `Original-Recipient` | Original envelope recipient | RFC 3798 |
| `Auto-Submitted` | Indicates auto-generated message (`auto-generated`, `auto-replied`) | RFC 3834 |

#### Resent Headers (Forwarding/Redistribution)

| Header | Purpose | RFC |
|--------|---------|-----|
| `Resent-From` | Address of entity resending | RFC 6854 |
| `Resent-Sender` | Actual resending agent | RFC 6854 |
| `Resent-To` | New recipient(s) | RFC 5322 |
| `Resent-Cc` | New CC recipient(s) | RFC 5322 |
| `Resent-Bcc` | New BCC recipient(s) | RFC 5322 |
| `Resent-Date` | Date of resending | RFC 5322 |
| `Resent-Message-ID` | New Message-ID for resent copy | RFC 5322 |

#### Priority and Handling Headers

| Header | Purpose | Notes |
|--------|---------|-------|
| `Importance` | Message importance (`low`, `normal`, `high`) | X.400 origin |
| `Priority` | Message priority (`non-urgent`, `normal`, `urgent`) | X.400 origin |
| `Sensitivity` | Sensitivity (`personal`, `private`, `company-confidential`) | X.400 origin |
| `MT-Priority` | SMTP priority level | RFC 6758 |
| `Expires` | Suggested expiration date | X.400 origin |

#### TLS and Transport Security

| Header | Purpose | RFC |
|--------|---------|-----|
| `TLS-Required` | Require TLS for delivery (`No` to downgrade) | RFC 8689 |
| `TLS-Report-Domain` | Domain for TLS-RPT reporting | RFC 8460 |
| `TLS-Report-Submitter` | Entity submitting TLS report | RFC 8460 |

#### Common Non-Standard (X-) Headers

| Header | Purpose | Source |
|--------|---------|--------|
| `X-Mailer` / `X-MimeOLE` | Sending client identifier | Client-specific |
| `X-Originating-IP` | Sender's IP (webmail) | Webmail providers |
| `X-Forwarded-To` / `X-Forwarded-For` | Forwarding chain info | Mail forwarders |
| `X-Spam-Status` / `X-Spam-Score` | Spam filter verdict | SpamAssassin etc. |
| `X-MS-Exchange-Organization-*` | Exchange-specific routing/policy | Microsoft Exchange |
| `X-Google-DKIM-Signature` | Google's internal DKIM signature | Gmail |
| `X-Gm-Message-State` | Gmail internal message state | Gmail |
| `X-MS-Has-Attach` | Exchange attachment indicator | Microsoft |
| `X-MS-TNEF-Correlator` | TNEF content correlation | Microsoft |
| `X-Auto-Response-Suppress` | Suppress OOF/auto-reply types | Microsoft |
| `X-Priority` | Legacy priority (1=highest, 5=lowest) | Legacy clients |

### 1.3 Header Ordering and Significance

```
[Top of headers — added last by receiving MTA]
  Received: by final-mta.example.com ...         ← Final hop (your MTA)
  Authentication-Results: ...                      ← YOUR MTA's auth verdict
  Received: by relay2.example.net ...              ← Intermediate relay
  Received: by relay1.example.net ...              ← Intermediate relay
  Received: by origin-mta.sender.com ...           ← Sender's outbound MTA
[Bottom of headers — original message headers]
  DKIM-Signature: ...                              ← Sender's DKIM sig
  From: sender@sender.com
  To: recipient@example.com
  Subject: ...
  Date: ...
  Message-ID: ...
  MIME-Version: 1.0
  Content-Type: ...
```

**Critical forensic principle**: Only headers added by YOUR infrastructure (top of chain) are trustworthy. Everything below could be forged by the sender.

---

## 2. Received Header Chain Analysis

### 2.1 Received Header Syntax

```
Received: from <sending-host> (<reverse-dns> [<IP>])
        by <receiving-host> (<software>)
        with <protocol> id <message-id>
        for <recipient>;
        <timestamp (RFC 2822)>
```

Example:
```
Received: from mail-sor-f41.google.com (mail-sor-f41.google.com [209.85.220.41])
        by mx.example.com (Postfix)
        with ESMTPS id A1B2C3D4E5
        for <user@example.com>;
        Fri, 14 Mar 2026 10:23:45 +0000 (UTC)
```

### 2.2 Parsing Each Received Hop

For each `Received:` header, extract:

| Field | What to Examine |
|-------|-----------------|
| `from <hostname>` | HELO/EHLO identity claimed by sending server |
| `(<reverse-dns> [<IP>])` | Actual rDNS and IP of connecting server — **this is verified by the receiving MTA** |
| `by <hostname>` | The server that received and logged this hop |
| `with <protocol>` | Protocol: `SMTP`, `ESMTP`, `ESMTPS` (TLS), `ESMTPSA` (TLS+Auth), `HTTP` (webmail), `LMTP` |
| `id <msg-id>` | Queue/session ID on the receiving server |
| `for <recipient>` | Envelope recipient at this hop |
| Timestamp | When this hop occurred |

### 2.3 Trace Analysis Procedure

```
STEP 1: Number hops bottom-to-top (Hop 1 = origination)
STEP 2: For each hop, record:
        - Claimed HELO name vs actual rDNS vs IP
        - Timestamp and time zone
        - Protocol (ESMTPS = encrypted, ESMTP = cleartext)
STEP 3: Calculate delay between consecutive hops
        - Normal: < 5 seconds between hops
        - Suspicious: > 30 seconds (processing delay, greylisting, or queuing)
        - Very suspicious: negative time delta (clock skew or forged timestamps)
STEP 4: Identify trust boundary
        - Your organization's MTA is the trust boundary
        - Headers below the trust boundary could be attacker-controlled
STEP 5: Verify IP geolocation and ASN for each external hop
STEP 6: Cross-reference originating IP against threat intelligence
```

### 2.4 Red Flags in Received Headers

| Indicator | Significance |
|-----------|-------------|
| HELO name doesn't match rDNS | Misconfigured or intentionally deceptive sender |
| IP resolves to residential ISP or VPN/proxy | Likely compromised host or anonymized sender |
| Missing `Received` headers | Headers stripped (some services do this legitimately; also attacker technique) |
| Inconsistent timestamp ordering | Possible header injection or forged headers |
| `with HTTP` or `with HTTPREST` at origin | Sent via webmail interface |
| `with ESMTPSA` | Authenticated SMTP submission (legitimate user or compromised credentials) |
| Unusual number of hops (>6) | May indicate open relays, forwarding chains, or obfuscation |
| Internal-looking hostnames in external email | Header injection to simulate internal routing |

### 2.5 Identifying the True Originating IP

```
1. Find the LOWEST Received header (bottom of chain)
2. If from a known webmail service (Gmail, Outlook, Yahoo):
   - The originating IP is the webmail server, NOT the user's IP
   - Check X-Originating-IP header (if present) for user IP
   - Gmail removed X-Originating-IP in 2013 for privacy
3. If from an on-premise mail server:
   - The first external hop (first hop outside sender's infrastructure) reveals the sender's network
4. Validate: does the IP belong to the domain's published SPF/MX records?
```

### 2.6 Received Header Parsing with Command Line

```bash
# Extract all Received headers from an EML file
grep -i "^Received:" email.eml

# Extract with continuation lines (multi-line headers)
grep -P "^Received:|^\s+" email.eml | grep -B1 "^\s+" | tr '\n' ' ' | sed 's/Received:/\nReceived:/g'

# Extract IPs from Received headers
grep -oP '\[(\d{1,3}\.){3}\d{1,3}\]' email.eml | tr -d '[]' | sort -u

# Extract timestamps from Received headers
grep -i "^Received:" email.eml | grep -oP ';\s*.*$' | sed 's/^;\s*//'

# Quick originating IP identification
formail -x Received < email.eml | tail -1 | grep -oP '\[(\d{1,3}\.){3}\d{1,3}\]'
```

---

## 3. Authentication Result Analysis

### 3.1 SPF (Sender Policy Framework)

**Purpose**: Validates that the sending IP is authorized to send for the envelope sender domain (MAIL FROM).

**DNS Record**: `TXT` record on sender domain.

```
v=spf1 ip4:192.0.2.0/24 include:_spf.google.com ~all
```

**SPF Result Values** (RFC 7208):

| Result | Meaning | Forensic Significance |
|--------|---------|----------------------|
| `pass` | IP authorized by domain's SPF | Legitimate or attacker using authorized infrastructure |
| `fail` (`-all`) | IP explicitly NOT authorized | Strong indicator of spoofing (if DMARC enforces) |
| `softfail` (`~all`) | IP not authorized, treat as suspicious | Common — many domains use `~all` instead of `-all` |
| `neutral` (`?all`) | Domain makes no assertion | No useful signal |
| `none` | No SPF record published | Domain has no SPF protection |
| `temperror` | Temporary DNS failure | Retry; not conclusive |
| `permerror` | SPF record syntax error | Broken SPF — investigate |

**SPF Header Example**:
```
Received-SPF: pass (google.com: domain of user@example.com designates 192.0.2.1 as permitted sender)
    client-ip=192.0.2.1;
Authentication-Results: mx.google.com;
    spf=pass (google.com: domain of user@example.com designates 192.0.2.1 as permitted sender)
    smtp.mailfrom=user@example.com
```

**SPF Forensic Checks**:
```bash
# Query SPF record
dig +short TXT example.com | grep "v=spf1"

# Resolve includes recursively
# Use dmarcian or mxtoolbox SPF survey for full expansion

# Check if sending IP falls within SPF ranges
# Compare client-ip in Received-SPF against published ranges
```

**SPF Limitations** [CONFIRMED]:
- SPF checks MAIL FROM (envelope sender), NOT the `From:` header displayed to users
- SPF breaks on forwarding (forwarding server IP is not in original domain's SPF)
- SPF has a 10-DNS-lookup limit — exceeding it causes `permerror`
- Attackers can pass SPF by using their own domain in MAIL FROM while spoofing the display `From:`

### 3.2 DKIM (DomainKeys Identified Mail)

**Purpose**: Cryptographic signature proving message integrity and authenticating the signing domain.

**DNS Record**: Public key at `<selector>._domainkey.<domain>` TXT record.

**DKIM-Signature Header Fields**:

```
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
    d=example.com; s=selector1;
    h=from:to:subject:date:message-id:content-type:mime-version;
    bh=<body-hash>;
    b=<signature>;
```

| Tag | Meaning |
|-----|---------|
| `v` | Version (always `1`) |
| `a` | Algorithm (`rsa-sha256` standard; `rsa-sha1` weak/deprecated) |
| `c` | Canonicalization (header/body): `simple` or `relaxed` |
| `d` | Signing domain — **this is the authenticated identity** |
| `s` | Selector (identifies which key to query in DNS) |
| `h` | Signed header fields (order matters) |
| `bh` | Body hash (Base64) |
| `b` | Signature (Base64) |
| `t` | Signature timestamp (Unix epoch) |
| `x` | Signature expiration (Unix epoch) |
| `l` | Body length limit (dangerous — allows appending unsigned content) |
| `i` | Agent or user identifier (optional, must be subdomain of `d`) |
| `q` | Query method (always `dns/txt`) |

**DKIM Result Values**:

| Result | Meaning |
|--------|---------|
| `pass` | Signature valid, message integrity confirmed |
| `fail` | Signature invalid — message modified in transit or forged signature |
| `none` | No DKIM signature present |
| `neutral` | Signature present but cannot be verified |
| `temperror` | Temporary failure (DNS timeout) |
| `permerror` | Permanent failure (missing key, bad format) |
| `policy` | Signature not acceptable per local policy |

**DKIM Forensic Checks**:
```bash
# Query DKIM public key
dig +short TXT selector1._domainkey.example.com

# Verify DKIM signature with opendkim
opendkim-testkey -d example.com -s selector1 -vvv

# Check signature with Python dkimpy
pip install dkimpy
dkimverify < message.eml

# Check which headers are signed (h= tag)
# CRITICAL: If "from" is not in h= tag, the From header is not authenticated
```

**DKIM Forensic Red Flags**:
- `l=` tag present: attacker can append content after the signed body length
- `a=rsa-sha1`: weak algorithm, vulnerable to collision attacks
- `h=` does not include `from`: signature doesn't protect sender identity
- Signature `d=` domain doesn't match `From:` domain: third-party signature (may be legitimate relay or suspicious)
- `x=` expired: signature no longer valid (may be legitimate for old messages)
- Key length < 1024 bits: potentially forgeable [CONFIRMED]

### 3.3 DMARC (Domain-based Message Authentication, Reporting, and Conformance)

**Purpose**: Links SPF and DKIM to the `From:` header domain. Tells receivers what to do when authentication fails.

**DNS Record**: `_dmarc.example.com TXT "v=DMARC1; p=reject; ..."`

**DMARC Record Tags**:

| Tag | Purpose | Values |
|-----|---------|--------|
| `v` | Version | `DMARC1` |
| `p` | Policy for domain | `none` (monitor), `quarantine`, `reject` |
| `sp` | Policy for subdomains | Same as `p` |
| `rua` | Aggregate report recipients | `mailto:dmarc-agg@example.com` |
| `ruf` | Forensic/failure report recipients | `mailto:dmarc-fail@example.com` |
| `adkim` | DKIM alignment mode | `r` (relaxed) or `s` (strict) |
| `aspf` | SPF alignment mode | `r` (relaxed) or `s` (strict) |
| `pct` | Percentage of messages to apply policy | `0`-`100` |
| `fo` | Failure reporting options | `0` (all fail), `1` (any fail), `d` (DKIM fail), `s` (SPF fail) |
| `ri` | Aggregate report interval (seconds) | Default `86400` (24h) |

**DMARC Alignment**:

```
DMARC PASS requires EITHER:
  1. SPF pass AND SPF domain aligns with From: domain
     - Relaxed: organizational domain match (sub.example.com aligns with example.com)
     - Strict: exact domain match
  OR
  2. DKIM pass AND DKIM d= domain aligns with From: domain
     - Relaxed: organizational domain match
     - Strict: exact domain match
```

**DMARC Forensic Checks**:
```bash
# Query DMARC record
dig +short TXT _dmarc.example.com

# Check Authentication-Results for DMARC verdict
grep -i "dmarc=" email_headers.txt

# Common Authentication-Results DMARC line:
# dmarc=pass (p=reject dis=none) header.from=example.com
# dmarc=fail (p=none dis=none) header.from=example.com
```

**DMARC Result Interpretation**:

| Result | `p=` | Action | Forensic Meaning |
|--------|------|--------|-----------------|
| `pass` | any | Delivered | Sender authenticated — but could be compromised account |
| `fail` | `none` | Delivered (monitoring) | Domain owner knows it fails but isn't enforcing yet |
| `fail` | `quarantine` | Spam/junk | Message failed auth, quarantined |
| `fail` | `reject` | Bounced | Message rejected — you may not even see it in logs |

### 3.4 ARC (Authenticated Received Chain)

**Purpose**: Preserves authentication results across indirect mail flows (forwarding, mailing lists) where SPF/DKIM break.

**ARC Headers** (RFC 8617, experimental):

```
ARC-Seal: i=1; a=rsa-sha256; cv=none; d=forwarder.com; s=arc-key; b=<sig>
ARC-Message-Signature: i=1; a=rsa-sha256; d=forwarder.com; s=arc-key; h=from:to:subject; bh=<hash>; b=<sig>
ARC-Authentication-Results: i=1; mx.forwarder.com;
    dkim=pass header.d=original-sender.com;
    spf=fail smtp.mailfrom=original-sender.com;
    dmarc=fail header.from=original-sender.com
```

| Tag | Meaning |
|-----|---------|
| `i=` | Instance number (increments with each forwarder in chain) |
| `cv=` | Chain validation: `none` (first), `pass`, `fail` |
| `d=` / `s=` | Signing domain and selector of the forwarder |

**ARC Forensic Significance**:
- ARC `cv=pass` with `dmarc=fail` in ARC-Authentication-Results suggests legitimate forwarding
- ARC `cv=fail` indicates the chain is broken — treat with suspicion
- ARC is trusted based on the receiver's trust of the ARC signer (forwarder)
- Microsoft 365 and Gmail both honor ARC from trusted forwarders

### 3.5 Authentication-Results Header Deep Dive

Full example with all mechanisms:
```
Authentication-Results: mx.example.com;
    spf=pass (sender SPF authorized) smtp.mailfrom=user@sender.com;
    dkim=pass (2048-bit key) header.d=sender.com header.s=sel1 header.b=abc123;
    dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=sender.com;
    compauth=pass reason=100
```

**Microsoft-specific `compauth`** (Composite Authentication):

| Reason Code | Meaning |
|-------------|---------|
| `000` | Message failed explicit authentication (`compauth=fail`) |
| `001` | Message failed implicit authentication |
| `1xx` | Message passed authentication |
| `2xx` | Soft-passed (sender authentication ambiguous) |
| `3xx` | Authentication not checked |
| `4xx`/`9xx` | Bypassed by policy/override |

---

## 4. Common Header Manipulation Techniques

### 4.1 Display Name Spoofing

The simplest and most common technique. No authentication fails because only the display name is faked.

```
From: "CEO John Smith" <attacker@evil.com>
```

- SPF: pass (for evil.com)
- DKIM: pass (signed by evil.com)
- DMARC: pass (for evil.com)
- **Detection**: Display name matches known internal contact, but domain doesn't

**Variant — Unicode/Homoglyph Display Name**:
```
From: "CEO J\u043ehn Smith" <attacker@evil.com>
```
Uses Cyrillic "o" (U+043E) instead of Latin "o" — visually identical.

### 4.2 Cousin/Lookalike Domain Spoofing

Attacker registers a domain visually similar to target.

```
From: ceo@exarnple.com       ← "rn" looks like "m"
From: ceo@example.co         ← TLD variation
From: ceo@examp1e.com        ← "1" instead of "l"
From: ceo@example-corp.com   ← Added suffix
```

- All authentication passes for the lookalike domain
- **Detection**: Domain similarity analysis, lookalike domain monitoring, Microsoft Defender impersonation protection

### 4.3 Reply-To Manipulation

Legitimate-looking `From:` but `Reply-To:` goes to attacker.

```
From: ceo@company.com
Reply-To: ceo.company@gmail.com
```

- If SPF/DKIM/DMARC are not enforced for company.com, the From may pass
- **Detection**: Check Reply-To against From domain; flag free email providers in Reply-To for business emails

### 4.4 Direct From: Header Spoofing

Attacker sends with a forged `From:` header from a server they control.

```
MAIL FROM: <attacker@evil.com>          ← Envelope sender (checked by SPF)
From: ceo@company.com                   ← Display header (checked by DMARC alignment)
```

- SPF: pass for evil.com (envelope sender)
- DKIM: pass for evil.com (if they sign)
- DMARC: **fail** for company.com (if company.com has DMARC) — SPF domain (evil.com) doesn't align with From domain (company.com)
- **Detection**: DMARC enforcement is the primary defense

### 4.5 Null Sender / Empty MAIL FROM

```
MAIL FROM: <>
From: ceo@company.com
```

- SPF checks the HELO identity when MAIL FROM is null
- DMARC may still catch this if company.com publishes DMARC
- Used legitimately for DSN/bounce messages

### 4.6 Received Header Injection

Attacker adds fake `Received:` headers to make the message appear to originate from a different source.

```
Received: from internal-mail.company.com (internal-mail.company.com [10.0.0.5])
        by fake-hop.company.com with ESMTP; Fri, 14 Mar 2026 10:00:00 +0000
```

- **Detection**: Headers below YOUR MTA's Received header are untrusted
- Look for internal RFC 1918 IPs appearing before the trust boundary
- Check for timestamp inconsistencies

### 4.7 Header Field Injection via SMTP

Exploiting SMTP DATA command to inject arbitrary headers:

```
Subject: Urgent Payment\r\nFrom: ceo@company.com\r\nReceived: from trusted.server.com
```

- Modern MTAs sanitize this, but legacy systems may be vulnerable
- **Detection**: Look for duplicate `From:` headers; look for headers with unusual placement

### 4.8 Compromised Email Account

Hardest to detect — legitimate credentials, passes all authentication.

```
SPF: pass
DKIM: pass (signed by legitimate domain)
DMARC: pass
```

- **Detection**: Behavioral analysis required
  - Unusual login location/time (Unified Audit Log)
  - Inbox rules created to hide responses (forwarding rules, delete rules)
  - Unusual recipients or unusual attachment types
  - Message content analysis (urgency, wire transfer requests)

### 4.9 Via/Through Legitimate Services

Attacker uses legitimate email service (SendGrid, Mailchimp, AWS SES) to send phishing.

- SPF passes because the service is authorized
- DKIM may pass if the service signs with their domain
- **Detection**: Check `X-Mailer`, `X-SG-EID` (SendGrid), service-specific headers; verify if the domain owner actually uses that service

---

## 5. Attachment Analysis Methodology

### 5.1 Triage Workflow

```
                    ┌──────────────────┐
                    │  Extract Email    │
                    │  Attachments      │
                    └────────┬─────────┘
                             │
                    ┌────────▼─────────┐
                    │  Hash Files       │
                    │  (MD5/SHA256)     │
                    └────────┬─────────┘
                             │
                ┌────────────┼────────────┐
                │            │            │
       ┌────────▼───┐ ┌─────▼──────┐ ┌───▼────────────┐
       │ VT/MalBazaar│ │ File Type   │ │ Sandbox Submit │
       │ Hash Lookup │ │ Analysis    │ │ (ANY.RUN, etc) │
       └────────┬───┘ └─────┬──────┘ └───┬────────────┘
                │            │            │
                └────────────┼────────────┘
                             │
                    ┌────────▼─────────┐
                    │  Static Analysis  │
                    │  (oletools, YARA) │
                    └────────┬─────────┘
                             │
                    ┌────────▼─────────┐
                    │  Dynamic Analysis │
                    │  (Sandbox review) │
                    └──────────────────┘
```

### 5.2 Extracting Attachments

```bash
# Using munpack (from mpack package)
munpack -t email.eml

# Using Python email library
python3 -c "
import email, sys, os
with open('email.eml', 'rb') as f:
    msg = email.message_from_binary_file(f)
for part in msg.walk():
    fn = part.get_filename()
    if fn:
        with open(fn, 'wb') as out:
            out.write(part.get_payload(decode=True))
        print(f'Extracted: {fn}')
"

# Using emlanalyzer (from eml_analyzer)
# Web UI at localhost:8000 after Docker deployment

# Hash extracted files
sha256sum extracted_file.*
md5sum extracted_file.*
```

### 5.3 Office Document Analysis with oletools

**oletools** (https://github.com/decalage2/oletools) is the standard toolkit for Office document malware analysis. Install: `pip install -U oletools[full]`

#### oleid — Quick Triage

```bash
# Identify suspicious indicators
oleid suspicious_doc.docx

# Output includes risk levels for:
# - VBA Macros
# - XLM Macros
# - External Relationships
# - ObjectPool
# - Flash objects
```

#### olevba — VBA Macro Extraction and Analysis

```bash
# Extract and analyze VBA macros
olevba suspicious_doc.docm

# Decode obfuscated strings
olevba --decode suspicious_doc.docm

# Output in JSON for automated processing
olevba --json suspicious_doc.docm

# Key indicators in output:
# AutoExec    — macro runs automatically (AutoOpen, Document_Open, Workbook_Open)
# Suspicious  — Shell, WScript, PowerShell, CreateObject, download patterns
# IOC         — URLs, IPs, filenames
# Hex Strings — obfuscated content
# Base64      — encoded payloads
# Dridex      — specific obfuscation patterns
```

#### mraptor (MacroRaptor) — Malicious Macro Detection

```bash
# Quick malicious macro classification
mraptor suspicious_doc.docm

# Results: SUSPICIOUS or not
# Checks for: Auto-execution + Write to file/registry + Execute external commands
```

#### msodde — DDE/DDEAUTO Detection

```bash
# Extract DDE links (common infection vector, no macros needed)
msodde suspicious_doc.docx

# Also works on RTF and CSV files
msodde suspicious.rtf
```

#### rtfobj — RTF Embedded Object Extraction

```bash
# Extract embedded objects from RTF
rtfobj suspicious.rtf

# Extracts OLE objects, packages, embedded executables
# Common in exploit docs (CVE-2017-11882, CVE-2017-0199)
```

#### oleobj — OLE Embedded Object Extraction

```bash
# Extract embedded objects from OLE files
oleobj suspicious.doc

# Look for embedded PE files, scripts, or secondary documents
```

#### pyxswf — Flash/SWF Detection

```bash
# Detect embedded Flash objects
pyxswf suspicious.xls

# Legacy attack vector, still found in older malware
```

### 5.4 YARA Rules for Email Attachments

```yara
rule Suspicious_Office_Macro {
    meta:
        description = "Detects Office documents with suspicious VBA patterns"
        author = "NERF"
        date = "2026-03-14"
    strings:
        $auto1 = "AutoOpen" ascii nocase
        $auto2 = "Document_Open" ascii nocase
        $auto3 = "Workbook_Open" ascii nocase
        $sus1 = "Shell" ascii nocase
        $sus2 = "WScript" ascii nocase
        $sus3 = "PowerShell" ascii nocase
        $sus4 = "CreateObject" ascii nocase
        $sus5 = "URLDownloadToFile" ascii nocase
        $sus6 = "XMLHTTP" ascii nocase
        $sus7 = "Environ" ascii nocase
    condition:
        (uint32(0) == 0xe011cfd0 or   // OLE
         uint32(0) == 0x04034b50)      // ZIP (OOXML)
        and any of ($auto*) and any of ($sus*)
}

rule Email_Attachment_Executable_In_Archive {
    meta:
        description = "Detects executables hidden in archive attachments"
    strings:
        $mz = { 4D 5A }
        $pe = "PE\x00\x00"
    condition:
        (uint32(0) == 0x04034b50 or    // ZIP
         uint16(0) == 0x8b1f)          // GZIP
        and $mz and $pe
}

rule HTML_Smuggling_Email_Attachment {
    meta:
        description = "Detects HTML smuggling in email attachments"
    strings:
        $blob = "new Blob" ascii
        $atob = "atob(" ascii
        $download = "download" ascii
        $b64 = /[A-Za-z0-9+\/]{100,}={0,2}/ ascii
    condition:
        filesize < 500KB and
        all of them
}
```

### 5.5 Common Malicious Attachment Types

| Extension | Threat | Analysis Tool |
|-----------|--------|---------------|
| `.docm`, `.xlsm`, `.pptm` | VBA macros | olevba, mraptor |
| `.doc`, `.xls` (OLE) | VBA macros, DDE, exploits | olevba, msodde, oleobj |
| `.docx`, `.xlsx` (OOXML) | DDE, external templates, remote OLE | msodde, zipdump |
| `.rtf` | Embedded OLE, exploits (CVE-2017-11882) | rtfobj |
| `.html`, `.htm` | HTML smuggling, credential phishing | Browser analysis, strings |
| `.iso`, `.img`, `.vhd` | MoTW bypass, embedded executables | Mount + static analysis |
| `.lnk` | Shortcut pointing to malicious command | LECmd, exiftool |
| `.one` | OneNote with embedded scripts | onenote-analyzer |
| `.pdf` | JavaScript, embedded files, phishing URLs | pdf-parser, pdfid |
| `.zip`, `.7z`, `.rar` | Password-protected archives with malware | Unarchive + analyze contents |
| `.js`, `.vbs`, `.wsf` | Script downloaders | Static analysis, sandbox |

---

## 6. URL Analysis in Emails

### 6.1 URL Extraction

```bash
# Extract URLs from EML file
grep -oP 'https?://[^\s"<>]+' email.eml | sort -u

# Extract URLs from HTML body (decode base64 first if needed)
python3 -c "
import email, re
from html import unescape
with open('email.eml', 'rb') as f:
    msg = email.message_from_binary_file(f)
for part in msg.walk():
    ct = part.get_content_type()
    if ct in ('text/html', 'text/plain'):
        body = part.get_payload(decode=True).decode('utf-8', errors='ignore')
        body = unescape(body)
        urls = re.findall(r'https?://[^\s\"<>\)]+', body)
        for url in set(urls):
            print(url)
"

# Extract href targets from HTML (catches obfuscated display text)
python3 -c "
from html.parser import HTMLParser
import email
class LinkExtractor(HTMLParser):
    def handle_starttag(self, tag, attrs):
        if tag == 'a':
            for name, val in attrs:
                if name == 'href' and val:
                    print(val)
with open('email.eml', 'rb') as f:
    msg = email.message_from_binary_file(f)
for part in msg.walk():
    if part.get_content_type() == 'text/html':
        body = part.get_payload(decode=True).decode('utf-8', errors='ignore')
        LinkExtractor().feed(body)
"
```

### 6.2 URL Analysis Checklist

```
□ Compare displayed text vs actual href (link text says "bank.com", href goes to "evil.com")
□ Check for URL shorteners (bit.ly, tinyurl, t.co) — expand before analysis
□ Check for tracking redirects (e.g., safelinks.protection.outlook.com, urldefense.proofpoint.com)
□ Decode percent-encoded characters (%20, %2F, etc.)
□ Check for punycode/IDN homograph domains (xn-- prefix)
□ Check for data: URIs (data:text/html;base64,...)
□ Look for @ in URL (user:pass@host — browser ignores before @)
□ Check domain age (whois) — newly registered domains are suspicious
□ Check against URL reputation services (VirusTotal, urlscan.io, PhishTank)
□ Check for IP-based URLs (http://192.168.1.1/payload)
□ Check for open redirects on legitimate domains
□ Identify credential harvesting pages (login forms, OAuth phishing)
```

### 6.3 URL Reputation and Intelligence

```bash
# urlscan.io submission
curl -X POST "https://urlscan.io/api/v1/scan/" \
  -H "API-Key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://suspicious-url.com", "visibility": "unlisted"}'

# VirusTotal URL scan
curl -X POST "https://www.virustotal.com/api/v3/urls" \
  -H "x-apikey: YOUR_KEY" \
  --form "url=https://suspicious-url.com"

# PhishTank check
curl "https://checkurl.phishtank.com/checkurl/" \
  -d "url=https://suspicious-url.com&format=json&app_key=YOUR_KEY"

# Google Safe Browsing API
curl -X POST "https://safebrowsing.googleapis.com/v4/threatMatches:find?key=YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "threatInfo": {
      "threatTypes": ["MALWARE", "SOCIAL_ENGINEERING", "UNWANTED_SOFTWARE"],
      "platformTypes": ["ANY_PLATFORM"],
      "threatEntryTypes": ["URL"],
      "threatEntries": [{"url": "https://suspicious-url.com"}]
    }
  }'

# Expand shortened URL without following
curl -sI "https://bit.ly/xxxxx" | grep -i "location:"
```

### 6.4 Common URL Obfuscation Techniques

| Technique | Example | Detection |
|-----------|---------|-----------|
| URL encoding | `%68%74%74%70` for `http` | Decode percent-encoding |
| IP address (decimal) | `http://3232235777/` (192.168.1.1) | Convert decimal to dotted |
| IP address (hex) | `http://0xC0A80101/` | Convert hex to dotted |
| IP address (octal) | `http://0300.0250.0001.0001/` | Convert octal to dotted |
| Punycode/IDN | `xn--exmple-cua.com` | Decode with `idn --decode` |
| URL shortener chain | `bit.ly` -> `tinyurl` -> `evil.com` | Recursive expansion |
| Open redirect abuse | `google.com/url?q=evil.com` | Check redirect parameter |
| Data URI | `data:text/html;base64,PHN...` | Base64 decode |
| JavaScript redirect | `javascript:window.location=...` | Deobfuscate JS |
| Credential in URL | `http://legit.com@evil.com/` | Parse actual destination host |
| Zero-width characters | `exam​ple.com` (ZWSP) | Check for U+200B, U+200C, U+200D |

---

## 7. BEC Investigation Playbook

### 7.1 BEC Attack Taxonomy (MITRE ATT&CK)

| Technique ID | Technique | BEC Application |
|-------------|-----------|----------------|
| T1566.001 | Spearphishing Attachment | Malware delivery to gain access |
| T1566.002 | Spearphishing Link | Credential harvesting |
| T1534 | Internal Spearphishing | Compromised account sends internal phishing |
| T1114.002 | Remote Email Collection | Attacker reads victim's mailbox |
| T1078 | Valid Accounts | Using compromised credentials |
| T1098.005 | Device Registration | Registering attacker device for MFA |
| T1564.008 | Email Hiding Rules | Inbox rules to hide evidence |
| T1036 | Masquerading | Impersonating executives/vendors |

### 7.2 BEC Investigation Phases

#### Phase 1: Initial Triage (0-30 minutes)

```
□ Identify the suspicious email(s) — save original EML/MSG files
□ Determine BEC variant:
  - CEO Fraud: executive impersonation requesting wire transfer
  - Invoice Fraud: vendor impersonation with modified banking details
  - Account Compromise: legitimate account used for internal phishing
  - Attorney Impersonation: legal pressure + urgency
  - Payroll Diversion: HR request to change direct deposit
  - Data Theft: request for employee W-2/tax data or customer PII
□ Check if financial transaction has occurred
  - If yes: IMMEDIATELY contact bank for recall/hold
  - Wire recall window is typically 24-72 hours
□ Assess scope: how many users received the email?
□ Identify the attack vector (spoofed external, compromised internal, lookalike domain)
```

#### Phase 2: Email Forensics (30 minutes - 2 hours)

```
HEADER ANALYSIS:
□ Parse full email headers (bottom to top)
□ Extract originating IP and geolocate
□ Verify SPF/DKIM/DMARC results
□ Check Authentication-Results for compauth (M365)
□ Identify actual sending infrastructure
□ Check for Reply-To manipulation
□ Look for header anomalies (mismatched timezones, unusual X-headers)

CONTENT ANALYSIS:
□ Identify social engineering indicators:
  - Urgency language ("immediately", "today", "critical")
  - Authority pressure ("CEO", "Board", "Legal")
  - Secrecy ("confidential", "don't discuss with anyone")
  - Financial action requests (wire, ACH, gift cards, cryptocurrency)
  - Changed banking details for known vendor
□ Extract and analyze all URLs (Section 6)
□ Extract and analyze all attachments (Section 5)
□ Check for brand impersonation in HTML/images

INFRASTRUCTURE ANALYSIS:
□ WHOIS on sending domain — registration date, registrar, registrant
□ DNS records for sending domain (MX, SPF, DKIM, DMARC)
□ Passive DNS on sending IP
□ Check sending IP against threat intelligence feeds
□ If lookalike domain: document character substitutions
□ Certificate Transparency logs for lookalike domains (crt.sh)
```

#### Phase 3: Account Compromise Assessment (if internal account suspected)

```
MICROSOFT 365:
□ Unified Audit Log search (Section 8)
□ Sign-in logs: unusual IPs, locations, devices, user agents
□ Check for inbox rules created (T1564.008):
  - Search-UnifiedAuditLog -Operations "New-InboxRule","Set-InboxRule"
  - Look for rules forwarding to external addresses
  - Look for rules deleting/moving messages matching keywords
□ Check for email forwarding configured:
  - Get-Mailbox -Identity user | FL ForwardingAddress,ForwardingSMTPAddress
  - Get-InboxRule -Mailbox user | where {$_.ForwardTo -or $_.RedirectTo}
□ Check for OAuth app consent (consent phishing):
  - Search-UnifiedAuditLog -Operations "Consent to application"
□ Check for MFA changes/additions
□ Check for mail sent from the compromised account
□ Check Mailbox Audit Log for MailItemsAccessed

GOOGLE WORKSPACE:
□ Admin Console > Reports > User Audit
□ Check login activity for suspicious sessions
□ Check for email forwarding and delegation
□ Check for app passwords created
□ Review OAuth token grants
□ Check filter/label rules for evidence hiding
```

#### Phase 4: Containment

```
IMMEDIATE ACTIONS:
□ Reset compromised account password
□ Revoke all active sessions and refresh tokens
□ Revoke suspicious OAuth app consents
□ Remove malicious inbox rules and forwarding
□ Enable MFA if not already enabled (or reset MFA)
□ Block attacker IPs/domains at email gateway
□ Block lookalike domains in DNS/firewall
□ Quarantine/delete malicious emails from all mailboxes
  - M365: Search-Mailbox -SearchQuery "subject:..." -DeleteContent
  - Or use Threat Explorer / Email Entity in Defender portal

NOTIFICATION:
□ Notify affected users (what to look for, what NOT to do)
□ Notify finance/accounting if wire transfer requested
□ Notify legal if PII/regulated data exposed
□ Notify law enforcement (IC3.gov for US, Action Fraud for UK)
□ Consider regulatory notification (GDPR Art. 33: 72-hour window)
```

#### Phase 5: Scope Assessment and Evidence Collection

```
EVIDENCE PRESERVATION:
□ Export original malicious email(s) as EML
□ Screenshot email as displayed to user
□ Export relevant audit logs (retain for investigation period)
□ Document timeline of events
□ Preserve email headers in original format (no reformatting)
□ If financial fraud: preserve all wire transfer instructions,
  invoices, and communication chain

SCOPE ASSESSMENT:
□ Search all mailboxes for similar phishing emails
  - By sender domain/address
  - By subject line patterns
  - By URL/attachment hash
□ Check if other accounts interacted with the email
□ Check if credentials were entered on phishing page
□ Review email gateway logs for related traffic
□ Check if data was exfiltrated
```

#### Phase 6: Remediation and Hardening

```
□ Implement/enforce DMARC p=reject for organizational domains
□ Enable anti-impersonation policies (M365 Defender)
□ Add external email warning banner
□ Review and tighten inbox rule creation permissions
□ Implement conditional access policies (block legacy auth, require MFA)
□ Deploy anti-phishing training for affected users
□ Add lookalike domains to block lists
□ Review financial approval workflows (dual authorization for wire transfers)
□ Update email gateway rules based on IOCs
□ Submit IOCs to threat intelligence sharing platforms (MISP, ISACs)
```

### 7.3 BEC IOC Collection Template

```
SENDER INFORMATION:
  Display Name:
  From Address:
  Reply-To Address:
  Envelope Sender (MAIL FROM):
  Sending IP:
  Sending IP Geolocation:
  Sending IP ASN:
  User-Agent / X-Mailer:

DOMAIN INTELLIGENCE:
  Sending Domain:
  Domain Registration Date:
  Domain Registrar:
  Domain Registrant (if available):
  MX Records:
  SPF Record:
  DMARC Record:
  SSL Certificate (if phishing site):

EMAIL IDENTIFIERS:
  Message-ID:
  Subject:
  Date/Time (UTC):
  Authentication Results (SPF/DKIM/DMARC):

PAYLOAD:
  URLs (defanged):
  Attachment Filenames:
  Attachment Hashes (SHA256):
  Attachment File Types:

INFRASTRUCTURE:
  Phishing Page URL:
  Phishing Page IP:
  Phishing Page Hosting Provider:
  C2 Domains (if malware):
  C2 IPs (if malware):

FINANCIAL:
  Beneficiary Name:
  Beneficiary Bank:
  Account Number:
  Routing/SWIFT/IBAN:
  Requested Amount:
  Cryptocurrency Wallet (if applicable):
```

---

## 8. Microsoft 365 Email Forensics

### 8.1 Unified Audit Log (UAL) — Email-Related Events

**Prerequisite**: Audit logging must be enabled (on by default since 2019, but verify).

```powershell
# Connect to Exchange Online PowerShell
Connect-ExchangeOnline -UserPrincipalName admin@company.com

# Verify audit logging is enabled
Get-AdminAuditLogConfig | FL UnifiedAuditLogIngestionEnabled

# Enable if disabled
Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled $true
```

#### Key UAL Operations for Email Investigations

```powershell
# Search for mailbox login activity
Search-UnifiedAuditLog -StartDate "2026-03-01" -EndDate "2026-03-14" `
  -Operations "MailboxLogin" -UserIds "user@company.com" -ResultSize 5000

# Search for inbox rule creation/modification
Search-UnifiedAuditLog -StartDate "2026-03-01" -EndDate "2026-03-14" `
  -Operations "New-InboxRule","Set-InboxRule","Enable-InboxRule" `
  -UserIds "user@company.com"

# Search for email forwarding changes
Search-UnifiedAuditLog -StartDate "2026-03-01" -EndDate "2026-03-14" `
  -Operations "Set-Mailbox" -UserIds "user@company.com" `
  | Where-Object { $_.AuditData -like "*Forward*" }

# Search for mail items accessed (requires E5 or Audit Premium)
Search-UnifiedAuditLog -StartDate "2026-03-01" -EndDate "2026-03-14" `
  -Operations "MailItemsAccessed" -UserIds "user@company.com" -ResultSize 5000

# Search for email send events
Search-UnifiedAuditLog -StartDate "2026-03-01" -EndDate "2026-03-14" `
  -Operations "Send","SendAs","SendOnBehalf" -UserIds "user@company.com"

# Search for OAuth consent grants
Search-UnifiedAuditLog -StartDate "2026-03-01" -EndDate "2026-03-14" `
  -Operations "Consent to application" -UserIds "user@company.com"

# Search for delegate access changes
Search-UnifiedAuditLog -StartDate "2026-03-01" -EndDate "2026-03-14" `
  -Operations "Add-MailboxPermission","Add-RecipientPermission" `
  -UserIds "user@company.com"

# Export results for analysis
Search-UnifiedAuditLog -StartDate "2026-03-01" -EndDate "2026-03-14" `
  -UserIds "user@company.com" -ResultSize 5000 `
  | Export-Csv -Path "audit_log_export.csv" -NoTypeInformation
```

| Operation | What It Captures |
|-----------|-----------------|
| `MailboxLogin` | Mailbox access (IP, client, user agent) |
| `MailItemsAccessed` | Individual mail items read (E5/Audit Premium) |
| `New-InboxRule` | Inbox rule creation |
| `Set-InboxRule` | Inbox rule modification |
| `UpdateInboxRules` | Client-side rule changes (Outlook) |
| `Set-Mailbox` | Mailbox property changes (forwarding, delegation) |
| `Send` / `SendAs` / `SendOnBehalf` | Email sending |
| `MoveToDeletedItems` / `SoftDelete` / `HardDelete` | Email deletion |
| `Consent to application` | OAuth app consent |
| `Add-MailboxPermission` | Delegate access granted |

### 8.2 Message Trace

```powershell
# Basic message trace (last 10 days)
Get-MessageTrace -SenderAddress "attacker@evil.com" `
  -StartDate "2026-03-04" -EndDate "2026-03-14"

# Trace by recipient
Get-MessageTrace -RecipientAddress "victim@company.com" `
  -StartDate "2026-03-04" -EndDate "2026-03-14"

# Trace by Message-ID
Get-MessageTrace -MessageId "<message-id@domain.com>" `
  -StartDate "2026-03-04" -EndDate "2026-03-14"

# Detailed message trace (for messages older than 10 days, up to 90 days)
Start-HistoricalSearch -ReportTitle "BEC Investigation" `
  -StartDate "2026-01-01" -EndDate "2026-03-14" `
  -ReportType MessageTrace `
  -SenderAddress "attacker@evil.com"

# Get detailed trace for specific message
Get-MessageTraceDetail -MessageTraceId <trace-id> -RecipientAddress "victim@company.com"
```

### 8.3 Microsoft Defender for Office 365

#### Threat Explorer Queries

```
# Access: security.microsoft.com > Email & collaboration > Explorer

# Search by sender
Sender: attacker@evil.com
Date: Last 30 days

# Search by subject
Subject: "Urgent Wire Transfer"

# Search phishing verdicts
Detection technology: URL detonation, File detonation, Impersonation domain
Delivery action: Delivered

# URL clicks tracking
View: URL clicks
Filter by user or URL

# Campaign view
View: Campaigns
Automated clustering of related phishing
```

#### Email Entity Investigation

```
# In Defender portal, investigate specific email:
# 1. Get Message-ID from headers
# 2. Explorer > search by Message-ID
# 3. Click email to open Email Entity page
#
# Email Entity shows:
# - Full headers
# - Authentication results
# - Delivery details (action, location, original delivery location)
# - URLs and their detonation results
# - Attachments and their detonation results
# - Impersonation detection details
# - Related alerts and incidents
```

### 8.4 Searching and Purging Malicious Emails

```powershell
# Search all mailboxes for malicious email (New Compliance Search)
New-ComplianceSearch -Name "BEC_Purge_2026_03" `
  -ExchangeLocation All `
  -ContentMatchQuery 'from:attacker@evil.com AND subject:"Urgent Payment"'

# Start the search
Start-ComplianceSearch -Identity "BEC_Purge_2026_03"

# Preview results
Get-ComplianceSearch -Identity "BEC_Purge_2026_03" | FL Items,Size

# Purge (soft delete — recoverable)
New-ComplianceSearchAction -SearchName "BEC_Purge_2026_03" -Purge -PurgeType SoftDelete

# Purge (hard delete — permanent, requires approval)
New-ComplianceSearchAction -SearchName "BEC_Purge_2026_03" -Purge -PurgeType HardDelete
```

### 8.5 Checking for Persistence (Compromised Account)

```powershell
# Check inbox rules
Get-InboxRule -Mailbox "victim@company.com" | FL Name,Description,Enabled,
  ForwardTo,ForwardAsAttachmentTo,RedirectTo,DeleteMessage,MoveToFolder

# Check mailbox forwarding
Get-Mailbox -Identity "victim@company.com" | FL ForwardingAddress,
  ForwardingSMTPAddress,DeliverToMailboxAndForward

# Check mailbox delegates
Get-MailboxPermission -Identity "victim@company.com" |
  Where-Object { $_.IsInherited -eq $false -and $_.User -ne "NT AUTHORITY\SELF" }

# Check send-as permissions
Get-RecipientPermission -Identity "victim@company.com"

# Check transport rules (org-wide)
Get-TransportRule | FL Name,State,From,SentTo,RedirectMessageTo

# Check mail flow connectors (org-wide)
Get-InboundConnector | FL Name,Enabled,SenderDomains
Get-OutboundConnector | FL Name,Enabled,RecipientDomains

# Check OAuth app permissions (via Graph API)
# GET https://graph.microsoft.com/v1.0/users/{id}/oauth2PermissionGrants
# GET https://graph.microsoft.com/v1.0/servicePrincipals/{id}/appRoleAssignments

# Check registered devices/auth methods
# Azure AD Portal > Users > user > Authentication methods
# Azure AD Portal > Users > user > Devices
```

### 8.6 Microsoft 365 Anti-Phishing Features

Based on Microsoft Defender for Office 365 [CONFIRMED]:

**EOP (All Cloud Mailboxes)**:
- **Spoof intelligence**: Detects spoofed senders from internal and external domains; manual allow/block
- **Anti-phishing policies**: SPF/DKIM/DMARC enforcement, unauthenticated sender indicators in Outlook
- **DMARC policy honoring**: Respects `p=quarantine` and `p=reject` policies
- **Implicit email authentication**: Sender reputation, history, behavioral analysis beyond SPF/DKIM/DMARC
- **Tenant Allow/Block List**: Manual spoofed sender allow/block entries

**Defender for Office 365 (E5/P2)**:
- **Impersonation protection**: Protects specific users and domains from impersonation (display name + domain similarity)
- **Mailbox intelligence**: Learns user communication patterns, flags anomalous senders
- **Campaign Views**: ML-based clustering of coordinated phishing campaigns
- **Attack simulation training**: Simulated phishing for user training
- **Safe Links**: Real-time URL detonation and rewriting
- **Safe Attachments**: Sandbox detonation of attachments
- **Automated Investigation and Response (AIR)**: Automated threat investigation and remediation

---

## 9. Google Workspace Email Forensics

### 9.1 Admin Console Investigation Tools

```
# Access: admin.google.com > Security > Investigation Tool
# (Requires Enterprise/Education Plus license)

# Search by sender
Data source: Gmail log events
Condition: Sender is attacker@evil.com
Date range: Last 30 days

# Search by message ID
Data source: Gmail log events
Condition: Message ID is <message-id@domain>

# Search by subject
Data source: Gmail log events
Condition: Subject contains "Wire Transfer"
```

### 9.2 Gmail Log Events (Admin Console > Reports)

Key log fields:

| Field | Purpose |
|-------|---------|
| `actor.email` | User whose mailbox is affected |
| `event.name` | Action type (receive, send, view) |
| `source_ip` | IP address of action |
| `message_id` | RFC 5322 Message-ID |
| `subject` | Email subject |
| `is_spam` | Spam classification |
| `destination` | Delivery destination |
| `smtp_reply_code` | Delivery status |

### 9.3 Google Workspace Security Investigation

```
# Login audit events
Admin Console > Reports > Audit and investigation > User log events

Key fields to review:
- Login type (normal, suspicious, via app password)
- IP address and geolocation
- Device information
- Login challenge issued (MFA)

# Email audit
Admin Console > Reports > Audit and investigation > Gmail log events

# Check for forwarding rules
Admin Console > Apps > Google Workspace > Gmail > Routing
Per-user: Admin Console > Directory > Users > user > Gmail settings

# Check for OAuth tokens
Admin Console > Security > API controls > App access control
Per-user: Admin Console > Directory > Users > user > Security > Connected apps
```

### 9.4 Google Vault (eDiscovery and Preservation)

```
# Preserve mailbox for investigation
Google Vault > Matters > Create Matter
> Add Hold > Gmail > Specific users
> Date range + search terms

# Search and export
Google Vault > Matters > [matter] > Search
> Service: Mail
> Search: from:attacker@evil.com OR subject:"wire transfer"
> Export: MBOX format (includes full headers)

# Export includes:
# - Original messages in MBOX format
# - Metadata CSV
# - Full email headers preserved
```

### 9.5 Google Workspace Email Deletion/Quarantine

```
# Delete emails from user mailboxes (Investigation Tool)
Admin Console > Security > Investigation Tool
> Search for malicious emails
> Select messages
> Action: Delete messages

# Bulk actions via GAM (Google Apps Manager CLI)
# Delete specific message
gam user victim@company.com delete message query "from:attacker@evil.com subject:wire"

# Search across org
gam all users print messages query "from:attacker@evil.com" | tee search_results.csv
```

### 9.6 Checking for Persistence (Compromised Account — Google)

```
# Check email forwarding
Admin Console > Directory > Users > [user] > User information > Email forwarding

# Check email delegates
Admin Console > Directory > Users > [user] > Email delegation

# Check via GAM
gam user victim@company.com show forwards
gam user victim@company.com show delegates
gam user victim@company.com show filters

# Check for suspicious filters (auto-delete, auto-archive, auto-forward)
# Filters that match keywords like "invoice", "payment", "security" and
# skip inbox / mark as read / auto-archive are classic BEC persistence

# Revoke OAuth tokens
gam user victim@company.com deprovision

# Revoke app passwords
gam user victim@company.com update isenforcedin2sv true

# Force sign-out of all sessions
gam user victim@company.com signout
```

---

## 10. Email as Evidence

### 10.1 Legal Admissibility Considerations

Email evidence must meet standards for **authenticity**, **integrity**, and **chain of custody** to be admissible. Key frameworks:

| Jurisdiction | Standard | Key Requirement |
|-------------|---------|-----------------|
| US Federal | FRE 901(b)(4) | Distinctive characteristics, content, context |
| US Federal | FRE 902(14) | Self-authentication for certified electronic records |
| EU | eIDAS Regulation | Electronic documents admissible, weight varies |
| UK | Civil Evidence Act 1995 | Hearsay admissible with notice |
| General | ISO/IEC 27037 | Guidelines for digital evidence identification, collection, acquisition |

### 10.2 Evidence Preservation Protocol

```
STEP 1: DOCUMENT THE SCENE
  □ Screenshot the email as displayed to the user (full screen including headers)
  □ Record date/time of preservation
  □ Record who is performing preservation
  □ Record the system/client used for viewing

STEP 2: PRESERVE ORIGINAL FORMAT
  □ Export as EML (plaintext with full headers) — PREFERRED
  □ Export as MSG (Outlook proprietary format) — acceptable
  □ Do NOT rely on PDF printouts alone (headers may be incomplete)
  □ Do NOT forward the email (modifies headers, adds forwarding artifacts)

  Outlook:
    - File > Save As > Outlook Message Format (.msg)
    - Or drag email to desktop (creates .msg)
    - For EML: File > Save As > Text Only, then manually save raw source

  Gmail:
    - Open email > Three dots > Show original > Download Original (.eml)

  Thunderbird:
    - File > Save As > File (.eml)

  M365 (Admin):
    - Compliance Search > Export results
    - eDiscovery > Export (PST format)

STEP 3: GENERATE CRYPTOGRAPHIC HASH
  □ SHA-256 hash of the EML/MSG file immediately after export
  □ Record hash value in evidence log
  □ Hash BEFORE any analysis tools touch the file

  sha256sum evidence_email.eml > evidence_email.sha256

STEP 4: PRESERVE HEADERS SEPARATELY
  □ Extract full headers to separate text file
  □ Hash the header file
  □ Headers are the most forensically valuable component

STEP 5: CHAIN OF CUSTODY LOG
  □ Date/time of each action
  □ Who performed the action
  □ What action was taken
  □ Hash verification at each transfer
```

### 10.3 Evidence Integrity Verification

```bash
# Generate evidence hashes
sha256sum evidence_email.eml > evidence.sha256
sha256sum evidence_email.msg >> evidence.sha256

# Verify on subsequent access
sha256sum -c evidence.sha256

# Sign evidence hash file with GPG
gpg --detach-sign --armor evidence.sha256

# Verify signature
gpg --verify evidence.sha256.asc evidence.sha256

# Timestamp proof (RFC 3161 timestamp)
openssl ts -query -data evidence_email.eml -no_nonce -sha256 -out evidence.tsq
# Submit to timestamp authority
curl -H "Content-Type: application/timestamp-query" \
  --data-binary @evidence.tsq \
  https://freetsa.org/tsr > evidence.tsr
```

### 10.4 Email Header Authentication as Evidence

When presenting email evidence, the authentication results provide corroboration:

```
AUTHENTICATION EVIDENCE HIERARCHY:

1. DKIM signature verification (strongest)
   - Proves: message body and signed headers were not modified after signing
   - Limitation: does not prove who sent it, only which domain signed it
   - Verification: re-verify DKIM signature against the domain's public key
     (note: key may be rotated; record current key at time of investigation)

2. SPF verification
   - Proves: sending IP was authorized by the domain owner
   - Limitation: only covers MAIL FROM, may not match display From

3. DMARC alignment
   - Proves: SPF or DKIM domain aligns with the From: header domain
   - Provides strongest assurance of sender identity

4. Received headers (from your MTA)
   - Proves: which server delivered the message and when
   - Only headers added by YOUR infrastructure are trustworthy

5. Server-side logs (strongest corroboration)
   - SMTP transaction logs on receiving MTA
   - Message trace / audit logs from email platform
   - These are independent records controlled by your organization
```

### 10.5 Common Evidence Challenges

| Challenge | Mitigation |
|-----------|-----------|
| "Email was fabricated" | DKIM signature verification + server logs + message trace |
| "Headers were modified" | Original EML with hash + DKIM verification |
| "Timestamp is wrong" | Cross-reference with MTA logs and multiple Received headers |
| "Someone else had access" | Login audit logs + MFA records + IP correlation |
| "I didn't send that email" | Audit log (MailItemsAccessed, Send) + IP address + device correlation |
| "Forwarded email altered" | Compare Message-ID and content hash with original |

---

## 11. Tools Reference

### 11.1 Email Analysis Tools

| Tool | Purpose | Install / Access |
|------|---------|-----------------|
| **eml_analyzer** | Web-based EML analysis: headers, IOCs, attachments, SpamAssassin | Docker: `docker-compose up` (github.com/ninoseki/eml_analyzer) |
| **oletools** | Office document malware analysis suite | `pip install -U oletools[full]` (github.com/decalage2/oletools) |
| **MXToolbox Header Analyzer** | Online email header parsing and hop analysis | mxtoolbox.com/EmailHeaders.aspx |
| **Google Admin Toolbox** | Email header analysis | toolbox.googleapps.com/apps/messageheader |
| **msgconvert** | Convert MSG to EML format | `apt install libemail-outlook-message-perl` |
| **munpack** | Extract MIME attachments | `apt install mpack` |
| **dkimpy** | DKIM signature verification | `pip install dkimpy` |
| **spfquery** | SPF record validation | `apt install spfquery` |
| **SpamAssassin** | Email spam/phishing scoring | `apt install spamassassin` |
| **PhishTool** | Commercial phishing analysis platform | phishtool.com |

### 11.2 Attachment and Payload Analysis Tools

| Tool | Purpose | Install |
|------|---------|---------|
| **olevba** | VBA macro extraction and analysis | Part of oletools |
| **mraptor** | Malicious macro detection | Part of oletools |
| **msodde** | DDE/DDEAUTO link detection | Part of oletools |
| **rtfobj** | RTF embedded object extraction | Part of oletools |
| **oleobj** | OLE embedded object extraction | Part of oletools |
| **oleid** | OLE file triage and risk assessment | Part of oletools |
| **pdfid** | PDF structure analysis | `pip install pdfid` |
| **pdf-parser** | PDF object and stream analysis | `pip install pdf-parser` |
| **YARA** | Pattern-matching for malware classification | `apt install yara` |
| **exiftool** | Metadata extraction from files | `apt install exiftool` |
| **file / libmagic** | File type identification | Built into most Linux distros |
| **CyberChef** | Data decoding and transformation | gchq.github.io/CyberChef |

### 11.3 URL and Domain Intelligence Tools

| Tool | Purpose | Access |
|------|---------|--------|
| **urlscan.io** | URL scanning and screenshot capture | urlscan.io (API available) |
| **VirusTotal** | Multi-engine URL/file scanning | virustotal.com (API available) |
| **PhishTank** | Community phishing URL database | phishtank.org |
| **URLhaus** | Malware URL database | urlhaus.abuse.ch |
| **whois** | Domain registration lookup | `whois domain.com` |
| **crt.sh** | Certificate Transparency log search | crt.sh |
| **dnstwist** | Domain permutation and lookalike detection | `pip install dnstwist` |
| **Shodan** | IP and host intelligence | shodan.io |
| **SecurityTrails** | Historical DNS and WHOIS | securitytrails.com |
| **RiskIQ / PassiveTotal** | Passive DNS and threat infrastructure | community.riskiq.com |

### 11.4 Command-Line Quick Reference

```bash
# === HEADER ANALYSIS ===
# View raw headers
formail -X "" < email.eml | head -100

# Extract specific header
formail -x "Authentication-Results" < email.eml

# Parse Received chain
grep -i "^Received:" email.eml

# Extract all IPs from headers
grep -oP '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}' email.eml | sort -u

# === AUTHENTICATION CHECKS ===
# Verify DKIM
dkimverify < email.eml

# Check SPF
dig +short TXT example.com | grep "v=spf1"

# Check DMARC
dig +short TXT _dmarc.example.com

# Check DKIM selector
dig +short TXT selector._domainkey.example.com

# Check MX records
dig +short MX example.com

# === ATTACHMENT HANDLING ===
# Extract attachments
munpack email.eml

# Hash all extracted files
find . -maxdepth 1 -type f -newer email.eml -exec sha256sum {} \;

# Quick triage Office file
oleid suspicious.docx

# Extract macros
olevba suspicious.docm

# Check for DDE
msodde suspicious.docx

# === URL ANALYSIS ===
# Extract URLs
grep -oP 'https?://[^\s"<>]+' email.eml | sort -u

# Check domain age
whois suspicious-domain.com | grep -i "creation"

# Generate domain permutations for lookalike detection
dnstwist example.com

# Expand shortened URL
curl -sIL "https://bit.ly/xxx" 2>&1 | grep -i "^location:"

# === REPUTATION CHECKS ===
# Check IP reputation (AbuseIPDB)
curl -s "https://api.abuseipdb.com/api/v2/check?ipAddress=1.2.3.4" \
  -H "Key: YOUR_KEY" -H "Accept: application/json"

# Check domain on VirusTotal
curl -s "https://www.virustotal.com/api/v3/domains/suspicious.com" \
  -H "x-apikey: YOUR_KEY"

# === M365 POWERSHELL ===
# Quick compromised account check
Connect-ExchangeOnline
Get-InboxRule -Mailbox user@company.com | FL Name,ForwardTo,RedirectTo,DeleteMessage
Get-Mailbox user@company.com | FL ForwardingAddress,ForwardingSMTPAddress
Search-UnifiedAuditLog -UserIds user@company.com -Operations "New-InboxRule" -StartDate (Get-Date).AddDays(-30) -EndDate (Get-Date)
```

---

## Appendix A: Email Authentication Decision Tree

```
                        ┌─────────────────────┐
                        │  Received Email      │
                        └──────────┬──────────┘
                                   │
                        ┌──────────▼──────────┐
                        │  Check SPF           │
                        │  (MAIL FROM domain)  │
                        └──────────┬──────────┘
                          ┌────────┼────────┐
                        pass    fail     none
                          │      │         │
                        ┌─▼──────▼─────────▼─┐
                        │  Check DKIM          │
                        │  (d= domain)         │
                        └──────────┬──────────┘
                          ┌────────┼────────┐
                        pass    fail     none
                          │      │         │
                        ┌─▼──────▼─────────▼──┐
                        │  Check DMARC          │
                        │  Alignment             │
                        │  (From: vs SPF/DKIM)   │
                        └──────────┬────────────┘
                          ┌────────┼────────┐
                        pass    fail     none
                          │      │         │
                          │    ┌─▼────┐    │
                          │    │Policy│    │
                          │    │p=?   │    │
                          │    └─┬────┘    │
                          │  ┌───┼───┐     │
                          │ none quar rej  │
                          │  │    │    │   │
                          ▼  ▼    ▼    ▼   ▼
                       DELIVER  JUNK  REJECT  DELIVER
                       (monitor)             (no policy)
```

## Appendix B: Phishing Indicators Scoring Matrix

Use this scoring matrix to quickly assess phishing likelihood:

| Indicator | Points | Notes |
|-----------|:------:|-------|
| SPF fail | +3 | Sender IP not authorized |
| DKIM fail | +3 | Message modified or forged sig |
| DMARC fail | +4 | Strongest authentication failure |
| Display name spoofs known contact | +3 | Compare against GAL/directory |
| Reply-To differs from From | +2 | Classic BEC indicator |
| Reply-To uses free email service | +3 | Business email from Gmail/Yahoo |
| Domain registered < 30 days | +4 | Newly registered for campaign |
| Lookalike domain (edit distance <= 2) | +4 | Typosquatting/homoglyph |
| Urgency language | +2 | "Immediately", "ASAP", "today" |
| Financial action requested | +3 | Wire, gift card, crypto, payment |
| Request for secrecy | +2 | "Don't tell anyone", "confidential" |
| Unusual sending time for sender | +1 | 3 AM from sender normally in US EST |
| Embedded URLs to non-org domains | +2 | Links not matching sender domain |
| URL uses IP address instead of domain | +3 | IP-based URLs almost always malicious |
| Attachment with macros | +3 | .docm, .xlsm, or OLE with VBA |
| Password-protected archive attachment | +3 | Bypasses scanning |
| HTML smuggling attachment | +4 | Advanced delivery technique |
| First-time sender | +1 | No prior communication history |
| Geolocation mismatch (IP vs claimed sender) | +2 | Sender claims US, IP in Nigeria |
| Missing or minimal SMTP TLS | +1 | `with ESMTP` instead of `ESMTPS` |

**Scoring**: 0-3 Low | 4-7 Medium | 8-12 High | 13+ Critical

---

*NERF Training Module — Email Forensics Deep Reference*
*Generated: 2026-03-14*
*Sources: IANA Message Headers Registry (RFC 5322bis), Microsoft Defender for Office 365 documentation, oletools (decalage2), eml_analyzer (ninoseki), MXToolbox, RFC 5322, RFC 7208, RFC 6376, RFC 7489, RFC 8601, RFC 8617*
