penetration testing

Conducting Social Engineering Penetration Test

Design and execute a social engineering penetration test including phishing, vishing, smishing, and physical pretexting campaigns to measure human security resilience and identify training gaps.

gophishosintphishingpretextingred-teamsecurity-awarenesssetsocial-engineering
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

Overview

Social engineering penetration testing assesses an organization's human attack surface through controlled simulation of real-world deception techniques. According to Verizon DBIR 2024, the human element is involved in approximately 68% of all breaches, with phishing remaining the dominant initial access vector. This skill covers phishing, vishing (voice phishing), smishing (SMS phishing), and physical pretexting campaigns using tools like GoPhish, the Social Engineer Toolkit (SET), and Evilginx.

When to Use

  • When conducting security assessments that involve conducting social engineering penetration test
  • When following incident response procedures for related security events
  • When performing scheduled security testing or auditing activities
  • When validating security controls through hands-on testing

Prerequisites

  • Written authorization from senior management (CISO/CTO)
  • Legal review confirming compliance with local laws (CFAA, GDPR, etc.)
  • Defined scope: target employee groups, attack types, exclusions
  • GoPhish server, domain for phishing infrastructure, VPS
  • OSINT tools: Maltego, theHarvester, LinkedIn scraping tools
  • Coordination with HR and Legal for employee notification post-test

Phase 1 — OSINT and Target Profiling

Employee Reconnaissance

# Email harvesting
theHarvester -d targetcorp.com -b all -l 500 -f harvester_results
 
# LinkedIn OSINT (manual + tools)
# Gather: names, roles, departments, email format
# Identify: new hires, IT admins, finance team, executives
 
# Email format discovery
# Check: first.last@, flast@, firstl@
# Verify with: hunter.io, phonebook.cz, email-checker.net
 
# Social media OSINT
# Twitter/X: employees posting about work tools/frustrations
# Facebook: corporate event photos, office layout
# GitHub: employee repos with corporate email addresses
 
# Domain intelligence
dig targetcorp.com MX +short
dig targetcorp.com TXT +short
# Check for SPF, DKIM, DMARC records
# Weak DMARC = easier email spoofing
 
# Check breach databases (authorized)
# HaveIBeenPwned API for corporate emails
# Identify employees with compromised credentials

Target Selection Matrix

Group Count Pretext Attack Vector
Finance 15 Invoice approval Phishing (credential harvest)
IT Help Desk 8 Password reset Vishing
Executives 5 Board meeting update Spear phishing
New Hires (< 90 days) 12 HR onboarding form Phishing (payload)
All Employees 200 IT security update Broad phishing

Phase 2 — Phishing Campaign

Infrastructure Setup

# Register lookalike domain
# targetcorp.com -> targetc0rp.com, targetcorp-secure.com, targetcorp.net
 
# Set up GoPhish server
sudo apt install gophish
# Edit config.json for admin and phishing server ports
gophish
 
# Configure sending profile in GoPhish
# SMTP server: mail.attackdomain.com
# From: it-security@targetcorp-secure.com
# Headers: proper DKIM/SPF for attack domain
 
# Create landing page (credential harvesting)
# Clone legitimate login page (Office 365, Okta, etc.)
# GoPhish: Import Site -> https://login.microsoftonline.com
# Enable: Capture Credentials, Capture Passwords
# Redirect to real site after capture
 
# Set up Evilginx for MFA bypass (authorized testing only)
evilginx2
: config domain attackdomain.com
: config ipv4 <server_ip>
: phishlets hostname o365 login.targetcorp-secure.com
: phishlets enable o365
: lures create o365
: lures get-url 0

GoPhish Campaign Configuration

{
  "campaign": {
    "name": "IT Security Update - Q1 2025",
    "template": {
      "name": "Mandatory Security Training",
      "subject": "Action Required: Complete Security Awareness Training by Friday",
      "html": "<html>...[branded email with urgency]...</html>",
      "from": "IT Security Team <security@targetcorp-secure.com>"
    },
    "landing_page": "Office 365 Login Clone",
    "sending_profile": "Phishing SMTP",
    "groups": ["All Employees - Batch 1"],
    "launch_date": "2025-03-10T09:00:00Z",
    "send_by_date": "2025-03-10T12:00:00Z"
  }
}

