35  Threat Detection Lab

35.1 Learning Objectives

By completing this interactive hardware lab, you will be able to:

  • Detect simulated attack patterns including brute force, replay, and injection attacks using threshold-based monitoring
  • Implement security event logging with timestamped attack records and threat categorization on embedded hardware
  • Configure alert thresholds that balance detection sensitivity against false positive rates
  • Calculate risk scores using DREAD-inspired methodology in real-time on constrained devices
  • Visualize threat levels through LED indicators representing different security states
  • Design incident response mechanisms with automated lockout and escalation procedures
  • Analyze attack patterns through serial console threat reports to identify attacker behavior

Key Concepts

  • Controlled lab environment: A physically or virtually isolated network and device setup where security attacks can be performed safely without risk to production systems or unintended victims.
  • Attack documentation: Structured recording of each step in a security lab attack — the tool used, input provided, output observed, and security implication — building a replicable record of the demonstrated vulnerability.
  • Defensive countermeasure implementation: The process of implementing and validating the specific control that would have prevented or detected the demonstrated attack, completing the attack-defend cycle.
  • Lab report: A structured document recording the lab setup, attack procedure, observed results, security implications, and remediation recommendations — essential for learning consolidation and skill development.
  • Threat replication: Reproducing a documented real-world attack technique in a lab environment to understand how it works mechanically, which systems it affects, and which defences would block it.
In 60 Seconds

The IoT security threats lab provides hands-on experience identifying, exploiting, and mitigating real security vulnerabilities in a controlled environment — translating the abstract knowledge that ‘default credentials are dangerous’ into the concrete experience of actually accessing a device using default credentials and observing what an attacker can achieve. Lab experiences build the intuitive security judgment that enables rapid identification of vulnerabilities in real-world systems.

Prerequisites: Basic Arduino/C++ syntax, understanding of STRIDE/DREAD from threat modeling chapters

Estimated Time: 75-90 minutes

Threat Modeling Series:

Security Implementation:

What is this lab about? This interactive simulator teaches you to detect and respond to security threats in real-time. You’ll analyze login attempts, identify brute-force attacks, calculate risk scores using DREAD, and tune detection thresholds to catch attackers without blocking legitimate users.

Why does this matter? Threat modeling isn’t just theory - you need to implement detection systems that catch real attacks. This lab gives you hands-on experience with the trade-offs: set thresholds too low and you miss attacks; set them too high and you block legitimate users.

What you’ll learn:

  • How to spot brute-force password attacks
  • When to lock accounts vs reset passwords
  • How to calculate DREAD risk scores
  • How to tune detection sensitivity
  • How to recover from false positives
MVU: Threat Detection Systems

Core Concept: Threat detection systems monitor activity patterns to identify attacks (failed logins, unusual traffic, privilege escalation attempts) and trigger automated responses (account lockout, alerts, blocking). Why It Matters: Threats must be detected before they succeed; the average data breach takes 207 days to detect - automated systems reduce this to minutes. Key Takeaway: Balance false positives (blocking legitimate users) with false negatives (missing real attacks) by tuning thresholds based on risk tolerance.

35.2 Lab: Threat Detection and Risk Assessment Simulator

This hands-on lab simulates an IoT security monitoring system that demonstrates core threat modeling concepts. You will build a device that detects, logs, and responds to simulated attacks while calculating real-time risk scores based on the DREAD methodology covered in threat modeling chapters.

How It Works: Threat Detection System

This lab demonstrates how production IoT security systems detect and respond to attacks:

Detection Layer

  • Pattern Recognition: System tracks attack frequency within time windows (10-second intervals)
  • Threshold Comparison: Each attack type has specific thresholds (brute force: 5 attempts, replay: 3 attempts, injection: 2 attempts)
  • Attack Fingerprinting: Button presses simulate different attack signatures (brute force vs. injection vs. replay)

Scoring Layer

  • Dynamic DREAD Calculation: Risk scores increase with attack count (reproducibility and affected users factors)
  • Attack Type Weighting: Injection attacks score higher (9/10 damage) than brute force (8/10 damage)
  • Overall Risk Aggregation: Weighted moving average tracks cumulative risk across all attack types

Response Layer

  • Graduated Escalation: Normal → Warning → Critical → Lockout based on threat level
  • Automated Countermeasures: System automatically locks out after critical thresholds
  • Visual Feedback: LEDs provide immediate threat status indication (Green=safe, Yellow=warning, Red=critical, Blue=lockout)

Logging Layer

  • Event Correlation: Circular buffer stores 50 security events with timestamps
  • Attack Attribution: Each event records attack type, severity, and STRIDE category
  • Forensic Trail: Logs enable post-incident analysis without storing sensitive payload data

Recovery Layer

  • Time-based Unlocking: 30-second lockout period prevents immediate re-attack
  • Manual Override: Reset button allows operator intervention
  • Threat Decay: Risk levels automatically decrease when attacks stop

Why This Approach Works: Real production systems (AWS GuardDuty, Azure Sentinel, Splunk) use similar principles - pattern-based detection, risk scoring, automated response, and comprehensive logging - to protect large-scale IoT deployments.

Concept Relationships
Concept Relates To Nature of Relationship
Attack Patterns STRIDE Categories Each pattern maps to specific STRIDE threats
DREAD Scoring Response Escalation Higher scores trigger more aggressive countermeasures
Threshold Tuning False Positive Trade-off Lower thresholds catch more attacks but cause more false alarms
Event Logging Non-Repudiation Logs create audit trail preventing denial of actions
Lockout Mechanism Denial of Service Mitigation Rate limiting prevents resource exhaustion
Threat Level Decay Recovery Procedures Gradual de-escalation allows return to normal operations
See Also

Threat Modeling Fundamentals:

Security Implementation:

Practical Application:

35.2.1 Why This Lab Matters

In production IoT systems, threat detection happens at multiple layers:

  • Device level: Detecting abnormal access patterns, failed authentications, firmware tampering
  • Network level: Identifying malicious traffic, port scans, protocol violations
  • Application level: Catching injection attacks, unauthorized API calls, data exfiltration

Anomaly Detection and Z-Score Thresholds

Statistical anomaly detection uses the Z-score to identify unusual sensor readings:

\[Z = \frac{x - \mu}{\sigma}\]

where \(x\) is the observed value, \(\mu\) is the baseline mean, and \(\sigma\) is the standard deviation.

Example: Temperature sensor baseline

  • Baseline: \(\mu = 25.0°C\)
  • Standard deviation: \(\sigma = 2.0°C\)

Reading analysis:

  • Normal reading (\(x = 24.5°C\)): \(Z = \frac{24.5 - 25.0}{2.0} = -0.25\) (within normal range)
  • Warning reading (\(x = 30.0°C\)): \(Z = \frac{30.0 - 25.0}{2.0} = 2.5\) (elevated alert)
  • Critical reading (\(x = 100.0°C\)): \(Z = \frac{100.0 - 25.0}{2.0} = 37.5\) (confirmed anomaly)

Threshold significance:

  • \(|Z| < 2.0\): Within 95% confidence interval (normal)
  • \(2.0 \leq |Z| < 3.0\): Outside 95% CI (warning)
  • \(|Z| \geq 3.0\): Outside 99.7% CI (critical, possible attack)

False positive rate calculation: \[\text{FPR} = P(|Z| > z_{\text{threshold}}) = 1 - \Phi(z_{\text{threshold}})\]

For \(z = 3.0\) threshold: \(\text{FPR} = 0.27\%\) (only 1 in 370 normal readings triggers false alarm)

