Security Fundamentals & Threat Modeling

CIA Triad, STRIDE, Attack Vectors, Defense in Depth

Introduction

Security engineering starts with a mindset: assume breach, design for failure, and layer your defenses. Before writing a single line of secure code, you need to understand what you are protecting, from whom, and how attackers think. This lesson establishes the foundational vocabulary and frameworks that every security engineer uses daily, the CIA Triad, threat modeling with STRIDE, attack vectors classification, and the defense-in-depth architecture principle.

The CIA Triad

The CIA Triad is the foundational framework for information security. Every security decision you make maps back to protecting one or more of these three properties.

Confidentiality

Data is accessible only to authorized parties.

  • Encryption at rest
  • Access control lists
  • TLS in transit
  • Least-privilege access
Threat: Unauthorized data exposure, eavesdropping

Integrity

Data has not been tampered with or altered.

  • Cryptographic hashing
  • Digital signatures
  • Checksums (SHA-256)
  • Version control & audit logs
Threat: Data tampering, man-in-the-middle attacks

Availability

Systems are accessible to authorized users when needed.

  • Redundancy & failover
  • DDoS protection
  • Backup & disaster recovery
  • Rate limiting
Threat: Denial of service, ransomware
CIA in Practice

Security controls often involve trade-offs between CIA properties. A heavily encrypted, air-gapped system maximizes Confidentiality but may hurt Availability. Understanding your system's requirements helps you make informed trade-offs, not every system needs maximum protection for all three.

Threat Modeling with STRIDE

STRIDE is Microsoft's threat modeling framework. Each letter represents a threat category that maps to a CIA property. Use it to systematically identify threats during design, before you build.

LetterThreat CategoryCIA Property ViolatedExample AttackMitigation
SSpoofingAuthenticationFake identity, phishingMFA, certificate pinning
TTamperingIntegrityMITM data modificationHMAC, digital signatures
RRepudiationNon-repudiationDeny performing an actionAudit logs, signatures
IInformation DisclosureConfidentialityData leak, SQL error messagesEncryption, input sanitization
DDenial of ServiceAvailabilityDDoS, resource exhaustionRate limiting, CDN, WAF
EElevation of PrivilegeAuthorizationPrivilege escalationLeast privilege, RBAC

Python: STRIDE Threat Report Generator

A practical Python script that models a system's components and generates a STRIDE threat assessment report.

# threat_model.py, STRIDE Threat Report Generator
from dataclasses import dataclass, field
from enum import Enum
from typing import List


class StrideCategory(Enum):
    SPOOFING = "Spoofing"
    TAMPERING = "Tampering"
    REPUDIATION = "Repudiation"
    INFO_DISCLOSURE = "Information Disclosure"
    DENIAL_OF_SERVICE = "Denial of Service"
    ELEVATION_OF_PRIVILEGE = "Elevation of Privilege"


class Severity(Enum):
    LOW = "LOW"
    MEDIUM = "MEDIUM"
    HIGH = "HIGH"
    CRITICAL = "CRITICAL"


@dataclass
class Threat:
    category: StrideCategory
    description: str
    severity: Severity
    component: str
    mitigation: str


@dataclass
class SystemComponent:
    name: str
    component_type: str   # e.g., "web_server", "database", "api_gateway"
    threats: List[Threat] = field(default_factory=list)

    def add_threat(self, threat: Threat) -> None:
        self.threats.append(threat)

    def threat_count_by_severity(self) -> dict:
        counts = {s.value: 0 for s in Severity}
        for t in self.threats:
            counts[t.severity.value] += 1
        return counts