Phishing Email Templates by Pretext

Template 1 — IT Security Update:

Subject: [Action Required] Mandatory Password Reset - Security Incident
From: IT Security <security@targetcorp-secure.com>
 
Dear {FirstName},
 
Our security team has detected unauthorized access attempts on our systems.
As a precautionary measure, all employees must reset their passwords immediately.
 
Please click below to reset your password within the next 24 hours:
 
[Reset Password Now] -> {phishing_url}
 
Failure to comply may result in temporary account suspension.
 
Thank you,
IT Security Team

Template 2 — Finance Invoice:

Subject: Invoice #INV-2025-4821 - Approval Required
From: Accounts Payable <ap@targetcorp-secure.com>
 
Hi {FirstName},
 
Please review and approve the attached invoice from our vendor.
Amount: $47,250.00 | Due: March 15, 2025
 
[View Invoice] -> {phishing_url}
 
Best regards,
Accounts Payable

Phase 3 — Vishing Campaign

Call Script Template

Pretext: IT Help Desk calling about suspicious login
 
Caller: "Hi, this is [Name] from the IT Help Desk. Am I speaking with [Target Name]?"
 
[Wait for confirmation]
 
Caller: "We've detected some unusual login activity on your account from an
unrecognized location. For your protection, I need to verify your identity
before we can investigate further."
 
Caller: "Can you confirm your employee ID and the email address associated
with your account?"
 
[Record responses]
 
Caller: "Thank you. I'm going to send you a verification link to confirm
it's really you. Can you click on it and enter your credentials so we can
secure your account?"
 
[Send phishing link via email/SMS during call]
 
Caller: "Great, I can see you've been verified. Your account is now secured.
If you notice any further issues, please call the help desk at [real number]."

Vishing Metrics to Track

Metric Description
Call answered Target picked up the phone
Engaged Target continued conversation past initial question
Information disclosed Target provided credentials, employee ID, or PII
Link clicked Target clicked the verification link
Credentials entered Target entered credentials on phishing page
Reported Target reported the call to security

Phase 4 — Physical Social Engineering

Physical Pretexting Scenarios

Scenario 1: Delivery Person
- Arrive with package labeled for executive
- Request access to deliver personally
- Attempt to tailgate through secure doors
- Drop USB drives in common areas
 
Scenario 2: IT Vendor
- Arrive with vendor badge (printed)
- Claim scheduled maintenance on network closet
- Attempt to access server rooms
- Install rogue wireless AP if access gained
 
Scenario 3: New Employee
- Arrive claiming first day orientation
- Request temporary badge
- Attempt to access restricted areas
- Photograph sensitive screens/documents
 
Evidence Collection:
- Body camera (if legally permitted and authorized)
- Photographs of accessed areas
- WiFi probe from rogue AP
- Notes on which doors/checkpoints bypassed

Phase 5 — Metrics and Analysis

Campaign Results Dashboard

Phishing Campaign Results:
├── Emails Sent: 200
├── Emails Delivered: 195 (97.5%)
├── Emails Opened: 142 (72.8%)
├── Links Clicked: 68 (34.9%)
├── Credentials Submitted: 31 (15.9%)
├── MFA Bypassed: 8 (4.1%)  [Evilginx]
├── Reported to SOC: 12 (6.2%)
└── No Action: 53 (27.2%)
 
Vishing Campaign Results:
├── Calls Made: 23
├── Calls Answered: 18 (78.3%)
├── Engaged in Conversation: 15 (65.2%)
├── Information Disclosed: 9 (39.1%)
├── Credentials Provided: 4 (17.4%)
└── Reported to Security: 2 (8.7%)
 
Physical Assessment:
├── Tailgating Successful: 3/5 attempts
├── USB Drives Plugged In: 2/10 dropped
├── Restricted Areas Accessed: 2/4 attempted
└── Challenged by Employee: 1 time

Risk Scoring

