Conduct systematic threat modeling using STRIDE framework, attack trees, and security architecture analysis for CIA platform
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.
Apply this skill when:
Do NOT use for:
Threats to Consider:
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:
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");
}
}
}
Threats to Consider:
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:
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
);
}
Threats to Consider:
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:
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");
}
}
Threats to Consider:
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:
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();
}
}
Threats to Consider:
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:
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);
}
}
Threats to Consider:
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:
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;
}
}
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]
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)
Level 0 DFD - Context Diagram:
[Public Users] ā (CIA Web App) ā [Database]
[Admin Users] ā (CIA Web App) ā [External APIs]
Security Analysis:
# 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]
Threat Management Framework:
All Hack23 ISMS Policies: https://github.com/Hack23/ISMS-PUBLIC