This mathematical framework balances sensitivity (catching attacks) against specificity (avoiding false alarms).

Interactive Z-Score Calculator

This lab simulates device-level threat detection, giving you hands-on experience with:

  1. Attack pattern recognition - How systems identify malicious behavior
  2. Threshold-based alerting - When to escalate vs. ignore security events
  3. Risk quantification - Converting qualitative threats to actionable scores
  4. Automated response - Implementing lockouts and countermeasures

35.2.2 Components

Component Purpose Wokwi Element
ESP32 DevKit Main controller running threat detection algorithms esp32:devkit-v1
Green LED System normal / secure state indicator led:green
Yellow LED Warning state / elevated threat level led:yellow
Red LED Critical alert / attack in progress led:red
Blue LED Lockout active / system recovery mode led:blue
Push Button 1 Simulate brute force attack (rapid authentication failures) button
Push Button 2 Simulate replay attack (repeated command injection) button
Push Button 3 Simulate injection attack (malformed data packets) button
Push Button 4 Reset security state / clear lockout button
Resistors (4x 220 ohm) Current limiting for LEDs resistor

35.2.3 Interactive Wokwi Simulator

Use the embedded simulator below to build and test your threat detection system. Wire the circuit as shown, paste the code, and click “Start Simulation”.

Simulator Tips
  • Wire first: Connect all components before pasting code
  • Paste code: Copy the complete code into the editor (replacing existing code)
  • Run: Click the green “Play” button to compile and run
  • Serial Monitor: View threat logs and risk scores in the Serial Monitor panel (115200 baud)
  • Simulate attacks: Press buttons rapidly to trigger different attack patterns
  • Observe LEDs: Watch threat level changes reflected in LED states
  • Save: Create a free Wokwi account to save your projects

35.2.4 Circuit Connections

Wire the circuit in Wokwi before entering the code:

ESP32 Pin Connections:
----------------------
GPIO 2  --> Green LED (+)  --> 220 ohm Resistor --> GND  (Normal/Secure)
GPIO 4  --> Yellow LED (+) --> 220 ohm Resistor --> GND  (Warning)
GPIO 5  --> Red LED (+)    --> 220 ohm Resistor --> GND  (Critical)
GPIO 18 --> Blue LED (+)   --> 220 ohm Resistor --> GND  (Lockout)

GPIO 15 --> Button 1       --> GND  (Brute Force Attack)
GPIO 16 --> Button 2       --> GND  (Replay Attack)
GPIO 17 --> Button 3       --> GND  (Injection Attack)
GPIO 19 --> Button 4       --> GND  (Reset/Recovery)
Circuit diagram showing ESP32 DevKit with four LEDs (green for normal, yellow for warning, red for critical, blue for lockout) connected via 220-ohm resistors to GPIO pins 2, 4, 5, and 18, and four push buttons (brute force, replay, injection, reset) connected to GPIO pins 15, 16, 17, and 19
Figure 35.1: Circuit diagram showing ESP32 connections to threat level LEDs and attack simulation buttons for the threat modeling lab.

35.2.5 Complete Arduino Code

Copy and paste this complete code into the Wokwi simulator:

Threat Detection and Risk Assessment Lab Code
// =====================================================================
// THREAT DETECTION AND RISK ASSESSMENT SIMULATOR
// IoT Security Monitoring Lab - ESP32
// =====================================================================
//
// This lab simulates an IoT security monitoring system that:
// - Detects simulated attack patterns (brute force, replay, injection)
// - Logs security events with timestamps and severity levels
// - Calculates real-time risk scores using DREAD methodology
// - Triggers automated responses based on threat thresholds
// - Visualizes threat levels through LED indicators
//
// Educational purposes - demonstrates threat modeling concepts
// NOT for production security implementations
// =====================================================================

#include <Arduino.h>

// =====================================================================
// PIN DEFINITIONS
// =====================================================================

// LED Indicators - Threat Level Visualization
#define LED_NORMAL    2   // Green LED  - System secure, no active threats
#define LED_WARNING   4   // Yellow LED - Elevated threat, monitoring
#define LED_CRITICAL  5   // Red LED    - Active attack, immediate response
#define LED_LOCKOUT   18  // Blue LED   - System locked, recovery mode

// Attack Simulation Buttons
#define BTN_BRUTE_FORCE  15  // Button 1 - Simulate brute force attack
#define BTN_REPLAY       16  // Button 2 - Simulate replay attack
#define BTN_INJECTION    17  // Button 3 - Simulate injection attack
#define BTN_RESET        19  // Button 4 - Reset security state

// =====================================================================
// THREAT MODELING CONSTANTS
// =====================================================================

// STRIDE Threat Categories (mapped to attack types)
enum STRIDECategory {
  STRIDE_SPOOFING,              // Identity spoofing attacks
  STRIDE_TAMPERING,             // Data/code tampering
  STRIDE_REPUDIATION,           // Action denial
  STRIDE_INFORMATION_DISCLOSURE, // Data leaks
  STRIDE_DENIAL_OF_SERVICE,      // Availability attacks
  STRIDE_ELEVATION_OF_PRIVILEGE  // Unauthorized access
};

// Attack Types we simulate
enum AttackType {
  ATTACK_NONE = 0,
  ATTACK_BRUTE_FORCE,    // STRIDE: Spoofing + Elevation of Privilege
  ATTACK_REPLAY,         // STRIDE: Spoofing + Repudiation
  ATTACK_INJECTION,      // STRIDE: Tampering + Elevation of Privilege
  ATTACK_TYPE_COUNT
};

// Threat Levels
enum ThreatLevel {
  THREAT_NORMAL = 0,     // Green  - No active threats
  THREAT_LOW,            // Green  - Minor anomalies
  THREAT_MEDIUM,         // Yellow - Suspicious activity
  THREAT_HIGH,           // Yellow - Likely attack
  THREAT_CRITICAL,       // Red    - Confirmed attack
  THREAT_LOCKOUT         // Blue   - System locked down
};

// =====================================================================
// DREAD RISK SCORING STRUCTURE
// Each factor scored 0-10, total risk = average
// =====================================================================

struct DREADScore {
  uint8_t damage;         // D: Potential damage (0-10)
  uint8_t reproducibility; // R: How easy to reproduce (0-10)
  uint8_t exploitability;  // E: Skill level required (0-10)
  uint8_t affectedUsers;   // A: Scope of impact (0-10)
  uint8_t discoverability; // D: How easy to find (0-10)

  // Calculate overall DREAD score (0-10 scale)
  float calculate() {
    return (damage + reproducibility + exploitability +
            affectedUsers + discoverability) / 5.0;
  }

  // Get risk level string
  const char* getRiskLevel() {
    float score = calculate();
    if (score >= 8.0) return "CRITICAL";
    if (score >= 6.0) return "HIGH";
    if (score >= 4.0) return "MEDIUM";
    return "LOW";
  }
};

// =====================================================================
// SECURITY EVENT STRUCTURE
// =====================================================================

struct SecurityEvent {
  unsigned long timestamp;     // Milliseconds since boot
  AttackType attackType;       // Type of attack detected
  STRIDECategory strideType;   // STRIDE classification
  uint8_t severity;            // 1-5 severity scale
  DREADScore dreadScore;       // DREAD risk assessment
  bool mitigated;              // Was the attack blocked?
  char description[64];        // Human-readable description
};

// =====================================================================
// ATTACK PATTERN DETECTOR
// Tracks attack frequency and patterns over time windows
// =====================================================================