Attack Vector Success Rate Risk Level Priority
Phishing (credential harvest) 15.9% High P1
Vishing (info disclosure) 39.1% Critical P1
Physical tailgating 60% High P2
USB drop 20% Medium P3
Spear phishing (exec) 40% Critical P1

Phase 6 — Reporting and Recommendations

Remediation Priorities

Priority Recommendation Timeline
P1 Deploy phishing-resistant MFA (FIDO2/WebAuthn) 30 days
P1 Implement targeted security awareness training 14 days
P1 Deploy email gateway with URL rewriting 30 days
P2 Strengthen physical access controls (mantraps, visitor badges) 60 days
P2 Implement security champion program per department 30 days
P3 Deploy USB device control policy 30 days
P3 Establish phishing reporting button in email client 14 days

Tools Reference

Tool Purpose
GoPhish Phishing campaign management platform
Evilginx2 MFA bypass via reverse proxy phishing
Social Engineer Toolkit (SET) Social engineering attack framework
Maltego OSINT and relationship mapping
theHarvester Email and domain OSINT
King Phisher Phishing campaign tool
Modlishka Reverse proxy for credential interception

References

Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 3

api-reference.md1.5 KB

Social Engineering Penetration Test — API Reference

Libraries

Library Install Purpose
requests pip install requests GoPhish REST API client
gophish pip install gophish Official GoPhish Python client

GoPhish API Endpoints

Method Endpoint Description
GET /api/campaigns/ List all campaigns
GET /api/campaigns/{id}/results Campaign results and metrics
POST /api/campaigns/ Create new campaign
POST /api/templates/ Create email template
POST /api/groups/ Create target group
POST /api/smtp/ Create sending profile
POST /api/pages/ Create landing page

Campaign Metrics

Metric Formula
Open Rate emails_opened / emails_sent x 100
Click Rate links_clicked / emails_sent x 100
Submit Rate data_submitted / emails_sent x 100
Report Rate reported / emails_sent x 100

Social Engineering Vectors

Vector Tools
Email Phishing GoPhish, King Phisher
Vishing Pretext scripts, VoIP tools
Physical Badge cloning, tailgating
USB Drops Rubber Ducky, USB armory

External References

standards.md0.9 KB

Standards — Social Engineering Penetration Testing

Frameworks

MITRE ATT&CK Techniques

Technique ID Vector
Phishing: Spear Phishing Link T1566.002 Email with malicious URL
Phishing: Spear Phishing Attachment T1566.001 Email with payload
Phishing: Spear Phishing via Service T1566.003 Social media / messaging

Legal Considerations

  • Must have explicit written authorization
  • Cannot target personal email or devices without consent
  • GDPR compliance for EU employees
  • Cannot use real malware or destructive payloads
  • Results must be anonymized in reporting to protect individuals
workflows.md1.1 KB

Workflows — Social Engineering Penetration Testing

Campaign Lifecycle

Authorization & Scoping

    ├── OSINT & Target Profiling
    │   ├── Email harvesting
    │   ├── LinkedIn/social media reconnaissance
    │   └── Target group selection

    ├── Infrastructure Setup
    │   ├── Domain registration (lookalike)
    │   ├── GoPhish/Evilginx deployment
    │   ├── SMTP configuration (SPF/DKIM)
    │   └── Landing page creation

    ├── Campaign Execution
    │   ├── Phishing emails (batched sends)
    │   ├── Vishing calls
    │   ├── Physical pretexting
    │   └── USB drops

    ├── Monitoring & Data Collection
    │   ├── Email opens/clicks tracking
    │   ├── Credential captures
    │   ├── Call recordings/notes
    │   └── Physical access logs

    └── Reporting & Training
        ├── Metrics compilation
        ├── Risk scoring
        ├── Executive report
        └── Targeted training recommendations

Scripts 2

