threat-modeling
Threat Modeling Skill
Purpose
This skill provides structured methodology for identifying, analyzing, and mitigating security threats in the CIA platform using industry-standard frameworks including STRIDE, PASTA, and attack tree analysis. It ensures proactive security design aligned with Hack23 ISMS requirements.
When to Use This Skill
Apply this skill when:
- ✅ Designing new features that handle sensitive political data
- ✅ Integrating external APIs (Riksdagen, World Bank, Election Authority)
- ✅ Implementing authentication or authorization mechanisms
- ✅ Modifying security architecture or trust boundaries
- ✅ Before major releases to identify residual risks
- ✅ After security incidents to prevent recurrence
- ✅ Conducting annual security architecture reviews
Do NOT use for:
- ❌ Routine bug fixes without security implications
- ❌ UI/UX changes that don't affect security
- ❌ Performance optimizations (unless affecting security)
STRIDE Threat Model Framework
S - Spoofing Identity
Threats to Consider:
- Attackers impersonating legitimate users
- Session hijacking or fixation
- Credential theft or replay attacks
- API key theft and misuse
CIA Platform Attack Scenarios:
Threat: Attacker impersonates politician to modify profile data
├─ Entry Point: User authentication endpoint (/login)
├─ Attack Vector: Credential stuffing with breached password databases
├─ Impact: Reputational damage, data integrity loss
└─ Mitigation:
├─ Implement rate limiting (5 attempts per 15 minutes)
├─ Enable 2FA for sensitive accounts
├─ Monitor for suspicious login patterns
└─ Enforce strong password policy (12+ chars, complexity)
Mitigation Checklist:
- ✅ Multi-factor authentication for privileged accounts
- ✅ Certificate-based authentication for API clients
- ✅ Strong password policies (bcrypt with cost factor 12)
- ✅ Session tokens with HMAC integrity protection
- ✅ JWT signature verification for API tokens
Code Pattern:
@Service
public class AuthenticationService {
private static final int MAX_LOGIN_ATTEMPTS = 5;
private static final Duration LOCKOUT_PERIOD = Duration.ofMinutes(15);
@Autowired
private LoginAttemptService loginAttemptService;
@Autowired
private UserDetailsService userDetailsService;
public AuthenticationToken authenticate(LoginRequest request) {
String username = request.getUsername();
// Check if account is locked due to failed attempts
if (loginAttemptService.isLocked(username)) {
throw new AccountLockedException(
"Account temporarily locked. Try again in " +
loginAttemptService.getTimeUntilUnlock(username) + " minutes"
);
}
try {
// Authenticate user
UserDetails user = userDetailsService.loadUserByUsername(username);
if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
loginAttemptService.recordFailedAttempt(username);
throw new BadCredentialsException("Invalid credentials");
}
// Success - reset attempt counter
loginAttemptService.resetAttempts(username);
// Generate secure token
return tokenService.generateToken(user);
} catch (UsernameNotFoundException e) {
// Don't reveal if username exists
throw new BadCredentialsException("Invalid credentials");
}
}
}
T - Tampering with Data
Threats to Consider:
- Modification of politician voting records
- Alteration of financial data or reports
- Database injection attacks
- Parameter tampering in HTTP requests
CIA Platform Attack Scenarios:
Threat: Attacker modifies politician absence rate to damage reputation
├─ Entry Point: REST API endpoint /api/politicians/{id}/data
├─ Attack Vector: SQL injection via unvalidated input parameters
├─ Impact: Data integrity compromise, false political analysis
└─ Mitigation:
├─ Use JPA parameterized queries exclusively
├─ Implement data integrity checks (checksums, timestamps)
├─ Enable database audit logging
└─ Apply digital signatures to critical data
Mitigation Checklist:
- ✅ All database queries use parameterized statements
- ✅ Input validation on all user-provided data
- ✅ Data integrity checks (checksums, digital signatures)
- ✅ Database audit logging enabled
- ✅ CSRF protection on all state-changing operations
- ✅ Immutable data structures for sensitive information
Code Pattern:
@Entity
@Table(name = "politician_voting_record")
@Audited // Hibernate Envers for audit trail
public class VotingRecord {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
private String politicianId;
@Column(nullable = false)
private String voteType;
@Column(nullable = false)
private LocalDateTime voteDate;
// Integrity protection - computed hash of critical fields
@Column(name = "data_hash")
private String dataHash;
@PrePersist
@PreUpdate
private void calculateHash() {
this.dataHash = DigestUtils.sha256Hex(
politicianId + voteType + voteDate.toString()
);
}
public boolean verifyIntegrity() {
String expectedHash = DigestUtils.sha256Hex(
politicianId + voteType + voteDate.toString()
);
return expectedHash.equals(this.dataHash);
}
}
@Repository
public interface VotingRecordRepository extends JpaRepository<VotingRecord, Long> {
// Safe: JPA query with named parameters
@Query("SELECT v FROM VotingRecord v WHERE v.politicianId = :politicianId " +
"AND v.voteDate BETWEEN :startDate AND :endDate")
List<VotingRecord> findByPoliticianAndDateRange(
@Param("politicianId") String politicianId,
@Param("startDate") LocalDateTime startDate,
@Param("endDate") LocalDateTime endDate
);
}
R - Repudiation
Threats to Consider:
- Users denying actions they performed
- Lack of audit trails for sensitive operations
- Missing transaction logs
- Insufficient evidence for security investigations
CIA Platform Attack Scenarios:
Threat: Administrator denies modifying user permissions
├─ Entry Point: Admin panel /admin/users/{id}/permissions
├─ Attack Vector: No audit logging of administrative actions
├─ Impact: Accountability loss, inability to investigate incidents
└─ Mitigation:
├─ Implement comprehensive audit logging
├─ Log all authentication and authorization events
├─ Include timestamps, user identity, IP address, action details
└─ Store logs in tamper-proof storage (write-once)
Mitigation Checklist:
- ✅ Comprehensive audit logging for all sensitive operations
- ✅ Logs include: timestamp, user, IP, action, outcome
- ✅ Logs stored in tamper-resistant storage
- ✅ Log retention policy enforced (minimum 1 year)
- ✅ Regular log review and analysis
- ✅ Digital signatures on critical transactions
Code Pattern:
@Component
@Aspect
public class AuditLoggingAspect {
private static final Logger auditLog = LoggerFactory.getLogger("AUDIT");
@Autowired
private AuditLogRepository auditLogRepository;
@Around("@annotation(Audited)")
public Object logAuditEvent(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String methodName = signature.getName();
String className = signature.getDeclaringTypeName();
// Capture context
String username = SecurityContextHolder.getContext()
.getAuthentication().getName();
String ipAddress = RequestContextHolder.currentRequestAttributes()
.getSessionId();
AuditLogEntry entry = new AuditLogEntry();
entry.setTimestamp(Instant.now());
entry.setUsername(username);
entry.setIpAddress(ipAddress);
entry.setAction(className + "." + methodName);
entry.setParameters(Arrays.toString(joinPoint.getArgs()));
try {
// Execute the method
Object result = joinPoint.proceed();
entry.setOutcome("SUCCESS");
entry.setResult(result != null ? result.toString() : "void");
return result;
} catch (Exception e) {
entry.setOutcome("FAILURE");
entry.setErrorMessage(e.getMessage());
throw e;
} finally {
// Always log, even on failure
auditLogRepository.save(entry);
auditLog.info("Audit: {}", entry.toJson());
}
}
}
@Entity
@Table(name = "audit_log")
public class AuditLogEntry {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false, updatable = false)
private Instant timestamp;
@Column(nullable = false, updatable = false)
private String username;
@Column(updatable = false)
private String ipAddress;
@Column(nullable = false, updatable = false)
private String action;
@Column(updatable = false, columnDefinition = "TEXT")
private String parameters;
@Column(nullable = false, updatable = false)
private String outcome;
// Immutable - prevent tampering
@PreUpdate
private void preventUpdate() {
throw new IllegalStateException("Audit log entries cannot be modified");
}
}
I - Information Disclosure
Threats to Consider:
- Exposure of personal identifiable information (PII)
- Leakage of API keys or credentials
- Verbose error messages revealing system details
- Insufficient access controls on sensitive data
CIA Platform Attack Scenarios:
Threat: Attacker accesses politician personal contact information
├─ Entry Point: Public API endpoint /api/politicians/{id}
├─ Attack Vector: Insufficient access control, over-fetching data
├─ Impact: GDPR violation, privacy breach
└─ Mitigation:
├─ Implement field-level access control
├─ Return only public data in API responses
├─ Redact or mask sensitive fields (phone, email)
└─ Log all access to PII for audit purposes
Mitigation Checklist:
- ✅ Sensitive data encrypted at rest (database encryption)
- ✅ TLS 1.2+ for all data in transit
- ✅ Error messages sanitized (no stack traces in production)
- ✅ Access control on all data endpoints
- ✅ Data classification and handling procedures
- ✅ PII minimization and purpose limitation
Code Pattern:
@RestController
@RequestMapping("/api/politicians")
public class PoliticianController {
@GetMapping("/{id}")
public ResponseEntity<PoliticianDTO> getPolitician(
@PathVariable String id,
@AuthenticationPrincipal UserDetails currentUser) {
Politician politician = politicianService.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("Politician not found"));
// Apply field-level filtering based on user role
PoliticianDTO dto = mapToDTO(politician, currentUser);
// Log PII access for audit
auditLogger.logPIIAccess(currentUser.getUsername(), "Politician", id);
return ResponseEntity.ok(dto);
}
private PoliticianDTO mapToDTO(Politician politician, UserDetails user) {
PoliticianDTO dto = new PoliticianDTO();
// Always include public information
dto.setFirstName(politician.getFirstName());
dto.setLastName(politician.getLastName());
dto.setParty(politician.getParty());
dto.setDistrict(politician.getDistrict());
// Only include sensitive data for authorized users
if (hasRole(user, "ADMIN") || hasRole(user, "RESEARCHER")) {
// Redact instead of exposing full data
dto.setEmail(redactEmail(politician.getEmail()));
dto.setPhone(redactPhone(politician.getPhone()));
}
return dto;
}
private String redactEmail(String email) {
if (email == null) return null;
int atIndex = email.indexOf('@');
if (atIndex > 2) {
return email.substring(0, 2) + "***" + email.substring(atIndex);
}
return "***" + email.substring(atIndex);
}
}
@Configuration
public class SecurityHeadersConfig {
@Bean
public SecurityFilterChain securityHeaders(HttpSecurity http) throws Exception {
http.headers(headers -> headers
.contentSecurityPolicy("default-src 'self'; script-src 'self'; style-src 'self'")
.xssProtection()
.frameOptions().deny()
.httpStrictTransportSecurity()
.maxAgeInSeconds(31536000)
.includeSubDomains(true)
);
return http.build();
}
}
D - Denial of Service
Threats to Consider:
- Resource exhaustion attacks (CPU, memory, disk)
- Application-level DoS (expensive queries)
- Distributed denial of service (DDoS)
- API abuse and rate limit bypass
CIA Platform Attack Scenarios:
Threat: Attacker overwhelms system with expensive political data queries
├─ Entry Point: Public search API /api/search?query=*
├─ Attack Vector: Recursive queries, unbounded result sets
├─ Impact: Service unavailability, degraded performance for legitimate users
└─ Mitigation:
├─ Implement rate limiting (100 requests/minute per IP)
├─ Query result pagination (max 100 results per page)
├─ Timeout for long-running queries (30 seconds)
└─ Resource quotas per user tier
Mitigation Checklist:
- ✅ Rate limiting on all public APIs
- ✅ Request size limits enforced
- ✅ Query timeouts configured
- ✅ Pagination on all list endpoints
- ✅ Resource monitoring and alerting
- ✅ Circuit breakers for external dependencies
Code Pattern:
@Configuration
public class RateLimitingConfig {
@Bean
public RateLimiter apiRateLimiter() {
return RateLimiter.create(100.0); // 100 requests per second
}
}
@Component
public class RateLimitingInterceptor implements HandlerInterceptor {
@Autowired
private RateLimiter rateLimiter;
private final LoadingCache<String, AtomicInteger> requestCounts = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.MINUTES)
.build(new CacheLoader<String, AtomicInteger>() {
public AtomicInteger load(String key) {
return new AtomicInteger(0);
}
});
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
String clientIp = getClientIP(request);
// Apply rate limit
if (!rateLimiter.tryAcquire(1, TimeUnit.SECONDS)) {
response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
response.getWriter().write("Rate limit exceeded. Try again later.");
return false;
}
// Check per-IP limit
int requestCount = requestCounts.get(clientIp).incrementAndGet();
if (requestCount > 1000) {
response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
response.getWriter().write("IP-based rate limit exceeded.");
return false;
}
return true;
}
}
@Repository
public interface PoliticianSearchRepository extends JpaRepository<Politician, Long> {
// Pageable prevents unbounded result sets
@Query("SELECT p FROM Politician p WHERE " +
"LOWER(p.firstName) LIKE LOWER(CONCAT('%', :searchTerm, '%')) OR " +
"LOWER(p.lastName) LIKE LOWER(CONCAT('%', :searchTerm, '%'))")
@QueryHints(@QueryHint(name = "org.hibernate.timeout", value = "30")) // 30 second timeout
Page<Politician> search(@Param("searchTerm") String searchTerm, Pageable pageable);
}
@RestController
public class SearchController {
private static final int MAX_PAGE_SIZE = 100;
@GetMapping("/api/search")
public Page<PoliticianDTO> search(
@RequestParam String query,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size) {
// Enforce maximum page size
if (size > MAX_PAGE_SIZE) {
size = MAX_PAGE_SIZE;
}
Pageable pageable = PageRequest.of(page, size);
return searchService.search(query, pageable);
}
}
E - Elevation of Privilege
Threats to Consider:
- Horizontal privilege escalation (access other users' data)
- Vertical privilege escalation (gain admin rights)
- Bypassing authorization checks
- Exploiting misconfigured access controls
CIA Platform Attack Scenarios:
Threat: Regular user gains administrative access to modify site configuration
├─ Entry Point: Admin API endpoint /api/admin/settings
├─ Attack Vector: Missing @PreAuthorize annotation on controller method
├─ Impact: Unauthorized configuration changes, system compromise
└─ Mitigation:
├─ Enforce role-based access control on all endpoints
├─ Use Spring Security annotations (@PreAuthorize, @Secured)
├─ Implement defense in depth (controller + service layer checks)
└─ Regular access control audits
Mitigation Checklist:
- ✅ Role-based access control (RBAC) implemented
- ✅ Principle of least privilege enforced
- ✅ Authorization checks at multiple layers
- ✅ Regular access control reviews
- ✅ Privilege escalation attempts logged and alerted
- ✅ No default or backdoor admin accounts
Code Pattern:
@RestController
@RequestMapping("/api/admin")
@PreAuthorize("hasRole('ADMIN')") // Controller-level authorization
public class AdminController {
@PostMapping("/settings")
@PreAuthorize("hasAuthority('MODIFY_SETTINGS')") // Method-level check
public ResponseEntity<SystemSettings> updateSettings(
@RequestBody @Valid SystemSettingsRequest request,
@AuthenticationPrincipal UserDetails currentUser) {
// Log privileged action
auditLogger.logPrivilegedAction(
currentUser.getUsername(),
"UPDATE_SYSTEM_SETTINGS",
request.toString()
);
// Service layer also enforces authorization
SystemSettings updated = adminService.updateSettings(request);
return ResponseEntity.ok(updated);
}
}
@Service
public class AdminService {
@PreAuthorize("hasRole('ADMIN')")
public SystemSettings updateSettings(SystemSettingsRequest request) {
// Verify authorization again at service layer (defense in depth)
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (!auth.getAuthorities().stream()
.anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"))) {
throw new AccessDeniedException("Admin role required");
}
// Perform update
SystemSettings settings = settingsRepository.findCurrent();
settings.updateFrom(request);
return settingsRepository.save(settings);
}
}
// Global method security enabled
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler handler =
new DefaultMethodSecurityExpressionHandler();
handler.setPermissionEvaluator(new CustomPermissionEvaluator());
return handler;
}
}
Attack Tree Analysis
Example: Compromise Politician Data Integrity
ROOT: Compromise Politician Voting Record Data
├─ AND: Gain Write Access
│ ├─ OR: Exploit Authentication
│ │ ├─ Brute force credentials [Mitigated: Rate limiting]
│ │ ├─ Credential stuffing [Mitigated: 2FA]
│ │ └─ Session hijacking [Mitigated: Secure cookies]
│ └─ OR: Exploit Authorization
│ ├─ Privilege escalation [Mitigated: RBAC]
│ └─ IDOR vulnerability [Mitigated: Ownership checks]
└─ AND: Modify Data
├─ OR: Direct Database Access
│ ├─ SQL injection [Mitigated: Parameterized queries]
│ └─ Database credential theft [Mitigated: Secrets management]
└─ OR: API Manipulation
├─ Parameter tampering [Mitigated: Input validation]
└─ CSRF attack [Mitigated: CSRF tokens]
Attack Tree Legend:
- AND: All child nodes must succeed
- OR: Any child node success achieves goal
- [Mitigated]: Control in place, residual risk accepted
Security Architecture Review
Trust Boundaries
Internet Users (Untrusted)
│
├─→ Application Firewall / Rate Limiter
│ │
│ ├─→ Spring Boot Application (DMZ)
│ │ │
│ │ ├─→ Authentication Filter
│ │ ├─→ Authorization Filter
│ │ └─→ CSRF Protection
│ │
│ └─→ Internal Network (Trusted)
│ │
│ ├─→ PostgreSQL Database (Encrypted)
│ └─→ Redis Session Store (Encrypted)
│
└─→ External APIs (Semi-Trusted)
├─→ Riksdagen API (HTTPS only)
├─→ World Bank API (HTTPS only)
└─→ Election Authority API (HTTPS only)
Data Flow Diagram (DFD) Security Analysis
Level 0 DFD - Context Diagram:
[Public Users] → (CIA Web App) → [Database]
[Admin Users] → (CIA Web App) → [External APIs]
Security Analysis:
- Public Users: Untrusted, require authentication for sensitive operations
- Admin Users: Trusted but verify, require strong authentication (2FA)
- External APIs: Semi-trusted, validate all responses
- Database: Trusted, encrypted at rest and in transit
Threat Model Documentation Template
# Threat Model: [Feature Name]
## Overview
- **Component**: [Component being analyzed]
- **Last Updated**: [Date]
- **Reviewer**: [Name]
- **Risk Rating**: [Critical/High/Medium/Low]
## Assets
1. Politician personal information (GDPR protected)
2. Voting records (integrity critical)
3. User credentials (confidentiality critical)
4. API keys for external services
## Trust Boundaries
- Internet → Application Server
- Application Server → Database
- Application Server → External APIs
## STRIDE Analysis
### Spoofing
- **Threat**: [Description]
- **Likelihood**: [High/Medium/Low]
- **Impact**: [High/Medium/Low]
- **Risk**: [Critical/High/Medium/Low]
- **Mitigation**: [Controls in place]
- **Residual Risk**: [Accepted/Needs treatment]
[Repeat for T, R, I, D, E]
## Attack Trees
[Attach attack tree diagrams]
## Security Requirements
1. [Requirement 1]
2. [Requirement 2]
## Security Test Cases
1. Test authentication bypass attempts
2. Test authorization escalation
3. Test input validation
## ISMS Compliance
- ISO 27001:2022 A.5.15 (Access Control)
- NIST CSF PR.AC-4 (Access Permissions)
- CIS Control 6.1 (Access Control Management)
## Sign-off
- **Security Team**: [Approved/Rejected]
- **Development Team**: [Approved/Rejected]
- **Date**: [Date]
ISMS Compliance Mapping
ISO 27001:2022 Controls
- A.5.15 - Access Control: STRIDE analysis ensures proper access controls
- A.8.8 - Management of Technical Vulnerabilities: Threat modeling identifies vulnerabilities proactively
- A.14.2.1 - Secure Development Policy: Threat modeling is mandatory step in SDLC
- A.16.1 - Management of Information Security Incidents: Attack trees inform incident response
NIST Cybersecurity Framework
- ID.RA-1: Vulnerabilities identified through threat modeling
- ID.RA-3: Threats identified internally and externally
- PR.IP-1: Baseline security configurations from threat analysis
- DE.CM-4: System monitored for malicious activity based on threat model
CIS Controls v8
- Control 18.3: Establish and maintain architecture documentation
- Control 18.4: Establish secure application design
- Control 18.5: Document application design flaws
Hack23 ISMS Policy References
Threat Management Framework:
- Threat Modeling - Official STRIDE methodology and attack trees
- Risk Register - Identified risks and treatments
- Risk Assessment Methodology - Quantitative risk analysis
- Secure Development Policy - Security-by-design requirements
- Information Security Strategy - Defense-in-depth architecture
- Incident Response Plan - Response procedures
- Vulnerability Management - Vulnerability lifecycle
All Hack23 ISMS Policies: https://github.com/Hack23/ISMS-PUBLIC
CIA Platform Architecture References
- Threat Model: CIA THREAT_MODEL.md - Complete STRIDE analysis
- Security Architecture: CIA SECURITY_ARCHITECTURE.md - Control implementation
- Future Security: CIA FUTURE_SECURITY_ARCHITECTURE.md - Enhancement roadmap
- System Architecture: CIA ARCHITECTURE.md - C4 models and DFDs
- Data Model: CIA DATA_MODEL.md - Data flows
References
Threat Modeling Standards
- Microsoft STRIDE: https://learn.microsoft.com/en-us/azure/security/develop/threat-modeling-tool
- OWASP Threat Modeling: https://owasp.org/www-community/Threat_Modeling
- PASTA Methodology: https://versprite.com/pasta-threat-modeling/
- MITRE ATT&CK: https://attack.mitre.org/
- ISO 27005:2022: https://www.iso.org/standard/80585.html
- NIST SP 800-30: https://csrc.nist.gov/publications/detail/sp/800-30/rev-1/final
Tools & Frameworks
- Microsoft Threat Modeling Tool: https://www.microsoft.com/en-us/securityengineering/sdl/threatmodeling
- OWASP Threat Dragon: https://owasp.org/www-project-threat-dragon/
- Draw.io for DFDs: https://app.diagrams.net/