struct AttackPattern {
  AttackType type;
  uint16_t count;              // Total attacks detected
  uint16_t windowCount;        // Attacks in current time window
  unsigned long firstSeen;     // First attack timestamp
  unsigned long lastSeen;      // Most recent attack
  unsigned long windowStart;   // Current window start time
  uint16_t threshold;          // Alert threshold
  bool alertActive;            // Currently alerting?
};

// =====================================================================
// GLOBAL STATE VARIABLES
// =====================================================================

// Current system state
ThreatLevel currentThreatLevel = THREAT_NORMAL;
bool systemLocked = false;
unsigned long lockoutEndTime = 0;
const unsigned long LOCKOUT_DURATION = 30000;  // 30 second lockout

// Attack patterns for each type
AttackPattern attackPatterns[ATTACK_TYPE_COUNT];

// Security event log (circular buffer)
#define EVENT_LOG_SIZE 50
SecurityEvent eventLog[EVENT_LOG_SIZE];
int eventLogIndex = 0;
int eventLogCount = 0;

// Timing constants
const unsigned long WINDOW_SIZE = 10000;       // 10 second detection window
const unsigned long DEBOUNCE_DELAY = 150;      // Button debounce
const unsigned long THREAT_DECAY_INTERVAL = 5000; // Threat level decay time
unsigned long lastDebounce = 0;
unsigned long lastThreatDecay = 0;
unsigned long lastStatusReport = 0;

// Overall risk score (running average)
float overallRiskScore = 0.0;

// Attack statistics
unsigned long totalAttacksDetected = 0;
unsigned long totalAttacksMitigated = 0;

// =====================================================================
// DREAD SCORING PROFILES FOR EACH ATTACK TYPE
// Pre-defined scores based on attack characteristics
// =====================================================================

DREADScore getBruteForceDREAD(int attemptCount) {
  DREADScore score;
  // Damage: High if successful (account compromise)
  score.damage = 8;
  // Reproducibility: Very high (automated tools)
  score.reproducibility = min(10, 5 + attemptCount / 2);
  // Exploitability: Medium (requires weak passwords)
  score.exploitability = 6;
  // Affected Users: Single account initially, could spread
  score.affectedUsers = min(10, 3 + attemptCount / 5);
  // Discoverability: Low (needs enumeration)
  score.discoverability = 4;
  return score;
}

DREADScore getReplayDREAD(int attemptCount) {
  DREADScore score;
  // Damage: High (unauthorized actions)
  score.damage = 7;
  // Reproducibility: Very high (just replay captured data)
  score.reproducibility = 9;
  // Exploitability: Medium (need to capture valid session)
  score.exploitability = 5;
  // Affected Users: Depends on captured session scope
  score.affectedUsers = min(10, 4 + attemptCount / 3);
  // Discoverability: Medium (traffic analysis)
  score.discoverability = 6;
  return score;
}

DREADScore getInjectionDREAD(int attemptCount) {
  DREADScore score;
  // Damage: Critical (code execution, data breach)
  score.damage = 9;
  // Reproducibility: High once vulnerability found
  score.reproducibility = 8;
  // Exploitability: High (well-known techniques)
  score.exploitability = 7;
  // Affected Users: Potentially all users
  score.affectedUsers = min(10, 6 + attemptCount / 2);
  // Discoverability: Medium (requires probing)
  score.discoverability = 5;
  return score;
}

// =====================================================================
// SETUP FUNCTION
// =====================================================================

void setup() {
  Serial.begin(115200);
  delay(1000);  // Allow serial to initialize

  // Configure LED pins as outputs
  pinMode(LED_NORMAL, OUTPUT);
  pinMode(LED_WARNING, OUTPUT);
  pinMode(LED_CRITICAL, OUTPUT);
  pinMode(LED_LOCKOUT, OUTPUT);

  // Configure button pins with internal pull-ups
  pinMode(BTN_BRUTE_FORCE, INPUT_PULLUP);
  pinMode(BTN_REPLAY, INPUT_PULLUP);
  pinMode(BTN_INJECTION, INPUT_PULLUP);
  pinMode(BTN_RESET, INPUT_PULLUP);

  // Initialize attack pattern tracking
  initializeAttackPatterns();

  // LED startup sequence
  performStartupSequence();

  // Print welcome banner
  printWelcomeBanner();

  // Set initial LED state
  updateThreatLEDs();

  lastThreatDecay = millis();
  lastStatusReport = millis();
}

// =====================================================================
// MAIN LOOP
// =====================================================================

void loop() {
  unsigned long currentTime = millis();

  // Check for system lockout state
  if (systemLocked) {
    handleLockoutState(currentTime);
    return;
  }

  // Process button inputs with debouncing
  if (currentTime - lastDebounce > DEBOUNCE_DELAY) {
    processButtonInputs(currentTime);
  }

  // Update attack pattern windows
  updateAttackWindows(currentTime);

  // Decay threat level over time (recovery)
  if (currentTime - lastThreatDecay > THREAT_DECAY_INTERVAL) {
    decayThreatLevel();
    lastThreatDecay = currentTime;
  }

  // Periodic status report
  if (currentTime - lastStatusReport > 15000) {
    printStatusReport();
    lastStatusReport = currentTime;
  }

  // Update LED indicators
  updateThreatLEDs();

  // Small delay for stability
  delay(10);
}

// =====================================================================
// INITIALIZATION FUNCTIONS
// =====================================================================

void initializeAttackPatterns() {
  // Initialize brute force pattern
  attackPatterns[ATTACK_BRUTE_FORCE].type = ATTACK_BRUTE_FORCE;
  attackPatterns[ATTACK_BRUTE_FORCE].count = 0;
  attackPatterns[ATTACK_BRUTE_FORCE].windowCount = 0;
  attackPatterns[ATTACK_BRUTE_FORCE].firstSeen = 0;
  attackPatterns[ATTACK_BRUTE_FORCE].lastSeen = 0;
  attackPatterns[ATTACK_BRUTE_FORCE].windowStart = 0;
  attackPatterns[ATTACK_BRUTE_FORCE].threshold = 5;  // 5 attempts = alert
  attackPatterns[ATTACK_BRUTE_FORCE].alertActive = false;

  // Initialize replay attack pattern
  attackPatterns[ATTACK_REPLAY].type = ATTACK_REPLAY;
  attackPatterns[ATTACK_REPLAY].count = 0;
  attackPatterns[ATTACK_REPLAY].windowCount = 0;
  attackPatterns[ATTACK_REPLAY].firstSeen = 0;
  attackPatterns[ATTACK_REPLAY].lastSeen = 0;
  attackPatterns[ATTACK_REPLAY].windowStart = 0;
  attackPatterns[ATTACK_REPLAY].threshold = 3;  // 3 replays = alert
  attackPatterns[ATTACK_REPLAY].alertActive = false;

  // Initialize injection attack pattern
  attackPatterns[ATTACK_INJECTION].type = ATTACK_INJECTION;
  attackPatterns[ATTACK_INJECTION].count = 0;
  attackPatterns[ATTACK_INJECTION].windowCount = 0;
  attackPatterns[ATTACK_INJECTION].firstSeen = 0;
  attackPatterns[ATTACK_INJECTION].lastSeen = 0;
  attackPatterns[ATTACK_INJECTION].windowStart = 0;
  attackPatterns[ATTACK_INJECTION].threshold = 2;  // 2 injections = immediate alert
  attackPatterns[ATTACK_INJECTION].alertActive = false;
}