agent.py5.8 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Social engineering penetration test management agent using GoPhish API."""

import json
import sys
import argparse
from datetime import datetime

try:
    import requests
    requests.packages.urllib3.disable_warnings()
except ImportError:
    print("Install: pip install requests")
    sys.exit(1)


class GoPhishClient:
    """GoPhish API client for phishing campaign management."""

    def __init__(self, base_url, api_key):
        self.base_url = base_url.rstrip("/")
        self.headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}

    def _get(self, endpoint):
        resp = requests.get(f"{self.base_url}/api/{endpoint}", headers=self.headers, verify=False, timeout=30)
        resp.raise_for_status()
        return resp.json()

    def _post(self, endpoint, data):
        resp = requests.post(f"{self.base_url}/api/{endpoint}", headers=self.headers,
                             json=data, verify=False, timeout=30)
        resp.raise_for_status()
        return resp.json()

    def list_campaigns(self):
        return self._get("campaigns/")

    def get_campaign_results(self, campaign_id):
        return self._get(f"campaigns/{campaign_id}/results")

    def create_sending_profile(self, name, host, from_addr, username, password):
        return self._post("smtp/", {
            "name": name, "host": host, "from_address": from_addr,
            "username": username, "password": password, "ignore_cert_errors": True,
        })

    def create_template(self, name, subject, html, text=""):
        return self._post("templates/", {
            "name": name, "subject": subject, "html": html, "text": text,
        })

    def create_group(self, name, targets):
        return self._post("groups/", {
            "name": name,
            "targets": [{"email": t["email"], "first_name": t.get("first_name", ""),
                         "last_name": t.get("last_name", "")} for t in targets],
        })


def analyze_campaign_results(results):
    """Analyze phishing campaign results for metrics."""
    stats = {"total": 0, "sent": 0, "opened": 0, "clicked": 0, "submitted": 0, "reported": 0}
    for r in results:
        stats["total"] += 1
        status = r.get("status", "").lower()
        if status == "email sent":
            stats["sent"] += 1
        elif status == "email opened":
            stats["opened"] += 1
        elif status == "clicked link":
            stats["clicked"] += 1
        elif status == "submitted data":
            stats["submitted"] += 1
    if stats["sent"] > 0:
        stats["open_rate"] = round(stats["opened"] / stats["sent"] * 100, 1)
        stats["click_rate"] = round(stats["clicked"] / stats["sent"] * 100, 1)
        stats["submit_rate"] = round(stats["submitted"] / stats["sent"] * 100, 1)
    return stats


def generate_pretext_scenarios():
    """Generate social engineering pretext scenarios for testing."""
    return [
        {
            "scenario": "IT Password Reset",
            "pretext": "IT department requires immediate password reset due to security incident",
            "vector": "email",
            "urgency": "high",
            "success_indicator": "User clicks link and enters credentials",
        },
        {
            "scenario": "CEO Wire Transfer",
            "pretext": "CEO requests urgent wire transfer for confidential acquisition",
            "vector": "email",
            "urgency": "high",
            "success_indicator": "User initiates transfer or reveals banking info",
        },
        {
            "scenario": "Vendor Invoice",
            "pretext": "Known vendor sends updated invoice with changed payment details",
            "vector": "email",
            "urgency": "medium",
            "success_indicator": "User opens attachment or clicks payment link",
        },
        {
            "scenario": "Physical Tailgating",
            "pretext": "Contractor with clipboard requests building access",
            "vector": "physical",
            "urgency": "low",
            "success_indicator": "Employee holds door without badge verification",
        },
    ]


def run_assessment(base_url=None, api_key=None, campaign_id=None):
    """Execute social engineering assessment analysis."""
    print(f"\n{'='*60}")
    print(f"  SOCIAL ENGINEERING PENETRATION TEST")
    print(f"  Generated: {datetime.utcnow().isoformat()} UTC")
    print(f"{'='*60}\n")

    if base_url and api_key:
        client = GoPhishClient(base_url, api_key)
        campaigns = client.list_campaigns()
        print(f"--- CAMPAIGNS ({len(campaigns)}) ---")
        for c in campaigns[:5]:
            print(f"  {c['name']}: {c['status']}")

        if campaign_id:
            results = client.get_campaign_results(campaign_id)
            stats = analyze_campaign_results(results)
            print(f"\n--- CAMPAIGN METRICS ---")
            for k, v in stats.items():
                print(f"  {k}: {v}")

    scenarios = generate_pretext_scenarios()
    print(f"\n--- PRETEXT SCENARIOS ({len(scenarios)}) ---")
    for s in scenarios:
        print(f"  [{s['urgency'].upper()}] {s['scenario']}: {s['vector']}")

    return {"scenarios": scenarios}


def main():
    parser = argparse.ArgumentParser(description="Social Engineering Pentest Agent")
    parser.add_argument("--gophish-url", help="GoPhish server URL")
    parser.add_argument("--api-key", help="GoPhish API key")
    parser.add_argument("--campaign-id", type=int, help="Campaign ID for results")
    parser.add_argument("--output", help="Save report to JSON file")
    args = parser.parse_args()

    report = run_assessment(args.gophish_url, args.api_key, args.campaign_id)
    if args.output:
        with open(args.output, "w") as f:
            json.dump(report, f, indent=2, default=str)
        print(f"\n[+] Report saved to {args.output}")


if __name__ == "__main__":
    main()
process.py7.4 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""
Social Engineering Penetration Test — Campaign Metrics Processor

Processes GoPhish campaign results and generates analysis reports.
Requires: requests library for GoPhish API interaction.

Usage:
    python process.py --gophish-url https://localhost:3333 --api-key <key> --output ./results
"""

