mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-20 06:20:58 +03:00
Initial commit - 611 cybersecurity skills across all subdomains
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
---
|
||||
name: building-phishing-reporting-button-workflow
|
||||
description: Implement a phishing report button in email clients with automated triage workflow that analyzes user-reported suspicious emails and provides feedback to reporters.
|
||||
domain: cybersecurity
|
||||
subdomain: phishing-defense
|
||||
tags: [phishing-reporting, email-security, incident-response, security-awareness, outlook, microsoft-365, soar]
|
||||
version: "1.0"
|
||||
author: mahipal
|
||||
license: MIT
|
||||
---
|
||||
# Building Phishing Reporting Button Workflow
|
||||
|
||||
## Overview
|
||||
A phishing reporting button empowers users to flag suspicious emails directly from their email client, creating a critical feedback loop between end users and the security operations center. Microsoft's built-in Report button is now the recommended approach, replacing the deprecated Report Message and Report Phishing add-ins. When combined with automated triage using SOAR platforms, reported emails can be classified, IOCs extracted, and remediation actions taken within minutes. Organizations with effective phishing reporting programs see 70%+ report rates in phishing simulations.
|
||||
|
||||
## Prerequisites
|
||||
- Microsoft 365 or Google Workspace with administrative access
|
||||
- SOAR platform or automation capability (Microsoft Sentinel, Splunk SOAR, Cortex XSOAR)
|
||||
- Dedicated reporting mailbox for phishing submissions
|
||||
- Email security gateway with message retraction capability
|
||||
- Security awareness training platform for feedback loop
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### Step 1: Deploy Phishing Report Button
|
||||
- Enable Microsoft built-in Report button via Security & Compliance Center
|
||||
- Configure user reported settings: route to reporting mailbox and Microsoft
|
||||
- For third-party: deploy KnowBe4 Phish Alert Button or Cofense Reporter
|
||||
- Verify button appears in Outlook desktop, web, and mobile clients
|
||||
- Configure report options: Report Phishing, Report Junk, Report Not Junk
|
||||
|
||||
### Step 2: Build Automated Triage Pipeline
|
||||
- Configure reporting mailbox monitored by SOAR platform
|
||||
- Auto-extract IOCs from reported emails: URLs, attachments, sender info, headers
|
||||
- Submit URLs to VirusTotal, URLScan.io for reputation check
|
||||
- Submit attachments to sandbox for dynamic analysis
|
||||
- Check sender against known threat intelligence feeds
|
||||
- Auto-classify: confirmed phishing, spam, simulation, legitimate
|
||||
|
||||
### Step 3: Implement Response Actions
|
||||
- Confirmed phishing: auto-retract from all inboxes, block sender domain
|
||||
- Confirmed spam: move to junk for all recipients
|
||||
- Simulation email: mark as correctly reported, credit user
|
||||
- Legitimate email: return to inbox, notify reporter
|
||||
- Generate IOC report for threat intelligence team
|
||||
|
||||
### Step 4: Create Feedback Loop
|
||||
- Send automated thank-you response to reporter within 5 minutes
|
||||
- Include classification result when analysis completes
|
||||
- Track reporter accuracy and engagement metrics
|
||||
- Recognize top reporters in monthly security newsletter
|
||||
- Feed reporting metrics into security awareness training program
|
||||
|
||||
### Step 5: Measure and Optimize
|
||||
- Track mean time to triage (target: under 10 minutes automated)
|
||||
- Monitor report volume trends and false positive rates
|
||||
- Measure user reporting rate in phishing simulations
|
||||
- Report on confirmed threats caught by user reports vs. gateway
|
||||
- Optimize automation rules based on classification accuracy
|
||||
|
||||
## Tools & Resources
|
||||
- **Microsoft Report Button**: Built-in Outlook phishing reporting
|
||||
- **Cofense Reporter + Triage**: Enterprise phishing reporting and automated analysis
|
||||
- **KnowBe4 Phish Alert Button**: Integrated reporting with simulation platform
|
||||
- **Microsoft Sentinel**: SOAR automation for triage workflow
|
||||
- **Proofpoint CLEAR**: Closed-loop email analysis and response
|
||||
|
||||
## Validation
|
||||
- Report button visible and functional across all Outlook platforms
|
||||
- Reported email arrives in dedicated mailbox within 60 seconds
|
||||
- Automated triage classifies test phishing email correctly
|
||||
- Auto-retraction removes confirmed phishing from all inboxes
|
||||
- Reporter receives feedback notification with classification
|
||||
- Metrics dashboard shows report volume and accuracy trends
|
||||
@@ -0,0 +1,28 @@
|
||||
# Phishing Reporting Button Workflow Template
|
||||
|
||||
## Reporting Button Configuration
|
||||
| Setting | Value | Status |
|
||||
|---|---|---|
|
||||
| Button type | Microsoft built-in Report | |
|
||||
| Reporting mailbox | phishing-reports@company.com | |
|
||||
| Also send to Microsoft | Yes | |
|
||||
| Supported platforms | Desktop, Web, Mobile | |
|
||||
|
||||
## Triage Automation Rules
|
||||
| Classification | Criteria | Auto-Action |
|
||||
|---|---|---|
|
||||
| Confirmed Phishing | Score >= 50 | Retract + Block sender |
|
||||
| Suspicious | Score 25-49 | Escalate to SOC analyst |
|
||||
| Spam | Score 10-24 | Move to junk for all |
|
||||
| Simulation | Matches sim subject | Credit reporter |
|
||||
| Clean | Score < 10 | Return to inbox |
|
||||
|
||||
## Reporting Metrics Dashboard
|
||||
| Metric | Target | Current |
|
||||
|---|---|---|
|
||||
| Report volume (monthly) | | |
|
||||
| Mean time to triage | < 10 min | |
|
||||
| Confirmed phishing caught | | |
|
||||
| User report rate (sim) | > 70% | |
|
||||
| False positive rate | < 30% | |
|
||||
| Top reporter recognition | Monthly | |
|
||||
@@ -0,0 +1,28 @@
|
||||
# Standards & References: Building Phishing Reporting Button Workflow
|
||||
|
||||
## MITRE ATT&CK References
|
||||
- **T1566.001**: Phishing: Spearphishing Attachment
|
||||
- **T1566.002**: Phishing: Spearphishing Link
|
||||
- **T1204**: User Execution
|
||||
- **D3-RERE**: User Reporting (MITRE D3FEND)
|
||||
|
||||
## Industry Standards
|
||||
- **NIST SP 800-61 Rev.2**: Computer Security Incident Handling Guide
|
||||
- **CIS Controls v8 Control 14**: Security Awareness and Skills Training
|
||||
- **ISO 27001 A.6.3**: Information Security Awareness, Education and Training
|
||||
|
||||
## Reporting Platform Comparison
|
||||
| Platform | Type | Integration | Auto-Triage |
|
||||
|---|---|---|---|
|
||||
| Microsoft Report Button | Built-in | M365 native | Via Sentinel/API |
|
||||
| Cofense Reporter + Triage | Third-party | M365, Google | Yes (Cofense Triage) |
|
||||
| KnowBe4 PAB | Third-party | M365, Google | Yes (KMSAT) |
|
||||
| Proofpoint CLEAR | Third-party | M365, Google | Yes (built-in) |
|
||||
| Hoxhunt | Third-party | M365, Google | Yes (AI-powered) |
|
||||
|
||||
## Key Metrics
|
||||
- **Report Rate**: Percentage of phishing simulations reported (target: >70%)
|
||||
- **Mean Time to Triage**: Time from report to classification (target: <10 min)
|
||||
- **False Positive Rate**: Legitimate emails reported as phishing
|
||||
- **Threat Catch Rate**: Real threats first detected by user reports
|
||||
- **Reporter Accuracy**: Percentage of reports that are actual threats
|
||||
@@ -0,0 +1,69 @@
|
||||
# Workflows: Building Phishing Reporting Button Workflow
|
||||
|
||||
## Workflow 1: Automated Phishing Report Triage
|
||||
|
||||
```
|
||||
User clicks "Report Phishing" button
|
||||
|
|
||||
v
|
||||
[Email forwarded to reporting mailbox]
|
||||
+-- Original email preserved with full headers
|
||||
+-- Reporter identity recorded
|
||||
|
|
||||
v
|
||||
[SOAR platform ingests report]
|
||||
|
|
||||
v
|
||||
[Automated IOC extraction]
|
||||
+-- Extract sender address and domain
|
||||
+-- Extract all URLs from body
|
||||
+-- Extract attachment hashes (MD5, SHA256)
|
||||
+-- Parse email headers for authentication results
|
||||
|
|
||||
v
|
||||
[Automated analysis (parallel)]
|
||||
+-- URLs -> VirusTotal, URLScan.io, PhishTank
|
||||
+-- Attachments -> Sandbox detonation
|
||||
+-- Sender -> Threat intelligence lookup
|
||||
+-- Headers -> SPF/DKIM/DMARC validation
|
||||
|
|
||||
v
|
||||
[Classification]
|
||||
+-- CONFIRMED PHISHING: High-confidence malicious
|
||||
+-- SUSPICIOUS: Moderate indicators, needs analyst review
|
||||
+-- SPAM: Unwanted but not malicious
|
||||
+-- SIMULATION: Matches internal phishing test
|
||||
+-- CLEAN: Legitimate email, false report
|
||||
|
|
||||
v
|
||||
[Automated response by classification]
|
||||
+-- PHISHING: Retract from all inboxes + block sender
|
||||
+-- SUSPICIOUS: Escalate to SOC analyst
|
||||
+-- SPAM: Move to junk for all recipients
|
||||
+-- SIMULATION: Credit reporter in training platform
|
||||
+-- CLEAN: Return to inbox
|
||||
|
|
||||
v
|
||||
[Feedback to reporter]
|
||||
+-- "Thank you for reporting" (immediate)
|
||||
+-- Classification result (when complete)
|
||||
+-- Training tip (if false positive)
|
||||
```
|
||||
|
||||
## Workflow 2: SOC Analyst Escalation
|
||||
|
||||
```
|
||||
SOAR classifies report as SUSPICIOUS
|
||||
|
|
||||
v
|
||||
[SOC analyst reviews]
|
||||
+-- Examine full email content and headers
|
||||
+-- Verify automated analysis results
|
||||
+-- Check for similar reports from other users
|
||||
|
|
||||
v
|
||||
[Analyst decision]
|
||||
+-- Confirm malicious --> Trigger remediation playbook
|
||||
+-- Confirm clean --> Close and notify reporter
|
||||
+-- Need more info --> Contact reporter for context
|
||||
```
|
||||
@@ -0,0 +1,304 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Phishing Report Triage Engine
|
||||
|
||||
Processes user-reported phishing emails, extracts IOCs,
|
||||
performs automated analysis, and classifies the report.
|
||||
|
||||
Usage:
|
||||
python process.py triage --eml-file reported_email.eml
|
||||
python process.py metrics --reports-file reports.json
|
||||
python process.py extract-iocs --eml-file reported_email.eml
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import hashlib
|
||||
import sys
|
||||
from dataclasses import dataclass, field, asdict
|
||||
from collections import Counter
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
@dataclass
|
||||
class ExtractedIOCs:
|
||||
"""IOCs extracted from reported email."""
|
||||
sender_address: str = ""
|
||||
sender_domain: str = ""
|
||||
reply_to: str = ""
|
||||
urls: list = field(default_factory=list)
|
||||
domains: list = field(default_factory=list)
|
||||
attachment_names: list = field(default_factory=list)
|
||||
attachment_hashes: list = field(default_factory=list)
|
||||
ip_addresses: list = field(default_factory=list)
|
||||
subject: str = ""
|
||||
|
||||
|
||||
@dataclass
|
||||
class TriageResult:
|
||||
"""Triage classification result."""
|
||||
report_id: str = ""
|
||||
reporter: str = ""
|
||||
classification: str = ""
|
||||
confidence: float = 0.0
|
||||
iocs: dict = field(default_factory=dict)
|
||||
indicators: list = field(default_factory=list)
|
||||
recommended_action: str = ""
|
||||
auto_actionable: bool = False
|
||||
|
||||
|
||||
@dataclass
|
||||
class ReportingMetrics:
|
||||
"""Phishing reporting program metrics."""
|
||||
total_reports: int = 0
|
||||
confirmed_phishing: int = 0
|
||||
confirmed_spam: int = 0
|
||||
simulation_reports: int = 0
|
||||
false_positives: int = 0
|
||||
mean_triage_time_min: float = 0.0
|
||||
top_reporters: list = field(default_factory=list)
|
||||
report_rate: float = 0.0
|
||||
|
||||
|
||||
PHISHING_INDICATORS = [
|
||||
(r'\burgent\b.*\b(action|response|attention)\b', "Urgency language", 15),
|
||||
(r'\b(verify|confirm|validate)\s+your\s+(account|identity|password)\b', "Credential request", 20),
|
||||
(r'\b(click|follow)\s+(here|this|the)\s+(link|button)\b', "Click-bait language", 10),
|
||||
(r'\b(suspended|locked|disabled|compromised)\s+(account|access)\b', "Fear language", 15),
|
||||
(r'\b(wire\s+transfer|payment|invoice|bank)\b', "Financial language", 10),
|
||||
(r'\bgift\s+card\b', "Gift card request", 20),
|
||||
(r'\bdo\s+not\s+(share|tell|discuss)\b', "Secrecy language", 15),
|
||||
]
|
||||
|
||||
|
||||
def extract_iocs(eml_content: str) -> ExtractedIOCs:
|
||||
"""Extract IOCs from email content."""
|
||||
iocs = ExtractedIOCs()
|
||||
|
||||
# Extract From
|
||||
from_match = re.search(r'^From:\s*(?:.*<)?([^>\s]+@[^>\s]+)', eml_content,
|
||||
re.MULTILINE | re.IGNORECASE)
|
||||
if from_match:
|
||||
iocs.sender_address = from_match.group(1).strip()
|
||||
domain_match = re.search(r'@([\w.-]+)', iocs.sender_address)
|
||||
if domain_match:
|
||||
iocs.sender_domain = domain_match.group(1)
|
||||
|
||||
# Extract Reply-To
|
||||
reply_match = re.search(r'^Reply-To:\s*(?:.*<)?([^>\s]+@[^>\s]+)', eml_content,
|
||||
re.MULTILINE | re.IGNORECASE)
|
||||
if reply_match:
|
||||
iocs.reply_to = reply_match.group(1).strip()
|
||||
|
||||
# Extract Subject
|
||||
subj_match = re.search(r'^Subject:\s*(.+)$', eml_content, re.MULTILINE | re.IGNORECASE)
|
||||
if subj_match:
|
||||
iocs.subject = subj_match.group(1).strip()
|
||||
|
||||
# Extract URLs
|
||||
urls = re.findall(r'https?://[^\s<>"\']+', eml_content)
|
||||
iocs.urls = list(set(urls))
|
||||
|
||||
# Extract domains from URLs
|
||||
for url in iocs.urls:
|
||||
domain_match = re.search(r'https?://([^/:\s]+)', url)
|
||||
if domain_match:
|
||||
domain = domain_match.group(1).lower()
|
||||
if domain not in iocs.domains:
|
||||
iocs.domains.append(domain)
|
||||
|
||||
# Extract IP addresses from headers
|
||||
ips = re.findall(r'\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\b', eml_content)
|
||||
iocs.ip_addresses = list(set(ips))
|
||||
|
||||
# Extract attachment filenames
|
||||
attachments = re.findall(
|
||||
r'filename[*]?=(?:"([^"]+)"|([^\s;]+))',
|
||||
eml_content, re.IGNORECASE
|
||||
)
|
||||
for groups in attachments:
|
||||
name = groups[0] or groups[1]
|
||||
if name and name not in iocs.attachment_names:
|
||||
iocs.attachment_names.append(name)
|
||||
|
||||
return iocs
|
||||
|
||||
|
||||
def triage_report(eml_content: str, simulation_subjects: list = None) -> TriageResult:
|
||||
"""Classify a reported email."""
|
||||
result = TriageResult()
|
||||
iocs = extract_iocs(eml_content)
|
||||
result.iocs = asdict(iocs)
|
||||
|
||||
score = 0
|
||||
body_lower = eml_content.lower()
|
||||
|
||||
# Check if it's a known simulation
|
||||
if simulation_subjects:
|
||||
for sim_subj in simulation_subjects:
|
||||
if sim_subj.lower() in iocs.subject.lower():
|
||||
result.classification = "simulation"
|
||||
result.confidence = 0.95
|
||||
result.recommended_action = "Credit reporter in training platform"
|
||||
result.auto_actionable = True
|
||||
return result
|
||||
|
||||
# Check phishing indicators
|
||||
for pattern, desc, weight in PHISHING_INDICATORS:
|
||||
if re.search(pattern, body_lower):
|
||||
result.indicators.append(desc)
|
||||
score += weight
|
||||
|
||||
# Check for authentication failures
|
||||
auth_results = re.search(r'Authentication-Results:.*?(spf=fail|dkim=fail|dmarc=fail)',
|
||||
eml_content, re.IGNORECASE | re.DOTALL)
|
||||
if auth_results:
|
||||
result.indicators.append(f"Authentication failure: {auth_results.group(1)}")
|
||||
score += 20
|
||||
|
||||
# Check Reply-To mismatch
|
||||
if iocs.reply_to and iocs.sender_address:
|
||||
reply_domain = re.search(r'@([\w.-]+)', iocs.reply_to)
|
||||
sender_domain = re.search(r'@([\w.-]+)', iocs.sender_address)
|
||||
if reply_domain and sender_domain:
|
||||
if reply_domain.group(1) != sender_domain.group(1):
|
||||
result.indicators.append("Reply-To domain mismatch")
|
||||
score += 15
|
||||
|
||||
# Check for suspicious attachment types
|
||||
risky_extensions = ['.exe', '.scr', '.bat', '.cmd', '.ps1', '.vbs',
|
||||
'.js', '.wsf', '.hta', '.iso', '.img']
|
||||
for att in iocs.attachment_names:
|
||||
if any(att.lower().endswith(ext) for ext in risky_extensions):
|
||||
result.indicators.append(f"Risky attachment: {att}")
|
||||
score += 25
|
||||
|
||||
# Classify
|
||||
if score >= 50:
|
||||
result.classification = "confirmed_phishing"
|
||||
result.confidence = min(score / 100, 0.95)
|
||||
result.recommended_action = "Retract from all inboxes, block sender domain"
|
||||
result.auto_actionable = True
|
||||
elif score >= 25:
|
||||
result.classification = "suspicious"
|
||||
result.confidence = score / 100
|
||||
result.recommended_action = "Escalate to SOC analyst for manual review"
|
||||
result.auto_actionable = False
|
||||
elif score >= 10:
|
||||
result.classification = "spam"
|
||||
result.confidence = 0.6
|
||||
result.recommended_action = "Move to junk for all recipients"
|
||||
result.auto_actionable = True
|
||||
else:
|
||||
result.classification = "clean"
|
||||
result.confidence = 0.7
|
||||
result.recommended_action = "Return to inbox, notify reporter"
|
||||
result.auto_actionable = True
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def calculate_metrics(reports: list) -> ReportingMetrics:
|
||||
"""Calculate phishing reporting program metrics."""
|
||||
metrics = ReportingMetrics()
|
||||
metrics.total_reports = len(reports)
|
||||
|
||||
reporter_counts = Counter()
|
||||
triage_times = []
|
||||
|
||||
for report in reports:
|
||||
classification = report.get("classification", "")
|
||||
if classification == "confirmed_phishing":
|
||||
metrics.confirmed_phishing += 1
|
||||
elif classification == "spam":
|
||||
metrics.confirmed_spam += 1
|
||||
elif classification == "simulation":
|
||||
metrics.simulation_reports += 1
|
||||
elif classification == "clean":
|
||||
metrics.false_positives += 1
|
||||
|
||||
reporter = report.get("reporter", "")
|
||||
if reporter:
|
||||
reporter_counts[reporter] += 1
|
||||
|
||||
triage_time = report.get("triage_time_minutes", 0)
|
||||
if triage_time > 0:
|
||||
triage_times.append(triage_time)
|
||||
|
||||
if triage_times:
|
||||
metrics.mean_triage_time_min = sum(triage_times) / len(triage_times)
|
||||
|
||||
metrics.top_reporters = [
|
||||
{"reporter": r, "count": c}
|
||||
for r, c in reporter_counts.most_common(10)
|
||||
]
|
||||
|
||||
if metrics.total_reports > 0:
|
||||
metrics.report_rate = (
|
||||
(metrics.confirmed_phishing + metrics.simulation_reports) /
|
||||
metrics.total_reports * 100
|
||||
)
|
||||
|
||||
return metrics
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Phishing Report Triage Engine")
|
||||
subparsers = parser.add_subparsers(dest="command")
|
||||
|
||||
triage_parser = subparsers.add_parser("triage", help="Triage reported email")
|
||||
triage_parser.add_argument("--eml-file", required=True)
|
||||
triage_parser.add_argument("--sim-subjects", nargs="*", default=[])
|
||||
|
||||
metrics_parser = subparsers.add_parser("metrics", help="Calculate reporting metrics")
|
||||
metrics_parser.add_argument("--reports-file", required=True)
|
||||
|
||||
ioc_parser = subparsers.add_parser("extract-iocs", help="Extract IOCs from email")
|
||||
ioc_parser.add_argument("--eml-file", required=True)
|
||||
|
||||
parser.add_argument("--json", action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.command == "triage":
|
||||
with open(args.eml_file, 'r', errors='replace') as f:
|
||||
content = f.read()
|
||||
result = triage_report(content, args.sim_subjects)
|
||||
if args.json:
|
||||
print(json.dumps(asdict(result), indent=2))
|
||||
else:
|
||||
print(f"Classification: {result.classification}")
|
||||
print(f"Confidence: {result.confidence:.0%}")
|
||||
print(f"Action: {result.recommended_action}")
|
||||
print(f"Auto-actionable: {'Yes' if result.auto_actionable else 'No'}")
|
||||
if result.indicators:
|
||||
print(f"Indicators:")
|
||||
for ind in result.indicators:
|
||||
print(f" - {ind}")
|
||||
|
||||
elif args.command == "metrics":
|
||||
with open(args.reports_file) as f:
|
||||
reports = json.load(f)
|
||||
result = calculate_metrics(reports)
|
||||
if args.json:
|
||||
print(json.dumps(asdict(result), indent=2))
|
||||
else:
|
||||
print(f"Total reports: {result.total_reports}")
|
||||
print(f"Confirmed phishing: {result.confirmed_phishing}")
|
||||
print(f"Spam: {result.confirmed_spam}")
|
||||
print(f"Simulations reported: {result.simulation_reports}")
|
||||
print(f"False positives: {result.false_positives}")
|
||||
print(f"Mean triage time: {result.mean_triage_time_min:.1f} min")
|
||||
|
||||
elif args.command == "extract-iocs":
|
||||
with open(args.eml_file, 'r', errors='replace') as f:
|
||||
content = f.read()
|
||||
iocs = extract_iocs(content)
|
||||
print(json.dumps(asdict(iocs), indent=2))
|
||||
|
||||
else:
|
||||
parser.print_help()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user