void performStartupSequence() {
  int leds[] = {LED_NORMAL, LED_WARNING, LED_CRITICAL, LED_LOCKOUT};

  // Sequential LED test
  for (int i = 0; i < 4; i++) {
    digitalWrite(leds[i], HIGH);
    delay(200);
    digitalWrite(leds[i], LOW);
  }

  // Flash all LEDs
  for (int j = 0; j < 2; j++) {
    for (int i = 0; i < 4; i++) {
      digitalWrite(leds[i], HIGH);
    }
    delay(150);
    for (int i = 0; i < 4; i++) {
      digitalWrite(leds[i], LOW);
    }
    delay(150);
  }
}

void printWelcomeBanner() {
  Serial.println();
  Serial.println("================================================================");
  Serial.println("     THREAT DETECTION AND RISK ASSESSMENT SIMULATOR");
  Serial.println("     IoT Security Monitoring Lab - ESP32");
  Serial.println("================================================================");
  Serial.println();
  Serial.println("This lab demonstrates core threat modeling concepts:");
  Serial.println("  - Attack pattern detection (brute force, replay, injection)");
  Serial.println("  - STRIDE threat classification");
  Serial.println("  - DREAD risk scoring methodology");
  Serial.println("  - Threshold-based alerting and automated lockout");
  Serial.println();
  Serial.println("ATTACK SIMULATION CONTROLS:");
  Serial.println("  Button 1 (GPIO 15): Brute Force Attack");
  Serial.println("                      Simulates failed authentication attempts");
  Serial.println("  Button 2 (GPIO 16): Replay Attack");
  Serial.println("                      Simulates replayed command tokens");
  Serial.println("  Button 3 (GPIO 17): Injection Attack");
  Serial.println("                      Simulates malformed data injection");
  Serial.println("  Button 4 (GPIO 19): Reset / Recovery");
  Serial.println("                      Clears lockout and resets threat level");
  Serial.println();
  Serial.println("THREAT LEVEL INDICATORS:");
  Serial.println("  Green LED:  NORMAL   - System secure, no active threats");
  Serial.println("  Yellow LED: WARNING  - Elevated threat, increased monitoring");
  Serial.println("  Red LED:    CRITICAL - Active attack, countermeasures active");
  Serial.println("  Blue LED:   LOCKOUT  - System locked, recovery required");
  Serial.println();
  Serial.println("THRESHOLDS (within 10-second window):");
  Serial.println("  Brute Force: 5 attempts  -> HIGH threat");
  Serial.println("  Replay:      3 attempts  -> HIGH threat");
  Serial.println("  Injection:   2 attempts  -> CRITICAL + LOCKOUT");
  Serial.println();
  Serial.println("Press any attack button to simulate threats...");
  Serial.println("================================================================");
  Serial.println();
}

// =====================================================================
// BUTTON INPUT PROCESSING
// =====================================================================

void processButtonInputs(unsigned long currentTime) {
  bool inputProcessed = false;

  // Check Brute Force button
  if (digitalRead(BTN_BRUTE_FORCE) == LOW) {
    handleBruteForceAttack(currentTime);
    inputProcessed = true;
  }

  // Check Replay Attack button
  if (digitalRead(BTN_REPLAY) == LOW) {
    handleReplayAttack(currentTime);
    inputProcessed = true;
  }

  // Check Injection Attack button
  if (digitalRead(BTN_INJECTION) == LOW) {
    handleInjectionAttack(currentTime);
    inputProcessed = true;
  }

  // Check Reset button
  if (digitalRead(BTN_RESET) == LOW) {
    handleSecurityReset(currentTime);
    inputProcessed = true;
  }

  if (inputProcessed) {
    lastDebounce = currentTime;
  }
}

// =====================================================================
// ATTACK HANDLERS
// =====================================================================

void handleBruteForceAttack(unsigned long currentTime) {
  AttackPattern* pattern = &attackPatterns[ATTACK_BRUTE_FORCE];

  // Update pattern statistics
  pattern->count++;
  pattern->windowCount++;
  pattern->lastSeen = currentTime;
  if (pattern->firstSeen == 0) {
    pattern->firstSeen = currentTime;
  }

  // Get DREAD score for this attack
  DREADScore dread = getBruteForceDREAD(pattern->windowCount);
  float riskScore = dread.calculate();

  // Create security event
  SecurityEvent event;
  event.timestamp = currentTime;
  event.attackType = ATTACK_BRUTE_FORCE;
  event.strideType = STRIDE_SPOOFING;  // Primary STRIDE category
  event.severity = min(5, 1 + pattern->windowCount / 2);
  event.dreadScore = dread;
  event.mitigated = false;

  // Generate description
  snprintf(event.description, sizeof(event.description),
           "Brute force attempt #%d (window: %d)",
           pattern->count, pattern->windowCount);

  // Log the event
  logSecurityEvent(event);

  // Print attack detection
  Serial.println();
  Serial.println("========================================");
  Serial.println("! ATTACK DETECTED: BRUTE FORCE");
  Serial.println("========================================");
  Serial.printf("  Timestamp:     %lu ms\n", currentTime);
  Serial.printf("  Total Count:   %d\n", pattern->count);
  Serial.printf("  Window Count:  %d / %d threshold\n",
                pattern->windowCount, pattern->threshold);
  Serial.println();
  Serial.println("  STRIDE Classification:");
  Serial.println("    Primary:   Spoofing (identity impersonation)");
  Serial.println("    Secondary: Elevation of Privilege (if successful)");
  Serial.println();
  Serial.println("  DREAD Risk Assessment:");
  Serial.printf("    Damage:          %d/10 (account compromise risk)\n", dread.damage);
  Serial.printf("    Reproducibility: %d/10 (automated tools available)\n", dread.reproducibility);
  Serial.printf("    Exploitability:  %d/10 (weak password dependency)\n", dread.exploitability);
  Serial.printf("    Affected Users:  %d/10 (scope of impact)\n", dread.affectedUsers);
  Serial.printf("    Discoverability: %d/10 (enumeration required)\n", dread.discoverability);
  Serial.println("    --------------------------------");
  Serial.printf("    OVERALL SCORE:   %.1f/10 [%s]\n", riskScore, dread.getRiskLevel());
  Serial.println();

  // Check threshold
  if (pattern->windowCount >= pattern->threshold) {
    pattern->alertActive = true;
    escalateThreatLevel(THREAT_HIGH);
    event.mitigated = true;

    Serial.println("  >> THRESHOLD EXCEEDED <<");
    Serial.println("  Response: Escalating to HIGH threat level");
    Serial.println("  Mitigation: Rate limiting activated");
    Serial.println("  Recommendation: Implement account lockout after 3 failures");

    totalAttacksMitigated++;
  } else {
    Serial.printf("  Status: Monitoring (%d more attempts trigger alert)\n",
                  pattern->threshold - pattern->windowCount);
  }

  Serial.println("========================================");
  Serial.println();

  // Update overall risk
  updateOverallRisk(riskScore);
  totalAttacksDetected++;
}