import json
import csv
import argparse
import datetime
from pathlib import Path
from typing import Optional

try:
    import requests
    requests.packages.urllib3.disable_warnings()
except ImportError:
    print("Install requests: pip install requests")
    raise


class GoPhishClient:
    """Client for GoPhish REST API."""

    def __init__(self, base_url: str, api_key: str):
        self.base_url = base_url.rstrip("/")
        self.headers = {"Authorization": f"Bearer {api_key}"}
        self.session = requests.Session()
        self.session.headers.update(self.headers)
        self.session.verify = False

    def get_campaigns(self) -> list[dict]:
        resp = self.session.get(f"{self.base_url}/api/campaigns/")
        resp.raise_for_status()
        return resp.json()

    def get_campaign(self, campaign_id: int) -> dict:
        resp = self.session.get(f"{self.base_url}/api/campaigns/{campaign_id}")
        resp.raise_for_status()
        return resp.json()

    def get_campaign_results(self, campaign_id: int) -> dict:
        resp = self.session.get(f"{self.base_url}/api/campaigns/{campaign_id}/results")
        resp.raise_for_status()
        return resp.json()


def analyze_campaign(campaign: dict) -> dict:
    """Analyze a single campaign's results."""
    results = campaign.get("results", [])
    timeline = campaign.get("timeline", [])

    stats = {
        "campaign_name": campaign.get("name", "Unknown"),
        "total_targets": len(results),
        "emails_sent": 0,
        "emails_opened": 0,
        "links_clicked": 0,
        "credentials_submitted": 0,
        "emails_reported": 0,
        "errors": 0,
    }

    for entry in results:
        status = entry.get("status", "")
        if status == "Email Sent" or status in ("Email Opened", "Clicked Link",
                                                  "Submitted Data", "Email Reported"):
            stats["emails_sent"] += 1
        if status in ("Email Opened", "Clicked Link", "Submitted Data"):
            stats["emails_opened"] += 1
        if status in ("Clicked Link", "Submitted Data"):
            stats["links_clicked"] += 1
        if status == "Submitted Data":
            stats["credentials_submitted"] += 1
        if status == "Email Reported":
            stats["emails_reported"] += 1
        if status == "Error":
            stats["errors"] += 1

    # Calculate rates
    total = stats["total_targets"]
    if total > 0:
        stats["open_rate"] = round(stats["emails_opened"] / total * 100, 1)
        stats["click_rate"] = round(stats["links_clicked"] / total * 100, 1)
        stats["submit_rate"] = round(stats["credentials_submitted"] / total * 100, 1)
        stats["report_rate"] = round(stats["emails_reported"] / total * 100, 1)
    else:
        stats["open_rate"] = stats["click_rate"] = stats["submit_rate"] = stats["report_rate"] = 0

    return stats