def generate_stride_report(components: List[SystemComponent]) -> None:
    total_threats = sum(len(c.threats) for c in components)
    print("=" * 60)
    print("        STRIDE THREAT MODEL REPORT")
    print("=" * 60)
    print(f"Components analyzed: {len(components)}")
    print(f"Total threats identified: {total_threats}")
    print()

    for component in components:
        print(f"[COMPONENT] {component.name} ({component.component_type})")
        print(f"  Threats: {len(component.threats)}")
        counts = component.threat_count_by_severity()
        for severity, count in counts.items():
            if count > 0:
                print(f"    {severity}: {count}")

        for threat in sorted(component.threats,
                             key=lambda t: list(Severity).index(t.severity),
                             reverse=True):
            print(f"  ┌─ [{threat.severity.value}] {threat.category.value}")
            print(f"  │  Description: {threat.description}")
            print(f"  └─ Mitigation: {threat.mitigation}")
        print()


# ── Define your system ──────────────────────────────────────────
api_gateway = SystemComponent("API Gateway", "api_gateway")
api_gateway.add_threat(Threat(
    category=StrideCategory.SPOOFING,
    description="Attacker sends requests with forged JWT token",
    severity=Severity.CRITICAL,
    component="API Gateway",
    mitigation="Validate JWT signature with RS256; use short expiry + refresh"
))
api_gateway.add_threat(Threat(
    category=StrideCategory.DENIAL_OF_SERVICE,
    description="Flood of unauthenticated requests exhausts connection pool",
    severity=Severity.HIGH,
    component="API Gateway",
    mitigation="Implement rate limiting (100 req/min per IP) + WAF rules"
))

database = SystemComponent("PostgreSQL Database", "database")
database.add_threat(Threat(
    category=StrideCategory.INFO_DISCLOSURE,
    description="SQL error messages reveal table schema to attacker",
    severity=Severity.MEDIUM,
    component="PostgreSQL Database",
    mitigation="Catch exceptions; return generic error messages to client"
))
database.add_threat(Threat(
    category=StrideCategory.TAMPERING,
    description="Unparameterized queries allow SQL injection data modification",
    severity=Severity.CRITICAL,
    component="PostgreSQL Database",
    mitigation="Use parameterized queries / ORM; never interpolate user input"
))

generate_stride_report([api_gateway, database])
Expected Output:
============================================================
        STRIDE THREAT MODEL REPORT
============================================================
Components analyzed: 2
Total threats identified: 4

[COMPONENT] API Gateway (api_gateway)
  Threats: 2
    CRITICAL: 1
    HIGH: 1
  ┌─ [CRITICAL] Spoofing
  │  Description: Attacker sends requests with forged JWT token
  └─ Mitigation: Validate JWT signature with RS256; use short expiry + refresh
  ┌─ [HIGH] Denial of Service
  │  Description: Flood of unauthenticated requests exhausts connection pool
  └─ Mitigation: Implement rate limiting (100 req/min per IP) + WAF rules

[COMPONENT] PostgreSQL Database (database)
  Threats: 2
    CRITICAL: 1
    MEDIUM: 1
  ┌─ [CRITICAL] Tampering
  │  Description: Unparameterized queries allow SQL injection data modification
  └─ Mitigation: Use parameterized queries / ORM; never interpolate user input
  ┌─ [MEDIUM] Information Disclosure
  │  Description: SQL error messages reveal table schema to attacker
  └─ Mitigation: Catch exceptions; return generic error messages to client

Attack Vectors Overview

Understanding how attackers reach your system helps you prioritize your defensive investment.

Network Attacks
  • Packet sniffing, Intercepting unencrypted traffic
  • Port scanning, Discovering open services
  • MITM, Intercepting and altering communications
  • DNS poisoning, Redirecting traffic to malicious hosts
Social Engineering
  • Phishing, Fraudulent emails/pages stealing credentials
  • Spear phishing, Targeted phishing with personalization
  • Pretexting, Fabricating scenarios to gain trust
  • Vishing, Voice-based social engineering
Application Attacks
  • SQL injection, Manipulating database queries
  • XSS, Injecting malicious client-side scripts
  • CSRF, Forging authenticated user actions
  • Path traversal, Accessing unauthorized file paths