void handleReplayAttack(unsigned long currentTime) {
  AttackPattern* pattern = &attackPatterns[ATTACK_REPLAY];

  // Update pattern statistics
  pattern->count++;
  pattern->windowCount++;
  pattern->lastSeen = currentTime;
  if (pattern->firstSeen == 0) {
    pattern->firstSeen = currentTime;
  }

  // Get DREAD score
  DREADScore dread = getReplayDREAD(pattern->windowCount);
  float riskScore = dread.calculate();

  // Create security event
  SecurityEvent event;
  event.timestamp = currentTime;
  event.attackType = ATTACK_REPLAY;
  event.strideType = STRIDE_SPOOFING;
  event.severity = min(5, 2 + pattern->windowCount);
  event.dreadScore = dread;
  event.mitigated = false;
  snprintf(event.description, sizeof(event.description),
           "Replay attack #%d - duplicate token detected", pattern->count);

  logSecurityEvent(event);

  // Print attack detection
  Serial.println();
  Serial.println("========================================");
  Serial.println("! ATTACK DETECTED: REPLAY ATTACK");
  Serial.println("========================================");
  Serial.printf("  Timestamp:     %lu ms\n", currentTime);
  Serial.printf("  Total Count:   %d\n", pattern->count);
  Serial.printf("  Window Count:  %d / %d threshold\n",
                pattern->windowCount, pattern->threshold);
  Serial.println();
  Serial.println("  STRIDE Classification:");
  Serial.println("    Primary:   Spoofing (session impersonation)");
  Serial.println("    Secondary: Repudiation (action attribution)");
  Serial.println();
  Serial.println("  Attack Vector Analysis:");
  Serial.println("    - Captured valid authentication token");
  Serial.println("    - Replaying to bypass authentication");
  Serial.println("    - No timestamp/nonce validation detected");
  Serial.println();
  Serial.println("  DREAD Risk Assessment:");
  Serial.printf("    Damage:          %d/10 (unauthorized actions)\n", dread.damage);
  Serial.printf("    Reproducibility: %d/10 (trivial to replay)\n", dread.reproducibility);
  Serial.printf("    Exploitability:  %d/10 (traffic capture needed)\n", dread.exploitability);
  Serial.printf("    Affected Users:  %d/10 (captured session scope)\n", dread.affectedUsers);
  Serial.printf("    Discoverability: %d/10 (network sniffing)\n", dread.discoverability);
  Serial.println("    --------------------------------");
  Serial.printf("    OVERALL SCORE:   %.1f/10 [%s]\n", riskScore, dread.getRiskLevel());
  Serial.println();

  // Check threshold
  if (pattern->windowCount >= pattern->threshold) {
    pattern->alertActive = true;
    escalateThreatLevel(THREAT_HIGH);
    event.mitigated = true;

    Serial.println("  >> THRESHOLD EXCEEDED <<");
    Serial.println("  Response: Escalating to HIGH threat level");
    Serial.println("  Mitigation: Invalidating suspected tokens");
    Serial.println("  Recommendation: Implement nonce/timestamp in tokens");
    Serial.println("  Recommendation: Use short-lived session tokens");

    totalAttacksMitigated++;
  } else {
    Serial.printf("  Status: Monitoring (%d more replays trigger alert)\n",
                  pattern->threshold - pattern->windowCount);
  }

  Serial.println("========================================");
  Serial.println();

  updateOverallRisk(riskScore);
  totalAttacksDetected++;
}

void handleInjectionAttack(unsigned long currentTime) {
  AttackPattern* pattern = &attackPatterns[ATTACK_INJECTION];

  // Update pattern statistics
  pattern->count++;
  pattern->windowCount++;
  pattern->lastSeen = currentTime;
  if (pattern->firstSeen == 0) {
    pattern->firstSeen = currentTime;
  }

  // Get DREAD score - injection is highest severity
  DREADScore dread = getInjectionDREAD(pattern->windowCount);
  float riskScore = dread.calculate();

  // Create security event
  SecurityEvent event;
  event.timestamp = currentTime;
  event.attackType = ATTACK_INJECTION;
  event.strideType = STRIDE_TAMPERING;
  event.severity = 5;  // Always maximum severity
  event.dreadScore = dread;
  event.mitigated = false;
  snprintf(event.description, sizeof(event.description),
           "Injection attack #%d - malformed payload detected", pattern->count);

  logSecurityEvent(event);

  // Print attack detection
  Serial.println();
  Serial.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
  Serial.println("!!!  CRITICAL: INJECTION ATTACK  !!!");
  Serial.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
  Serial.printf("  Timestamp:     %lu ms\n", currentTime);
  Serial.printf("  Total Count:   %d\n", pattern->count);
  Serial.printf("  Window Count:  %d / %d threshold\n",
                pattern->windowCount, pattern->threshold);
  Serial.println();
  Serial.println("  STRIDE Classification:");
  Serial.println("    Primary:   Tampering (data manipulation)");
  Serial.println("    Secondary: Elevation of Privilege (code execution)");
  Serial.println("    Tertiary:  Information Disclosure (data exfiltration)");
  Serial.println();
  Serial.println("  Attack Payload Analysis:");
  Serial.println("    - Detected: SQL injection pattern");
  Serial.println("    - Detected: Command injection markers");
  Serial.println("    - Detected: Buffer overflow attempt");
  Serial.println("    - Risk: Remote code execution possible");
  Serial.println();
  Serial.println("  DREAD Risk Assessment:");
  Serial.printf("    Damage:          %d/10 (code execution, data breach)\n", dread.damage);
  Serial.printf("    Reproducibility: %d/10 (exploit is reliable)\n", dread.reproducibility);
  Serial.printf("    Exploitability:  %d/10 (known techniques)\n", dread.exploitability);
  Serial.printf("    Affected Users:  %d/10 (all system users)\n", dread.affectedUsers);
  Serial.printf("    Discoverability: %d/10 (active probing)\n", dread.discoverability);
  Serial.println("    --------------------------------");
  Serial.printf("    OVERALL SCORE:   %.1f/10 [%s]\n", riskScore, dread.getRiskLevel());
  Serial.println();

  // Injection attacks ALWAYS trigger immediate response
  pattern->alertActive = true;
  event.mitigated = true;
  totalAttacksMitigated++;

  Serial.println("  >> IMMEDIATE LOCKOUT TRIGGERED <<");
  Serial.println();
  Serial.println("  Automated Response:");
  Serial.println("    1. Blocking source IP address");
  Serial.println("    2. Terminating active session");
  Serial.println("    3. Logging forensic data");
  Serial.println("    4. Alerting security team");
  Serial.println("    5. Initiating system lockout");
  Serial.println();
  Serial.println("  Recommendations:");
  Serial.println("    - Input validation on all endpoints");
  Serial.println("    - Parameterized queries (prevent SQL injection)");
  Serial.println("    - Input sanitization (escape special characters)");
  Serial.println("    - Web Application Firewall (WAF) deployment");
  Serial.println();

  // Check threshold - injection has lower threshold
  if (pattern->windowCount >= pattern->threshold) {
    Serial.println("  >>> LOCKOUT INITIATED <<<");
    Serial.printf("  Duration: %d seconds\n", LOCKOUT_DURATION / 1000);
    Serial.println("  Press Button 4 (Reset) to recover manually");
    initiateSystemLockout(currentTime);
  } else {
    escalateThreatLevel(THREAT_CRITICAL);
    Serial.printf("  Warning: %d more injection = FULL LOCKOUT\n",
                  pattern->threshold - pattern->windowCount);
  }

  Serial.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
  Serial.println();

  updateOverallRisk(riskScore);
  totalAttacksDetected++;
}

void handleSecurityReset(unsigned long currentTime) {
  Serial.println();
  Serial.println("========================================");
  Serial.println("  SECURITY RESET INITIATED");
  Serial.println("========================================");
  Serial.println();

  // Clear lockout if active
  if (systemLocked) {
    systemLocked = false;
    lockoutEndTime = 0;
    Serial.println("  - Lockout cleared");
  }

  // Reset threat level
  currentThreatLevel = THREAT_NORMAL;
  Serial.println("  - Threat level reset to NORMAL");

  // Reset attack windows (keep cumulative counts)
  for (int i = 1; i < ATTACK_TYPE_COUNT; i++) {
    attackPatterns[i].windowCount = 0;
    attackPatterns[i].windowStart = currentTime;
    attackPatterns[i].alertActive = false;
  }
  Serial.println("  - Attack windows reset");

  // Reset overall risk
  overallRiskScore = 0.0;
  Serial.println("  - Risk score reset to 0.0");

  Serial.println();
  Serial.println("  System returning to normal operation");
  Serial.println("  Attack history preserved in event log");
  Serial.println("========================================");
  Serial.println();

  updateThreatLEDs();
}

