Files
hiveops-aria/src/main/java/com/hiveops/aria/service/ThreatEventClassifier.java
T
johannes e5f25f1c2c
CD - Develop / build-and-deploy (push) Failing after 11m31s
feat: Phase 1 — ARIA ATM threat monitoring service
- Spring Boot service on port 8095, database hiveiq_aria
- Flyway schema: threat_ioc, threat_event, precursor_sequence_alert, device_security_posture
- FBI FLASH-20260219-001 IOC seed data (executables, MD5s, directories, registry keys, services)
- ThreatEventClassifier — maps 20+ signal keys to severity + attack phase + IOC match
- ThreatEventIngestionService — persists events, publishes HIGH/CRITICAL to Kafka
- Kafka producer: topic hiveops.aria.threats (AriaThreatEvent payload)
- ThreatIocController — CRUD IOC management (MSP_ADMIN/BCOS_ADMIN)
- ThreatEventIngestionController — agent-facing ingest endpoint with service secret auth
- CI/CD: cd-develop.yml + cd-main.yml
2026-06-14 09:30:46 -04:00

171 lines
6.7 KiB
Java

package com.hiveops.aria.service;
import com.hiveops.aria.dto.ThreatEventItem;
import com.hiveops.aria.entity.ThreatEvent;
import com.hiveops.aria.entity.ThreatEvent.AttackPhase;
import com.hiveops.aria.entity.ThreatEvent.ThreatSeverity;
import com.hiveops.aria.entity.ThreatIoc;
import com.hiveops.aria.repository.ThreatIocRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Optional;
@Service
@RequiredArgsConstructor
@Slf4j
public class ThreatEventClassifier {
private final ThreatIocRepository iocRepository;
public ClassificationResult classify(ThreatEventItem item) {
String signal = item.getSignalKey();
ThreatSeverity severity;
AttackPhase phase = null;
ThreatIoc matchedIoc = null;
switch (signal) {
// Windows Security Event IDs — FBI FLASH-20260219-001
case "EVENT_1102" -> {
severity = ThreatSeverity.CRITICAL;
phase = AttackPhase.CLEANUP;
}
case "EVENT_4719" -> {
severity = ThreatSeverity.HIGH;
phase = AttackPhase.CLEANUP;
}
case "EVENT_6416", "EVENT_2003" -> {
severity = ThreatSeverity.HIGH;
phase = AttackPhase.PHYSICAL_ACCESS;
matchedIoc = matchUsb(item);
}
case "EVENT_4663" -> {
severity = ThreatSeverity.HIGH;
phase = AttackPhase.MALWARE_STAGING;
matchedIoc = matchFilePath(item);
}
case "EVENT_4688" -> {
matchedIoc = matchProcessName(item);
if (matchedIoc != null) {
severity = ThreatSeverity.HIGH;
phase = AttackPhase.MALWARE_EXECUTION;
} else {
severity = ThreatSeverity.INFO;
}
}
case "EVENT_4697" -> {
matchedIoc = matchServiceName(item);
if (matchedIoc != null) {
severity = ThreatSeverity.HIGH;
phase = AttackPhase.PERSISTENCE;
} else {
severity = ThreatSeverity.MEDIUM;
phase = AttackPhase.PERSISTENCE;
}
}
// Physical sensor signals
case "DOOR_OPEN" -> {
severity = ThreatSeverity.MEDIUM;
phase = AttackPhase.PHYSICAL_ACCESS;
}
case "CARD_READER_TAMPER" -> {
severity = ThreatSeverity.HIGH;
phase = AttackPhase.PHYSICAL_ACCESS;
}
case "USB_INSERTION" -> {
severity = ThreatSeverity.HIGH;
phase = AttackPhase.PHYSICAL_ACCESS;
}
case "POWER_CYCLE_UNEXPECTED", "OUT_OF_SERVICE" -> {
severity = ThreatSeverity.MEDIUM;
}
case "VIBRATION_ANOMALY" -> {
severity = ThreatSeverity.MEDIUM;
}
case "CASH_LOW_UNEXPECTED" -> {
severity = ThreatSeverity.HIGH;
}
// File system signals
case "HASH_DRIFT" -> {
severity = ThreatSeverity.HIGH;
phase = AttackPhase.MALWARE_STAGING;
}
case "IOC_PROCESS_MATCH", "IOC_FILENAME_MATCH" -> {
matchedIoc = matchProcessName(item);
severity = ThreatSeverity.HIGH;
phase = AttackPhase.MALWARE_EXECUTION;
}
case "REGISTRY_PERSISTENCE_DETECTED" -> {
matchedIoc = matchRegistryKey(item);
severity = ThreatSeverity.HIGH;
phase = AttackPhase.PERSISTENCE;
}
case "SUSPICIOUS_DIRECTORY" -> {
matchedIoc = matchDirectory(item);
severity = ThreatSeverity.HIGH;
phase = AttackPhase.MALWARE_STAGING;
}
case "REMOTE_TOOL_DETECTED" -> {
matchedIoc = matchProcessName(item);
severity = ThreatSeverity.MEDIUM;
}
default -> {
severity = ThreatSeverity.INFO;
log.debug("Unclassified signal key: {}", signal);
}
}
return new ClassificationResult(severity, phase, matchedIoc);
}
private ThreatIoc matchProcessName(ThreatEventItem item) {
String name = extractString(item, "processName", "imageName", "fileName");
if (name == null) return null;
return iocRepository.findByActiveTrueAndIocTypeAndValueIgnoreCase(ThreatIoc.IocType.FILENAME, name).orElse(null);
}
private ThreatIoc matchServiceName(ThreatEventItem item) {
String name = extractString(item, "serviceName", "serviceDisplayName");
if (name == null) return null;
return iocRepository.findByActiveTrueAndIocTypeAndValueIgnoreCase(ThreatIoc.IocType.SERVICE_NAME, name).orElse(null);
}
private ThreatIoc matchFilePath(ThreatEventItem item) {
String path = extractString(item, "objectName", "filePath");
if (path == null) return null;
Optional<ThreatIoc> dir = iocRepository.findByActiveTrueAndIocTypeAndValueIgnoreCase(ThreatIoc.IocType.DIRECTORY, path);
return dir.orElseGet(() ->
iocRepository.findByActiveTrueAndIocTypeAndValueIgnoreCase(ThreatIoc.IocType.FILE_PATH, path).orElse(null));
}
private ThreatIoc matchRegistryKey(ThreatEventItem item) {
String key = extractString(item, "registryKey", "keyPath");
if (key == null) return null;
return iocRepository.findByActiveTrueAndIocTypeAndValueIgnoreCase(ThreatIoc.IocType.REGISTRY_KEY, key).orElse(null);
}
private ThreatIoc matchDirectory(ThreatEventItem item) {
String path = extractString(item, "directory", "path");
if (path == null) return null;
return iocRepository.findByActiveTrueAndIocTypeAndValueIgnoreCase(ThreatIoc.IocType.DIRECTORY, path).orElse(null);
}
private ThreatIoc matchUsb(ThreatEventItem item) {
String deviceId = extractString(item, "deviceId", "deviceDescription");
if (deviceId == null) return null;
return iocRepository.findByActiveTrueAndIocTypeAndValueIgnoreCase(ThreatIoc.IocType.IP, deviceId).orElse(null);
}
private String extractString(ThreatEventItem item, String... keys) {
if (item.getRawPayload() == null) return null;
for (String key : keys) {
Object val = item.getRawPayload().get(key);
if (val instanceof String s && !s.isBlank()) return s;
}
return null;
}
public record ClassificationResult(ThreatSeverity severity, AttackPhase attackPhase, ThreatIoc matchedIoc) {}
}