Supply Chain Attacks
  • Dependency confusion, Malicious packages on public registries
  • Typosquatting, Packages with similar names to popular ones
  • Build system compromise, Injecting code in CI/CD pipeline
  • Vendor compromise, Attacking via trusted third-party software

Defense in Depth

Defense in depth (DiD) means using multiple independent security layers. If one layer fails, additional layers continue to protect the system. No single control is a silver bullet.

Perimeter Layer
Firewalls, IDS/IPS, DDoS protection, WAF
Network Layer
Network segmentation, VLANs, VPN, zero-trust
Host Layer
OS hardening, EDR, patch management, antivirus
Application Layer
Input validation, secure coding, SAST/DAST, OWASP
Data Layer
Encryption at rest, DLP, database ACLs, key management
Identity Layer
MFA, SSO, least privilege, PAM, RBAC
# defense_in_depth.py, Model your security layers
from dataclasses import dataclass, field
from typing import List


@dataclass
class SecurityControl:
    name: str
    control_type: str   # preventive, detective, corrective
    effectiveness: str  # low, medium, high


@dataclass
class SecurityLayer:
    name: str
    controls: List[SecurityControl] = field(default_factory=list)

    def add_control(self, control: SecurityControl) -> None:
        self.controls.append(control)

    def coverage_score(self) -> float:
        """Returns % of high-effectiveness controls."""
        if not self.controls:
            return 0.0
        high_count = sum(1 for c in self.controls if c.effectiveness == "high")
        return (high_count / len(self.controls)) * 100


# Define defense layers
layers = [
    SecurityLayer("Perimeter"),
    SecurityLayer("Application"),
    SecurityLayer("Data"),
]

layers[0].add_control(SecurityControl("WAF", "preventive", "high"))
layers[0].add_control(SecurityControl("Rate Limiter", "preventive", "high"))
layers[0].add_control(SecurityControl("IDS Alerts", "detective", "medium"))

layers[1].add_control(SecurityControl("Input Validation", "preventive", "high"))
layers[1].add_control(SecurityControl("SAST Scan", "detective", "medium"))

layers[2].add_control(SecurityControl("AES-256 Encryption", "preventive", "high"))
layers[2].add_control(SecurityControl("Access Logging", "detective", "high"))

print("Defense in Depth Analysis")
print("=" * 40)
for layer in layers:
    score = layer.coverage_score()
    status = "✅" if score >= 75 else "⚠️"
    print(f"{status} {layer.name:15}, Coverage: {score:.0f}%")
    for ctrl in layer.controls:
        print(f"   • {ctrl.name} ({ctrl.control_type}, {ctrl.effectiveness})")
Expected Output:
Defense in Depth Analysis
========================================
✅ Perimeter       , Coverage: 67%
   • WAF (preventive, high)
   • Rate Limiter (preventive, high)
   • IDS Alerts (detective, medium)
⚠️ Application     , Coverage: 50%
   • Input Validation (preventive, high)
   • SAST Scan (detective, medium)
✅ Data            , Coverage: 100%
   • AES-256 Encryption (preventive, high)
   • Access Logging (detective, high)

Key Takeaways

  • CIA Triad, Every security decision protects Confidentiality, Integrity, and/or Availability; understand the trade-offs
  • STRIDE, Systematically enumerate threats during design: Spoofing, Tampering, Repudiation, Info Disclosure, DoS, Elevation of Privilege
  • Attack vectors, Threats come from networks, social engineering, applications, and the software supply chain
  • Defense in depth, Layer multiple independent controls; no single control is sufficient on its own
  • Assume breach, Design systems expecting that any individual control will eventually fail
  • Least privilege, Grant only the minimum permissions required; limit blast radius when breaches occur
What's Next?

Now that you understand the threat landscape and security principles, Lesson 2 dives into the mathematical tools that power modern security: cryptography.

  • Hashing algorithms, SHA-256, SHA-3, and why MD5 is dead
  • Symmetric encryption, Fernet and AES in Python
  • Asymmetric encryption, RSA key pairs and digital signatures
  • HMAC, Message authentication for integrity verification