// =====================================================================
// THREAT LEVEL MANAGEMENT
// =====================================================================

void escalateThreatLevel(ThreatLevel newLevel) {
  if (newLevel > currentThreatLevel && newLevel != THREAT_LOCKOUT) {
    ThreatLevel oldLevel = currentThreatLevel;
    currentThreatLevel = newLevel;

    Serial.printf("  [ESCALATION] Threat level: %s -> %s\n",
                  getThreatLevelName(oldLevel),
                  getThreatLevelName(newLevel));
  }
}

void decayThreatLevel() {
  // Only decay if not in lockout and above normal
  if (!systemLocked && currentThreatLevel > THREAT_NORMAL) {
    // Check if any active alerts
    bool anyActiveAlerts = false;
    for (int i = 1; i < ATTACK_TYPE_COUNT; i++) {
      if (attackPatterns[i].alertActive && attackPatterns[i].windowCount > 0) {
        anyActiveAlerts = true;
        break;
      }
    }

    // Only decay if no active alerts
    if (!anyActiveAlerts) {
      ThreatLevel oldLevel = currentThreatLevel;
      currentThreatLevel = (ThreatLevel)(currentThreatLevel - 1);

      Serial.printf("[DECAY] Threat level: %s -> %s (no active threats)\n",
                    getThreatLevelName(oldLevel),
                    getThreatLevelName(currentThreatLevel));

      // Also decay overall risk score
      if (overallRiskScore > 0) {
        overallRiskScore = max(0.0f, overallRiskScore - 0.5f);
      }
    }
  }
}

const char* getThreatLevelName(ThreatLevel level) {
  switch (level) {
    case THREAT_NORMAL:   return "NORMAL";
    case THREAT_LOW:      return "LOW";
    case THREAT_MEDIUM:   return "MEDIUM";
    case THREAT_HIGH:     return "HIGH";
    case THREAT_CRITICAL: return "CRITICAL";
    case THREAT_LOCKOUT:  return "LOCKOUT";
    default:              return "UNKNOWN";
  }
}

// =====================================================================
// LOCKOUT MANAGEMENT
// =====================================================================

void initiateSystemLockout(unsigned long currentTime) {
  systemLocked = true;
  lockoutEndTime = currentTime + LOCKOUT_DURATION;
  currentThreatLevel = THREAT_LOCKOUT;

  // Flash all LEDs rapidly to indicate lockout
  for (int i = 0; i < 5; i++) {
    digitalWrite(LED_NORMAL, HIGH);
    digitalWrite(LED_WARNING, HIGH);
    digitalWrite(LED_CRITICAL, HIGH);
    digitalWrite(LED_LOCKOUT, HIGH);
    delay(100);
    digitalWrite(LED_NORMAL, LOW);
    digitalWrite(LED_WARNING, LOW);
    digitalWrite(LED_CRITICAL, LOW);
    digitalWrite(LED_LOCKOUT, LOW);
    delay(100);
  }

  updateThreatLEDs();
}

void handleLockoutState(unsigned long currentTime) {
  // Check if lockout expired
  if (currentTime >= lockoutEndTime) {
    systemLocked = false;
    currentThreatLevel = THREAT_HIGH;  // Return to high alert, not normal

    Serial.println();
    Serial.println("========================================");
    Serial.println("  LOCKOUT EXPIRED - SYSTEM RECOVERING");
    Serial.println("========================================");
    Serial.println("  Threat level: HIGH (manual reset for NORMAL)");
    Serial.println("  Press Button 4 for full reset");
    Serial.println("========================================");
    Serial.println();

    updateThreatLEDs();
    return;
  }

  // Check reset button during lockout
  if (digitalRead(BTN_RESET) == LOW && currentTime - lastDebounce > DEBOUNCE_DELAY) {
    lastDebounce = currentTime;
    handleSecurityReset(currentTime);
    return;
  }

  // Pulse blue LED during lockout
  static unsigned long lastPulse = 0;
  static bool pulseState = false;

  if (currentTime - lastPulse > 500) {
    pulseState = !pulseState;
    digitalWrite(LED_LOCKOUT, pulseState ? HIGH : LOW);
    lastPulse = currentTime;

    // Show countdown every 5 seconds
    if ((lockoutEndTime - currentTime) % 5000 < 500) {
      Serial.printf("[LOCKOUT] %lu seconds remaining...\n",
                    (lockoutEndTime - currentTime) / 1000);
    }
  }
}

// =====================================================================
// ATTACK WINDOW MANAGEMENT
// =====================================================================

void updateAttackWindows(unsigned long currentTime) {
  for (int i = 1; i < ATTACK_TYPE_COUNT; i++) {
    AttackPattern* pattern = &attackPatterns[i];

    // Check if window has expired
    if (pattern->windowStart > 0 &&
        currentTime - pattern->windowStart > WINDOW_SIZE) {

      // Window expired - reset window counter
      if (pattern->windowCount > 0) {
        Serial.printf("[WINDOW] %s window expired. Resetting count from %d to 0\n",
                      getAttackTypeName((AttackType)i), pattern->windowCount);
        pattern->windowCount = 0;
        pattern->alertActive = false;
      }
      pattern->windowStart = currentTime;
    }

    // Start window on first attack
    if (pattern->windowStart == 0 && pattern->count > 0) {
      pattern->windowStart = pattern->firstSeen;
    }
  }
}

const char* getAttackTypeName(AttackType type) {
  switch (type) {
    case ATTACK_BRUTE_FORCE: return "Brute Force";
    case ATTACK_REPLAY:      return "Replay";
    case ATTACK_INJECTION:   return "Injection";
    default:                 return "Unknown";
  }
}

// =====================================================================
// LED CONTROL
// =====================================================================

void updateThreatLEDs() {
  // Turn off all LEDs first
  digitalWrite(LED_NORMAL, LOW);
  digitalWrite(LED_WARNING, LOW);
  digitalWrite(LED_CRITICAL, LOW);
  digitalWrite(LED_LOCKOUT, LOW);

  // Set appropriate LED based on threat level
  switch (currentThreatLevel) {
    case THREAT_NORMAL:
    case THREAT_LOW:
      digitalWrite(LED_NORMAL, HIGH);
      break;

    case THREAT_MEDIUM:
    case THREAT_HIGH:
      digitalWrite(LED_WARNING, HIGH);
      break;

    case THREAT_CRITICAL:
      digitalWrite(LED_CRITICAL, HIGH);
      break;

    case THREAT_LOCKOUT:
      digitalWrite(LED_LOCKOUT, HIGH);
      break;
  }
}

// =====================================================================
// EVENT LOGGING
// =====================================================================

void logSecurityEvent(SecurityEvent event) {
  eventLog[eventLogIndex] = event;
  eventLogIndex = (eventLogIndex + 1) % EVENT_LOG_SIZE;
  if (eventLogCount < EVENT_LOG_SIZE) {
    eventLogCount++;
  }
}

// =====================================================================
// RISK CALCULATION
// =====================================================================