def analyze_by_department(results: list[dict]) -> dict[str, dict]:
    """Break down results by department/position."""
    departments = {}
    for entry in results:
        dept = entry.get("position", "Unknown")
        if dept not in departments:
            departments[dept] = {
                "total": 0, "clicked": 0, "submitted": 0, "reported": 0
            }
        departments[dept]["total"] += 1
        status = entry.get("status", "")
        if status in ("Clicked Link", "Submitted Data"):
            departments[dept]["clicked"] += 1
        if status == "Submitted Data":
            departments[dept]["submitted"] += 1
        if status == "Email Reported":
            departments[dept]["reported"] += 1

    return departments


def generate_report(stats: dict, dept_analysis: dict, output_dir: Path) -> str:
    """Generate campaign analysis report."""
    report_file = output_dir / "se_campaign_report.md"
    timestamp = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%d %H:%M UTC")

    with open(report_file, "w") as f:
        f.write("# Social Engineering Campaign Analysis Report\n\n")
        f.write(f"**Campaign:** {stats['campaign_name']}\n")
        f.write(f"**Generated:** {timestamp}\n\n---\n\n")

        f.write("## Campaign Metrics\n\n")
        f.write("| Metric | Count | Rate |\n")
        f.write("|--------|-------|------|\n")
        f.write(f"| Targets | {stats['total_targets']} | 100% |\n")
        f.write(f"| Emails Sent | {stats['emails_sent']} | — |\n")
        f.write(f"| Emails Opened | {stats['emails_opened']} | {stats['open_rate']}% |\n")
        f.write(f"| Links Clicked | {stats['links_clicked']} | {stats['click_rate']}% |\n")
        f.write(f"| Credentials Submitted | {stats['credentials_submitted']} | {stats['submit_rate']}% |\n")
        f.write(f"| Reported to Security | {stats['emails_reported']} | {stats['report_rate']}% |\n\n")

        f.write("## Department Breakdown\n\n")
        f.write("| Department | Total | Clicked | Submitted | Reported |\n")
        f.write("|-----------|-------|---------|-----------|----------|\n")
        for dept, data in sorted(dept_analysis.items()):
            f.write(f"| {dept} | {data['total']} | {data['clicked']} | {data['submitted']} | {data['reported']} |\n")
        f.write("\n")

        f.write("## Risk Assessment\n\n")
        if stats["submit_rate"] > 20:
            risk = "CRITICAL"
        elif stats["submit_rate"] > 10:
            risk = "HIGH"
        elif stats["submit_rate"] > 5:
            risk = "MEDIUM"
        else:
            risk = "LOW"
        f.write(f"**Overall Risk Level: {risk}**\n\n")

        f.write("## Recommendations\n\n")
        f.write("1. Deploy phishing-resistant MFA (FIDO2/WebAuthn)\n")
        f.write("2. Implement targeted training for high-risk departments\n")
        f.write("3. Deploy email security gateway with URL sandboxing\n")
        f.write("4. Establish phishing report button and reward program\n")
        f.write("5. Conduct quarterly phishing simulations\n")

    print(f"[+] Report: {report_file}")
    return str(report_file)


def main():
    parser = argparse.ArgumentParser(description="SE Campaign Analysis")
    parser.add_argument("--gophish-url", default="https://localhost:3333")
    parser.add_argument("--api-key", required=True)
    parser.add_argument("--campaign-id", type=int, help="Specific campaign ID")
    parser.add_argument("--output", default="./results")
    args = parser.parse_args()

    output_dir = Path(args.output)
    output_dir.mkdir(parents=True, exist_ok=True)

    client = GoPhishClient(args.gophish_url, args.api_key)

    if args.campaign_id:
        campaign = client.get_campaign(args.campaign_id)
        stats = analyze_campaign(campaign)
        dept_analysis = analyze_by_department(campaign.get("results", []))
        generate_report(stats, dept_analysis, output_dir)
    else:
        campaigns = client.get_campaigns()
        for campaign in campaigns:
            stats = analyze_campaign(campaign)
            dept_analysis = analyze_by_department(campaign.get("results", []))
            generate_report(stats, dept_analysis, output_dir)
            print(f"[+] Processed campaign: {campaign.get('name')}")


if __name__ == "__main__":
    main()

Assets 1

template.mdtext/markdown · 1.0 KB
Keep exploring