void updateOverallRisk(float newRiskScore) {
  // Weighted moving average
  if (overallRiskScore == 0) {
    overallRiskScore = newRiskScore;
  } else {
    overallRiskScore = (overallRiskScore * 0.7) + (newRiskScore * 0.3);
  }
}

// =====================================================================
// STATUS REPORTING
// =====================================================================

void printStatusReport() {
  Serial.println();
  Serial.println("================================================================");
  Serial.println("                  SECURITY STATUS REPORT");
  Serial.println("================================================================");
  Serial.printf("  Timestamp:          %lu ms\n", millis());
  Serial.printf("  Current Threat:     %s\n", getThreatLevelName(currentThreatLevel));
  Serial.printf("  System Locked:      %s\n", systemLocked ? "YES" : "NO");
  Serial.printf("  Overall Risk Score: %.1f/10\n", overallRiskScore);
  Serial.println();

  Serial.println("  ATTACK STATISTICS:");
  Serial.printf("    Total Detected:   %lu\n", totalAttacksDetected);
  Serial.printf("    Total Mitigated:  %lu\n", totalAttacksMitigated);
  Serial.printf("    Mitigation Rate:  %.1f%%\n",
                totalAttacksDetected > 0
                  ? (totalAttacksMitigated * 100.0 / totalAttacksDetected)
                  : 0);
  Serial.println();

  Serial.println("  ATTACK TYPE BREAKDOWN:");
  for (int i = 1; i < ATTACK_TYPE_COUNT; i++) {
    AttackPattern* p = &attackPatterns[i];
    Serial.printf("    %-12s: %3d total, %2d in window, Alert: %s\n",
                  getAttackTypeName((AttackType)i),
                  p->count,
                  p->windowCount,
                  p->alertActive ? "ACTIVE" : "inactive");
  }
  Serial.println();

  Serial.printf("  Event Log Entries:  %d / %d\n", eventLogCount, EVENT_LOG_SIZE);
  Serial.println("================================================================");
  Serial.println();
}

35.2.6 Lab Exercises

After building the circuit and running the simulation, complete these exercises to deepen your understanding:

Exercise 1: Understanding Attack Thresholds

Objective: Explore how different threshold settings affect security response.

Tasks:

  1. Press Button 1 (Brute Force) slowly - one press every 3 seconds. Observe the threat level.
  2. Press Button 1 rapidly - 5+ times within 10 seconds. What happens?
  3. Compare with Button 3 (Injection) - why does it trigger lockout faster?

Questions to Answer:

  • Why might a production system use different thresholds for different attack types?
  • What is the trade-off between low thresholds (quick response) and high thresholds (fewer false positives)?
  • How would you determine optimal thresholds for a smart home vs. industrial IoT system?

Expected Observation: Injection attacks have lower thresholds (2 attempts) because they indicate higher attacker sophistication and potential for immediate damage, while brute force requires more attempts (5) because individual failed logins could be legitimate user errors.

Exercise 2: DREAD Score Analysis

Objective: Understand how DREAD scores change with attack patterns.

Tasks:

  1. Trigger a single brute force attack and note the DREAD scores in the Serial Monitor
  2. Trigger 5 more brute force attacks and compare how scores change
  3. Do the same for replay attacks

Analysis Questions:

  • Which DREAD factor increases most with repeated attacks?
  • Why does “Affected Users” increase with attack count?
  • Calculate: If initial DREAD score is 6.0 and mitigation reduces it by 40%, what is residual risk?

Expected Observation: Reproducibility and Affected Users scores increase with repeated attacks, reflecting that the attacker has found a reliable attack vector that could scale to more targets.

Interactive DREAD Score Calculator

Exercise 3: Attack Pattern Correlation

Objective: Observe how multiple attack types combine to elevate threat levels.

Tasks:

  1. Start fresh (press Reset button)
  2. Trigger 2 brute force attacks (below threshold)
  3. Trigger 2 replay attacks (below threshold)
  4. Observe the overall risk score
  5. Now trigger 1 injection attack

Analysis Questions:

  • Does the system consider multiple low-severity events together?
  • How would you modify the code to detect coordinated multi-vector attacks?
  • In real systems, what is “attack chain analysis”?

Expected Observation: Individual attacks below threshold don’t trigger alerts, but the overall risk score accumulates, reflecting that a determined attacker often probes with multiple techniques before finding a successful vector.

Exercise 4: Lockout Recovery Analysis

Objective: Understand automated vs. manual security recovery.

Tasks:

  1. Trigger enough injection attacks to cause lockout
  2. Wait for automatic lockout expiration (30 seconds)
  3. Note what threat level the system returns to
  4. Compare with pressing the Reset button during lockout

Analysis Questions:

  • Why does automatic recovery return to HIGH threat rather than NORMAL?
  • What are the security implications of automatic lockout expiration?
  • How would you implement “progressive lockout” (longer duration for repeat offenders)?

Expected Observation: Automatic recovery maintains elevated threat level because the attack source hasn’t been verified as legitimate - manual review (Reset button) is required for full return to normal operations.

Challenge Exercise: Extend the Threat Detector

Advanced Challenge: Modify the code to add these features:

  1. Time-of-Day Sensitivity: Increase threat scores for attacks occurring outside business hours (hint: use millis() modulo to simulate hour-of-day)

  2. Attack Source Tracking: Add a simulated “IP address” to each attack and detect if multiple attack types come from the same source (coordinated attack)

  3. Adaptive Thresholds: Reduce thresholds after a lockout event (the system becomes more sensitive after being attacked)

  4. STRIDE Coverage Report: Add a function that prints which STRIDE categories have been observed and which remain undetected

  5. Risk Trend Analysis: Track risk score over time and alert if it’s trending upward even without threshold breaches

Hint: These extensions mirror real Security Information and Event Management (SIEM) system capabilities.


35.2.7 Expected Outcomes

After completing this lab, you should be able to:

Skill Demonstration
Attack Detection Explain how pattern matching identifies brute force, replay, and injection attacks
STRIDE Classification Map each attack type to appropriate STRIDE categories
DREAD Scoring Calculate DREAD scores and interpret risk levels
Threshold Design Justify different thresholds for different attack types
Automated Response Describe the lockout mechanism and recovery process
Security Logging Explain the importance of timestamped security events
Risk Aggregation Understand how multiple events combine into overall risk

35.2.8 Connection to Real-World Systems

This lab simulates concepts used in production security systems:

Lab Concept Production Equivalent
Button presses Network traffic / API calls
Attack patterns Intrusion Detection System (IDS) signatures
DREAD scores Security Information and Event Management (SIEM) risk scoring
Threshold alerts Security Operations Center (SOC) alerting
Lockout mechanism Automated incident response / firewall rules
Event log Security audit trail / forensic evidence
Real-World Application

The concepts demonstrated here are implemented in production systems like:

  • AWS GuardDuty: Detects brute force, injection, and reconnaissance attacks on cloud resources
  • Splunk Enterprise Security: SIEM with DREAD-like risk scoring and automated response
  • CrowdStrike Falcon: Endpoint detection with pattern-based threat identification
  • Azure Sentinel: Cloud-native SIEM with automated playbook responses

Understanding these fundamentals prepares you for implementing and configuring enterprise security monitoring systems.

35.3 Knowledge Check

35.4 What’s Next

If you want to… Read this
Study the theoretical basis for the lab attacks Threats Attacks and Vulnerabilities
Explore more structured IoT security lab exercises IoT Security Hands-On Labs
Apply lab findings to threat scenario analysis Threat Attack Scenarios
Practise additional scenario-based exercises Threats Exercises
Return to the security module overview IoT Security Fundamentals

Scenario: Your company deploys 5,000 IoT payment terminals across retail stores. The threat detection system (similar to this lab) monitors failed authentication attempts. You need to set the brute-force lockout threshold.

Initial Configuration: 5 failed attempts within 10 seconds triggers lockout (lab default)

Field Data After 30 Days:

  • Total lockout events: 12,400
  • Legitimate user errors (forgot PIN, wrong card): 11,800 (95%)
  • Actual brute-force attacks detected: 600 (5%)
  • Customer complaints about “locked out for no reason”: 1,247

Analysis: The 5-attempt threshold causes 95% false positives, frustrating customers.

Threshold Tuning Process:

Threshold False Positives/Month Attacks Missed Customer Impact Security Impact
3 attempts/10s 18,200 (too high) 0 Very negative Maximum security
5 attempts/10s 11,800 (current) 0 Negative High security
10 attempts/10s 4,200 120 (20%) Moderate Good security
15 attempts/10s 800 250 (42%) Low Acceptable security
20 attempts/10s 200 350 (58%) Minimal Inadequate security

Optimal Solution: 10 attempts within 15 seconds (increased window) - False positives drop 64% (11,800 → 4,200) - Catches 80% of attacks (only 20% missed, mostly sophisticated slow attacks) - Customer complaints drop 75% (1,247 → 312)

Additional Mitigations:

  1. Progressive delay: First 5 failures = no penalty. 6-10 failures = 10-second delay. 11+ = lockout.
  2. Time-of-day weighting: Attacks at 3 AM get lower threshold (5 attempts) than noon (15 attempts)
  3. Geo-anomaly detection: Failed attempts from unusual country trigger immediate lockout
  4. Recovery UX: Locked terminals display “Call support: 1-800-…” instead of silent failure

Lesson: Lab threshold values (5 attempts) optimize for demonstration, not production. Real-world tuning requires balancing false positives (user frustration) against false negatives (missed attacks). Start conservative (low threshold), analyze telemetry for 30-60 days, then adjust based on actual attack vs. error patterns.

Option A: Hard Lockout (Lab implementation) - After N failed attempts, account/device is completely locked - Requires manual intervention (admin reset, customer support call, password reset email) - Pros: Maximum attack prevention - Cons: Creates denial-of-service vector (attacker locks out legitimate users)

Option B: Progressive Delay

  • 1st failure: immediate retry
  • 2nd-3rd failure: 5-second delay
  • 4th-6th failure: 30-second delay
  • 7th+ failure: 5-minute delay (doubles each attempt)
  • Pros: No lockout DoS, self-recovers
  • Cons: Allows slow brute-force (attacker can continue indefinitely)

Option C: Hybrid (Best Practice) - Progressive delay for first 10 attempts (accommodates user errors) - Hard lockout after 10 attempts within 1 hour (stops automated attacks) - Time-based auto-unlock (e.g., 24-hour lockout, then auto-reset) - Pros: Balances usability and security - Cons: Complex implementation

Use Case Recommended Approach Rationale
Consumer IoT (smart locks) Hybrid (10 attempts, 24h lockout) Users forget codes; auto-recovery critical
Payment terminals Progressive delay only Hard lockout = lost revenue; PCI-DSS requires fraud detection, not lockout
Industrial HMI Hard lockout (3 attempts, admin reset) Safety-critical; no auto-recovery acceptable
Web admin panels Hard lockout + CAPTCHA (5 attempts) High-value target; CAPTCHA stops bots before lockout

Decision factors:

  1. Attack surface: Internet-facing needs stricter (more attacks)
  2. Impact of lockout: Can users self-recover or is support call required?
  3. Attacker persistence: Sophisticated attackers use slow attacks (progressive delay helps)
  4. Regulatory requirements: PCI-DSS, HIPAA may mandate specific thresholds
Common Mistake: Logging Sensitive Data in Security Events

What practitioners do wrong: Logging the actual failed password attempts in security event logs for “forensic analysis.” Example: eventLog.password = user_input;

Why it fails: The security log now contains plaintext passwords! If an attacker gains log access (common after initial compromise), they harvest: - Actual passwords users attempted (often reveals correct password with typos: “Pa\[w0rd" vs "Pa\]w0rd1”) - Password patterns showing what users think is “secure” - Credentials reused across systems

Real-world example - Adobe breach (2013): Security logs contained plaintext password hints. When the database leaked, attackers cross-referenced hints with encrypted passwords, recovering 150 million passwords. The security logging mechanism itself became the vulnerability.

Correct approach - This lab does it right:

SecurityEvent event;
event.description = "Brute force attempt #3";  // Count, not content
// NEVER: event.password = attemptedPassword;

What to log instead:

  1. Timestamp: When the attempt occurred
  2. Source identifier: Device ID, IP address (hashed if privacy-sensitive)
  3. Event type: Brute force, replay, injection (STRIDE category)
  4. Count: Attempt number within time window
  5. Outcome: Blocked, allowed, triggered lockout

What NEVER to log:

  • Plaintext passwords (even failed attempts)
  • Full credit card numbers (PCI-DSS violation)
  • Unencrypted personal data (GDPR violation)
  • Session tokens or API keys

The lab demonstrates proper logging: stores attack metadata (count, timestamp, DREAD score) without exposing the attack payload itself.

Common Pitfalls

Beginning a lab attack without predicting the expected result prevents learning from unexpected outcomes. Write down what you expect to happen before each step, then compare the actual result to identify where your mental model was incorrect.

A lab that demonstrates a vulnerability but does not implement and verify the fix teaches attack skills without defence skills. Always implement the mitigation and verify that the attack no longer succeeds.

A lab system compromised in a previous exercise may affect the results of subsequent labs. Reset to a known-good state (snapshot revert, fresh image flash) between lab exercises to ensure results reflect the specific vulnerability being studied.

Security labs performed without peer review miss the learning benefit of explaining your reasoning to another person and receiving different perspectives on attack paths and mitigations. Pair up for lab exercises wherever possible.

35.5 Summary

This hands-on threat detection lab demonstrated practical security monitoring implementation:

Detection Techniques:

  • Pattern recognition using time-windowed attack frequency analysis
  • Multi-layer threat classification (brute force, replay, injection attacks)
  • Statistical anomaly detection with Z-score thresholds
  • STRIDE taxonomy mapping for threat categorization

Risk Assessment:

  • DREAD methodology for quantifying threat severity (Damage, Reproducibility, Exploitability, Affected Users, Discoverability)
  • Dynamic risk scoring that adapts to attack patterns
  • Threshold-based escalation from normal to warning to critical states

Automated Response:

  • Graduated escalation with visual feedback through LED indicators
  • Threshold-triggered lockouts preventing further attacks
  • Event logging for forensic analysis without storing sensitive payloads
  • Recovery mechanisms balancing security with availability

Key Lessons:

  • Threshold tuning requires balancing false positives (blocking legitimate users) against false negatives (missing attacks)
  • Different attack types warrant different sensitivity levels based on damage potential
  • Automated systems reduce detection time from days to minutes
  • Production deployments need field data to optimize thresholds for specific use cases

Key Takeaway: Effective threat detection requires understanding attack patterns, quantifying risk systematically, and tuning automated responses based on operational requirements and risk tolerance.

35.6 Further Reading

  • Microsoft STRIDE Threat Modeling
  • ENISA IoT Security Guidelines
  • NIST SP 800-30: Risk Assessment Guide
  • OWASP IoT Top 10
  • Mirai Botnet Technical Analysis