Privilege Escalation Monitor in Java

Introduction to Privilege Escalation Monitoring

Privilege escalation monitoring detects and prevents unauthorized elevation of privileges in Java applications. This includes monitoring file permissions, process privileges, user context changes, and suspicious system operations that could lead to security breaches.

Core Security Monitoring

Security Monitor Service

/** * Privilege Escalation Monitoring Service * Monitors system for privilege escalation attempts and suspicious activities */ @Service @Slf4j public class PrivilegeEscalationMonitor { private final SecurityEventService securityEventService; private final AlertService alertService; private final SystemAccessMonitor systemAccessMonitor; private final FileSystemMonitor fileSystemMonitor; private final ProcessMonitor processMonitor; private ScheduledExecutorService monitorScheduler; private final Map<String, MonitoringRule> activeRules; private final List<SecurityEvent> detectedEvents; public PrivilegeEscalationMonitor(SecurityEventService securityEventService, AlertService alertService, SystemAccessMonitor systemAccessMonitor, FileSystemMonitor fileSystemMonitor, ProcessMonitor processMonitor) { this.securityEventService = securityEventService; this.alertService = alertService; this.systemAccessMonitor = systemAccessMonitor; this.fileSystemMonitor = fileSystemMonitor; this.processMonitor = processMonitor; this.activeRules = new ConcurrentHashMap<>(); this.detectedEvents = new CopyOnWriteArrayList<>(); initializeMonitor(); } @PostConstruct public void startMonitoring() { log.info("Starting privilege escalation monitoring"); initializeRules(); startPeriodicScans(); startRealTimeMonitoring(); } @PreDestroy public void stopMonitoring() { log.info("Stopping privilege escalation monitoring"); if (monitorScheduler != null) { monitorScheduler.shutdown(); try { if (!monitorScheduler.awaitTermination(30, TimeUnit.SECONDS)) { monitorScheduler.shutdownNow(); } } catch (InterruptedException e) { monitorScheduler.shutdownNow(); Thread.currentThread().interrupt(); } } } /** * Monitors for privilege escalation patterns */ public void monitorPrivilegeEscalation() { try { // Monitor file system for suspicious permissions monitorFilePermissions(); // Monitor process privileges monitorProcessPrivileges(); // Monitor user context changes monitorUserContext(); // Monitor system configuration changes monitorSystemConfiguration(); // Check for suspicious system calls monitorSystemCalls(); } catch (Exception e) { log.error("Error during privilege escalation monitoring", e); } } /** * Monitors file permissions for suspicious changes */ private void monitorFilePermissions() { try { List<FilePermissionViolation> violations = fileSystemMonitor.checkFilePermissions(); for (FilePermissionViolation violation : violations) { if (isSuspiciousPermissionChange(violation)) { reportPrivilegeEscalationEvent( "SUSPICIOUS_FILE_PERMISSION", "File permission change may enable privilege escalation", Map.of( "file", violation.getFilePath(), "permission", violation.getPermission(), "owner", violation.getOwner(), "previousPermission", violation.getPreviousPermission() ), Severity.HIGH ); } } } catch (Exception e) { log.error("Error monitoring file permissions", e); } } /** * Monitors process privileges and elevation attempts */ private void monitorProcessPrivileges() { try { List<ProcessPrivilegeInfo> privilegedProcesses = processMonitor.getPrivilegedProcesses(); for (ProcessPrivilegeInfo process : privilegedProcesses) { if (isSuspiciousPrivilegedProcess(process)) { reportPrivilegeEscalationEvent( "SUSPICIOUS_PRIVILEGED_PROCESS", "Process running with elevated privileges", Map.of( "processId", process.getPid(), "processName", process.getName(), "user", process.getUser(), "privileges", process.getPrivileges() ), Severity.HIGH ); } } // Monitor for privilege elevation attempts List<ProcessExecution> elevationAttempts = processMonitor.getPrivilegeElevationAttempts(); for (ProcessExecution attempt : elevationAttempts) { reportPrivilegeEscalationEvent( "PRIVILEGE_ELEVATION_ATTEMPT", "Attempt to elevate process privileges detected", Map.of( "process", attempt.getProcessName(), "command", attempt.getCommandLine(), "user", attempt.getUser(), "targetUser", attempt.getTargetUser() ), Severity.CRITICAL ); } } catch (Exception e) { log.error("Error monitoring process privileges", e); } } /** * Monitors user context and role changes */ private void monitorUserContext() { try { List<UserSession> activeSessions = systemAccessMonitor.getActiveSessions(); for (UserSession session : activeSessions) { if (isSuspiciousUserSession(session)) { reportPrivilegeEscalationEvent( "SUSPICIOUS_USER_SESSION", "Suspicious user session detected", Map.of( "user", session.getUsername(), "sessionId", session.getSessionId(), "loginTime", session.getLoginTime(), "source", session.getSourceIp(), "privileges", session.getPrivileges() ), Severity.MEDIUM ); } } // Monitor for user privilege changes List<UserPrivilegeChange> privilegeChanges = systemAccessMonitor.getRecentPrivilegeChanges(); for (UserPrivilegeChange change : privilegeChanges) { if (isUnauthorizedPrivilegeChange(change)) { reportPrivilegeEscalationEvent( "UNAUTHORIZED_PRIVILEGE_CHANGE", "Unauthorized user privilege change detected", Map.of( "user", change.getUsername(), "changedBy", change.getChangedBy(), "privilege", change.getPrivilege(), "action", change.getAction(), "timestamp", change.getTimestamp() ), Severity.CRITICAL ); } } } catch (Exception e) { log.error("Error monitoring user context", e); } } /** * Monitors system configuration for security changes */ private void monitorSystemConfiguration() { try { // Monitor sudoers configuration monitorSudoersConfiguration(); // Monitor service permissions monitorServicePermissions(); // Monitor scheduled tasks monitorScheduledTasks(); // Monitor environment variables monitorEnvironmentVariables(); } catch (Exception e) { log.error("Error monitoring system configuration", e); } } /** * Monitors system calls for suspicious activities */ private void monitorSystemCalls() { try { List<SystemCall> suspiciousCalls = systemAccessMonitor.getSuspiciousSystemCalls(); for (SystemCall systemCall : suspiciousCalls) { if (isPrivilegeEscalationSystemCall(systemCall)) { reportPrivilegeEscalationEvent( "SUSPICIOUS_SYSTEM_CALL", "Suspicious system call detected", Map.of( "call", systemCall.getCallName(), "process", systemCall.getProcessName(), "pid", systemCall.getPid(), "user", systemCall.getUser(), "arguments", systemCall.getArguments() ), Severity.HIGH ); } } } catch (Exception e) { log.error("Error monitoring system calls", e); } } private void monitorSudoersConfiguration() { try { List<SudoersEntry> suspiciousEntries = systemAccessMonitor.getSuspiciousSudoersEntries(); for (SudoersEntry entry : suspiciousEntries) { reportPrivilegeEscalationEvent( "SUSPICIOUS_SUDOERS_ENTRY", "Suspicious sudoers configuration detected", Map.of( "user", entry.getUser(), "host", entry.getHost(), "command", entry.getCommand(), "runAs", entry.getRunAsUser() ), Severity.HIGH ); } } catch (Exception e) { log.error("Error monitoring sudoers configuration", e); } } private void monitorServicePermissions() { try { List<ServicePermission> suspiciousServices = systemAccessMonitor.getServicesWithElevatedPermissions(); for (ServicePermission service : suspiciousServices) { reportPrivilegeEscalationEvent( "SERVICE_WITH_ELEVATED_PERMISSIONS", "Service running with elevated permissions", Map.of( "service", service.getServiceName(), "user", service.getRunAsUser(), "permissions", service.getPermissions() ), Severity.MEDIUM ); } } catch (Exception e) { log.error("Error monitoring service permissions", e); } } private void monitorScheduledTasks() { try { List<ScheduledTask> suspiciousTasks = systemAccessMonitor.getSuspiciousScheduledTasks(); for (ScheduledTask task : suspiciousTasks) { reportPrivilegeEscalationEvent( "SUSPICIOUS_SCHEDULED_TASK", "Suspicious scheduled task with elevated privileges", Map.of( "task", task.getTaskName(), "command", task.getCommand(), "user", task.getRunAsUser(), "schedule", task.getSchedule() ), Severity.HIGH ); } } catch (Exception e) { log.error("Error monitoring scheduled tasks", e); } } private void monitorEnvironmentVariables() { try { List<EnvironmentVariable> suspiciousVars = systemAccessMonitor.getSuspiciousEnvironmentVariables(); for (EnvironmentVariable envVar : suspiciousVars) { reportPrivilegeEscalationEvent( "SUSPICIOUS_ENVIRONMENT_VARIABLE", "Suspicious environment variable with privilege implications", Map.of( "variable", envVar.getName(), "value", envVar.getValue(), "process", envVar.getProcessName() ), Severity.MEDIUM ); } } catch (Exception e) { log.error("Error monitoring environment variables", e); } } /** * Reports a privilege escalation event */ private void reportPrivilegeEscalationEvent(String eventType, String description, Map<String, Object> details, Severity severity) { SecurityEvent event = SecurityEvent.builder() .eventType(eventType) .severity(severity) .description(description) .timestamp(Instant.now()) .source("PrivilegeEscalationMonitor") .details(details) .build(); detectedEvents.add(event); securityEventService.recordEvent(event); // Trigger alert for critical events if (severity == Severity.CRITICAL || severity == Severity.HIGH) { alertService.sendImmediateAlert(event); } log.warn("Privilege escalation event detected: {} - {}", eventType, description); } private boolean isSuspiciousPermissionChange(FilePermissionViolation violation) { // Check for world-writable sensitive files if (violation.getPermission().contains("w") && violation.getPermission().contains("other") && isSensitiveFile(violation.getFilePath())) { return true; } // Check for SUID/SGID binaries in unusual locations if ((violation.getPermission().contains("s") || violation.getPermission().contains("S")) && isSuspiciousLocation(violation.getFilePath())) { return true; } return false; } private boolean isSuspiciousPrivilegedProcess(ProcessPrivilegeInfo process) { // Check for processes running as root from non-standard users if ("root".equals(process.getUser()) && !isExpectedRootProcess(process.getName())) { return true; } // Check for processes with excessive privileges if (process.getPrivileges().size() > 5) { return true; } // Check for processes accessing sensitive resources if (isAccessingSensitiveResources(process)) { return true; } return false; } private boolean isSuspiciousUserSession(UserSession session) { // Check for root logins from non-console if ("root".equals(session.getUsername()) && !session.getSourceIp().equals("localhost") && !session.getSourceIp().equals("127.0.0.1")) { return true; } // Check for multiple simultaneous sessions from same user if (hasMultipleSimultaneousSessions(session)) { return true; } // Check for sessions with unusual privilege sets if (hasUnusualPrivileges(session)) { return true; } return false; } private boolean isUnauthorizedPrivilegeChange(UserPrivilegeChange change) { // Check if privilege change was performed by unauthorized user if (!isAuthorizedPrivilegeManager(change.getChangedBy())) { return true; } // Check for sensitive privilege additions if ("ADD".equals(change.getAction()) && isSensitivePrivilege(change.getPrivilege())) { return true; } return false; } private boolean isPrivilegeEscalationSystemCall(SystemCall systemCall) { Set<String> privilegeEscalationCalls = Set.of( "setuid", "setgid", "setreuid", "setregid", "setresuid", "setresgid", "capset", "prctl" ); return privilegeEscalationCalls.contains(systemCall.getCallName()); } // Helper methods for detection logic private boolean isSensitiveFile(String filePath) { Set<String> sensitiveFiles = Set.of( "/etc/passwd", "/etc/shadow", "/etc/sudoers", "/etc/crontab", "/root/.ssh/", "/etc/ssh/" ); return sensitiveFiles.stream().anyMatch(filePath::contains); } private boolean isSuspiciousLocation(String filePath) { Set<String> suspiciousLocations = Set.of( "/tmp", "/var/tmp", "/dev/shm", "/home" ); return suspiciousLocations.stream().anyMatch(filePath::contains); } private boolean isExpectedRootProcess(String processName) { Set<String> expectedRootProcesses = Set.of( "systemd", "init", "sshd", "crond", "syslogd" ); return expectedRootProcesses.contains(processName); } private boolean isAccessingSensitiveResources(ProcessPrivilegeInfo process) { // Implementation would check process file descriptors and resources return false; } private boolean hasMultipleSimultaneousSessions(UserSession session) { // Implementation would check session count for user return false; } private boolean hasUnusualPrivileges(UserSession session) { // Implementation would check against baseline privileges return false; } private boolean isAuthorizedPrivilegeManager(String username) { Set<String> authorizedUsers = Set.of("root", "admin", "security-admin"); return authorizedUsers.contains(username); } private boolean isSensitivePrivilege(String privilege) { Set<String> sensitivePrivileges = Set.of( "ALL", "SUDO", "DBA", "ROOT", "ADMIN" ); return sensitivePrivileges.contains(privilege.toUpperCase()); } private void initializeMonitor() { this.monitorScheduler = Executors.newScheduledThreadPool(3, r -> { Thread t = new Thread(r, "privilege-monitor"); t.setDaemon(true); return t; }); } private void initializeRules() { // Add monitoring rules activeRules.put("FILE_PERMISSION_MONITOR", new MonitoringRule("FILE_PERMISSION_MONITOR", "Monitor sensitive file permissions", MonitoringRule.Severity.HIGH)); activeRules.put("PROCESS_PRIVILEGE_MONITOR", new MonitoringRule("PROCESS_PRIVILEGE_MONITOR", "Monitor process privilege escalation", MonitoringRule.Severity.CRITICAL)); activeRules.put("USER_PRIVILEGE_MONITOR", new MonitoringRule("USER_PRIVILEGE_MONITOR", "Monitor user privilege changes", MonitoringRule.Severity.HIGH)); } private void startPeriodicScans() { // Schedule periodic monitoring monitorScheduler.scheduleAtFixedRate( this::monitorPrivilegeEscalation, 0, 60, TimeUnit.SECONDS); // Schedule comprehensive scans monitorScheduler.scheduleAtFixedRate( this::performComprehensiveScan, 0, 300, TimeUnit.SECONDS); } private void startRealTimeMonitoring() { // Start real-time monitoring based on platform capabilities if (isLinuxSystem()) { startLinuxRealTimeMonitoring(); } else if (isWindowsSystem()) { startWindowsRealTimeMonitoring(); } } private void performComprehensiveScan() { log.info("Starting comprehensive privilege escalation scan"); // Comprehensive scanning logic } private boolean isLinuxSystem() { return System.getProperty("os.name").toLowerCase().contains("linux"); } private boolean isWindowsSystem() { return System.getProperty("os.name").toLowerCase().contains("windows"); } private void startLinuxRealTimeMonitoring() { // Linux-specific real-time monitoring log.info("Starting Linux real-time privilege monitoring"); } private void startWindowsRealTimeMonitoring() { // Windows-specific real-time monitoring log.info("Starting Windows real-time privilege monitoring"); } /** * Gets detected privilege escalation events */ public List<SecurityEvent> getDetectedEvents() { return new ArrayList<>(detectedEvents); } /** * Gets events by severity */ public List<SecurityEvent> getEventsBySeverity(Severity severity) { return detectedEvents.stream() .filter(event -> event.getSeverity() == severity) .collect(Collectors.toList()); } /** * Clears old events */ public void clearEventsOlderThan(Duration duration) { Instant cutoff = Instant.now().minus(duration); detectedEvents.removeIf(event -> event.getTimestamp().isBefore(cutoff)); } }

File System Monitoring

File System Security Monitor

/** * File System Security Monitor * Monitors file permissions, ownership, and sensitive file access */ @Service @Slf4j public class FileSystemMonitor { private final Set<String> monitoredPaths; private final Map<String, FileSnapshot> fileSnapshots; private final WatchService watchService; private final Set<Path> watchedDirectories; public FileSystemMonitor() throws IOException { this.monitoredPaths = ConcurrentHashMap.newKeySet(); this.fileSnapshots = new ConcurrentHashMap<>(); this.watchService = FileSystems.getDefault().newWatchService(); this.watchedDirectories = ConcurrentHashMap.newKeySet(); initializeDefaultPaths(); } /** * Checks file permissions for violations */ public List<FilePermissionViolation> checkFilePermissions() { List<FilePermissionViolation> violations = new ArrayList<>(); for (String path : monitoredPaths) { try { violations.addAll(checkPathPermissions(Paths.get(path))); } catch (Exception e) { log.error("Error checking permissions for path: {}", path, e); } } return violations; } /** * Monitors file system changes in real-time */ public void startRealTimeMonitoring() { Thread monitorThread = new Thread(this::monitorFileEvents, "file-monitor"); monitorThread.setDaemon(true); monitorThread.start(); } /** * Adds a path to monitor */ public void addMonitoredPath(String path) { monitoredPaths.add(path); try { Path dirPath = Paths.get(path); if (Files.isDirectory(dirPath)) { WatchKey key = dirPath.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE); watchedDirectories.add(dirPath); log.info("Started monitoring directory: {}", path); } } catch (IOException e) { log.error("Failed to monitor directory: {}", path, e); } } /** * Takes snapshot of current file state */ public void takeSnapshot() { fileSnapshots.clear(); for (String path : monitoredPaths) { try { takePathSnapshot(Paths.get(path)); } catch (Exception e) { log.error("Error taking snapshot for path: {}", path, e); } } log.info("File system snapshot completed. Monitored files: {}", fileSnapshots.size()); } /** * Detects changes since last snapshot */ public List<FileSystemChange> detectChanges() { List<FileSystemChange> changes = new ArrayList<>(); for (String path : monitoredPaths) { try { changes.addAll(detectPathChanges(Paths.get(path))); } catch (Exception e) { log.error("Error detecting changes for path: {}", path, e); } } return changes; } private List<FilePermissionViolation> checkPathPermissions(Path path) throws IOException { List<FilePermissionViolation> violations = new ArrayList<>(); Files.walk(path) .filter(Files::isRegularFile) .forEach(file -> { try { FilePermissionViolation violation = checkFilePermission(file); if (violation != null) { violations.add(violation); } } catch (IOException e) { log.error("Error checking file permissions: {}", file, e); } }); return violations; } private FilePermissionViolation checkFilePermission(Path file) throws IOException { PosixFileAttributes attrs = Files.readAttributes(file, PosixFileAttributes.class); PosixFilePermissions.toString(attrs.permissions()); String permissions = PosixFilePermissions.toString(attrs.permissions()); String filename = file.toString(); // Check for world-writable files if (permissions.contains("w") && permissions.contains("other")) { if (isSensitiveFile(filename)) { return new FilePermissionViolation( filename, permissions, attrs.owner().getName(), "World-writable sensitive file", FilePermissionViolation.Type.WORLD_WRITABLE_SENSITIVE ); } } // Check for SUID/SGID files if (permissions.contains("s") || permissions.contains("S")) { if (isSuspiciousSuidFile(filename)) { return new FilePermissionViolation( filename, permissions, attrs.owner().getName(), "Suspicious SUID/SGID file", FilePermissionViolation.Type.SUSPICIOUS_SUID ); } } // Check for files owned by root with non-root group if ("root".equals(attrs.owner().getName()) && !"root".equals(attrs.group().getName())) { return new FilePermissionViolation( filename, permissions, attrs.owner().getName(), "Root-owned file with non-root group", FilePermissionViolation.Type.ROOT_NON_ROOT_GROUP ); } return null; } private void monitorFileEvents() { while (!Thread.currentThread().isInterrupted()) { try { WatchKey key = watchService.take(); Path dir = (Path) key.watchable(); for (WatchEvent<?> event : key.pollEvents()) { WatchEvent.Kind<?> kind = event.kind(); Path filename = (Path) event.context(); Path child = dir.resolve(filename); handleFileEvent(kind, child); } boolean valid = key.reset(); if (!valid) { watchedDirectories.remove(dir); log.warn("Watch key no longer valid for: {}", dir); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } catch (Exception e) { log.error("Error in file monitoring", e); } } } private void handleFileEvent(WatchEvent.Kind<?> kind, Path file) { try { if (Files.exists(file)) { PosixFileAttributes attrs = Files.readAttributes(file, PosixFileAttributes.class); String permissions = PosixFilePermissions.toString(attrs.permissions()); // Check for permission changes if (kind == StandardWatchEventKinds.ENTRY_MODIFY) { FileSnapshot previous = fileSnapshots.get(file.toString()); if (previous != null && !previous.getPermissions().equals(permissions)) { log.warn("File permission changed: {} -> {}", previous.getPermissions(), permissions); // Report permission change event } } // Update snapshot fileSnapshots.put(file.toString(), new FileSnapshot(file.toString(), permissions, attrs.owner().getName(), attrs.lastModifiedTime())); } } catch (IOException e) { log.error("Error handling file event: {}", file, e); } } private void takePathSnapshot(Path path) throws IOException { Files.walk(path) .filter(Files::isRegularFile) .forEach(file -> { try { PosixFileAttributes attrs = Files.readAttributes(file, PosixFileAttributes.class); String permissions = PosixFilePermissions.toString(attrs.permissions()); fileSnapshots.put(file.toString(), new FileSnapshot(file.toString(), permissions, attrs.owner().getName(), attrs.lastModifiedTime())); } catch (IOException e) { log.error("Error taking snapshot for file: {}", file, e); } }); } private List<FileSystemChange> detectPathChanges(Path path) throws IOException { List<FileSystemChange> changes = new ArrayList<>(); Files.walk(path) .filter(Files::isRegularFile) .forEach(file -> { try { FileSystemChange change = detectFileChange(file); if (change != null) { changes.add(change); } } catch (IOException e) { log.error("Error detecting changes for file: {}", file, e); } }); return changes; } private FileSystemChange detectFileChange(Path file) throws IOException { String filePath = file.toString(); FileSnapshot currentSnapshot = fileSnapshots.get(filePath); if (currentSnapshot == null) { return new FileSystemChange(filePath, FileSystemChange.Type.CREATED, "New file detected", Instant.now()); } PosixFileAttributes currentAttrs = Files.readAttributes(file, PosixFileAttributes.class); String currentPermissions = PosixFilePermissions.toString(currentAttrs.permissions()); if (!currentPermissions.equals(currentSnapshot.getPermissions())) { return new FileSystemChange(filePath, FileSystemChange.Type.PERMISSION_CHANGED, String.format("Permissions changed from %s to %s", currentSnapshot.getPermissions(), currentPermissions), Instant.now()); } if (!currentAttrs.owner().getName().equals(currentSnapshot.getOwner())) { return new FileSystemChange(filePath, FileSystemChange.Type.OWNER_CHANGED, String.format("Owner changed from %s to %s", currentSnapshot.getOwner(), currentAttrs.owner().getName()), Instant.now()); } return null; } private void initializeDefaultPaths() { // Add default sensitive paths to monitor addMonitoredPath("/etc"); addMonitoredPath("/root"); addMonitoredPath("/usr/bin"); addMonitoredPath("/usr/sbin"); addMonitoredPath("/var/log"); } private boolean isSensitiveFile(String filename) { Set<String> sensitivePatterns = Set.of( "passwd", "shadow", "sudoers", "crontab", "ssh", ".pem", ".key", ".crt", ".p12" ); return sensitivePatterns.stream().anyMatch(filename::contains); } private boolean isSuspiciousSuidFile(String filename) { Set<String> expectedSuidFiles = Set.of( "passwd", "su", "sudo", "mount", "umount", "ping" ); String baseName = Paths.get(filename).getFileName().toString(); return !expectedSuidFiles.contains(baseName); } } /** * File system data models */ @Data @AllArgsConstructor public class FilePermissionViolation { private String filePath; private String permission; private String owner; private String description; private Type type; public enum Type { WORLD_WRITABLE_SENSITIVE, SUSPICIOUS_SUID, ROOT_NON_ROOT_GROUP, EXCESSIVE_PERMISSIONS } } @Data @AllArgsConstructor public class FileSnapshot { private String filePath; private String permissions; private String owner; private FileTime lastModified; } @Data @AllArgsConstructor public class FileSystemChange { private String filePath; private Type type; private String description; private Instant detectedAt; public enum Type { CREATED, DELETED, MODIFIED, PERMISSION_CHANGED, OWNER_CHANGED } }

Process Monitoring

Process Security Monitor

/** * Process Security Monitor * Monitors process execution, privileges, and suspicious activities */ @Service @Slf4j public class ProcessMonitor { private final Set<String> monitoredProcesses; private final Map<Integer, ProcessInfo> activeProcesses; private final ScheduledExecutorService processScanner; public ProcessMonitor() { this.monitoredProcesses = ConcurrentHashMap.newKeySet(); this.activeProcesses = new ConcurrentHashMap<>(); this.processScanner = Executors.newScheduledThreadPool(1, r -> { Thread t = new Thread(r, "process-scanner"); t.setDaemon(true); return t; }); initializeProcessMonitoring(); } /** * Gets processes with elevated privileges */ public List<ProcessPrivilegeInfo> getPrivilegedProcesses() { List<ProcessPrivilegeInfo> privilegedProcesses = new ArrayList<>(); try { // Use platform-specific tools to get process information if (isLinuxSystem()) { privilegedProcesses.addAll(getLinuxPrivilegedProcesses()); } else if (isWindowsSystem()) { privilegedProcesses.addAll(getWindowsPrivilegedProcesses()); } } catch (Exception e) { log.error("Error getting privileged processes", e); } return privilegedProcesses; } /** * Gets privilege elevation attempts */ public List<ProcessExecution> getPrivilegeElevationAttempts() { List<ProcessExecution> elevationAttempts = new ArrayList<>(); try { // Monitor for sudo/su executions elevationAttempts.addAll(getSudoExecutions()); // Monitor for runas executions (Windows) if (isWindowsSystem()) { elevationAttempts.addAll(getRunasExecutions()); } } catch (Exception e) { log.error("Error getting privilege elevation attempts", e); } return elevationAttempts; } /** * Monitors process creation and termination */ public void startProcessMonitoring() { processScanner.scheduleAtFixedRate(this::scanProcesses, 0, 5, TimeUnit.SECONDS); } /** * Checks for suspicious process behavior */ public List<ProcessAnomaly> checkProcessAnomalies() { List<ProcessAnomaly> anomalies = new ArrayList<>(); try { // Check for process injection anomalies.addAll(checkProcessInjection()); // Check for unusual parent-child relationships anomalies.addAll(checkParentChildAnomalies()); // Check for process masquerading anomalies.addAll(checkProcessMasquerading()); } catch (Exception e) { log.error("Error checking process anomalies", e); } return anomalies; } private List<ProcessPrivilegeInfo> getLinuxPrivilegedProcesses() throws IOException { List<ProcessPrivilegeInfo> processes = new ArrayList<>(); // Parse /proc for process information File procDir = new File("/proc"); File[] processDirs = procDir.listFiles(File::isDirectory); if (processDirs != null) { for (File processDir : processDirs) { try { int pid = Integer.parseInt(processDir.getName()); ProcessPrivilegeInfo processInfo = getLinuxProcessInfo(pid); if (processInfo != null && processInfo.isPrivileged()) { processes.add(processInfo); } } catch (NumberFormatException e) { // Skip non-process directories } } } return processes; } private ProcessPrivilegeInfo getLinuxProcessInfo(int pid) throws IOException { Path statusPath = Paths.get("/proc", String.valueOf(pid), "status"); if (!Files.exists(statusPath)) { return null; } Map<String, String> status = new HashMap<>(); Files.lines(statusPath).forEach(line -> { String[] parts = line.split(":\t", 2); if (parts.length == 2) { status.put(parts[0].trim(), parts[1].trim()); } }); String name = status.get("Name"); String user = status.get("Uid"); String group = status.get("Gid"); ProcessPrivilegeInfo info = new ProcessPrivilegeInfo(); info.setPid(pid); info.setName(name); info.setUser(user); info.setGroup(group); // Check privileges if ("0".equals(user.split("\\s+")[0])) { // root user info.setPrivileged(true); info.getPrivileges().add("ROOT"); } // Check capabilities Set<String> capabilities = getProcessCapabilities(pid); info.getPrivileges().addAll(capabilities); return info; } private Set<String> getProcessCapabilities(int pid) throws IOException { Set<String> capabilities = new HashSet<>(); Path statusPath = Paths.get("/proc", String.valueOf(pid), "status"); if (Files.exists(statusPath)) { List<String> lines = Files.readAllLines(statusPath); for (String line : lines) { if (line.startsWith("Cap")) { capabilities.add(line.trim()); } } } return capabilities; } private List<ProcessPrivilegeInfo> getWindowsPrivilegedProcesses() { List<ProcessPrivilegeInfo> processes = new ArrayList<>(); try { // Use WMI or PowerShell to get process information ProcessBuilder pb = new ProcessBuilder("tasklist", "/fo", "csv", "/v"); Process process = pb.start(); String output = new String(process.getInputStream().readAllBytes()); String[] lines = output.split("\n"); for (String line : lines) { if (line.contains("NT AUTHORITY\\SYSTEM") || line.contains("Administrator")) { ProcessPrivilegeInfo info = parseWindowsProcessLine(line); if (info != null) { processes.add(info); } } } } catch (Exception e) { log.error("Error getting Windows privileged processes", e); } return processes; } private ProcessPrivilegeInfo parseWindowsProcessLine(String line) { // Parse CSV line from tasklist output String[] parts = line.split(","); if (parts.length >= 8) { ProcessPrivilegeInfo info = new ProcessPrivilegeInfo(); info.setName(parts[0].replace("\"", "").trim()); info.setPid(Integer.parseInt(parts[1].replace("\"", "").trim())); info.setUser(parts[6].replace("\"", "").trim()); info.setPrivileged(true); return info; } return null; } private List<ProcessExecution> getSudoExecutions() throws IOException { List<ProcessExecution> executions = new ArrayList<>(); // Parse auth.log or secure log for sudo executions Path authLog = Paths.get("/var/log/auth.log"); if (Files.exists(authLog)) { List<String> lines = Files.readAllLines(authLog); for (String line : lines) { if (line.contains("sudo:") && line.contains("COMMAND=")) { ProcessExecution execution = parseSudoLogLine(line); if (execution != null) { executions.add(execution); } } } } return executions; } private ProcessExecution parseSudoLogLine(String line) { // Parse sudo log line // Example: "sudo: user : TTY=pts/0 ; PWD=/home/user ; USER=root ; COMMAND=/bin/bash" ProcessExecution execution = new ProcessExecution(); String[] parts = line.split(";"); for (String part : parts) { if (part.contains("USER=")) { execution.setTargetUser(part.split("=")[1].trim()); } else if (part.contains("COMMAND=")) { execution.setCommandLine(part.split("=")[1].trim()); } } execution.setProcessName("sudo"); execution.setUser(System.getProperty("user.name")); return execution; } private List<ProcessExecution> getRunasExecutions() { // Windows runas command monitoring return new ArrayList<>(); // Implementation would use Windows event logs } private List<ProcessAnomaly> checkProcessInjection() { List<ProcessAnomaly> anomalies = new ArrayList<>(); // Check for process injection techniques // This would require platform-specific implementations return anomalies; } private List<ProcessAnomaly> checkParentChildAnomalies() { List<ProcessAnomaly> anomalies = new ArrayList<>(); // Check for unusual parent-child process relationships // e.g., browser spawning cmd.exe, word spawning powershell return anomalies; } private List<ProcessAnomaly> checkProcessMasquerading() { List<ProcessAnomaly> anomalies = new ArrayList<>(); // Check for process masquerading (e.g., lsass.exe vs lsass.exe) // Compare process names with expected locations and signatures return anomalies; } private void scanProcesses() { try { Map<Integer, ProcessInfo> currentProcesses = getCurrentProcesses(); // Detect new processes for (Integer pid : currentProcesses.keySet()) { if (!activeProcesses.containsKey(pid)) { ProcessInfo newProcess = currentProcesses.get(pid); handleNewProcess(newProcess); } } // Detect terminated processes for (Integer pid : activeProcesses.keySet()) { if (!currentProcesses.containsKey(pid)) { ProcessInfo terminatedProcess = activeProcesses.get(pid); handleTerminatedProcess(terminatedProcess); } } activeProcesses.clear(); activeProcesses.putAll(currentProcesses); } catch (Exception e) { log.error("Error scanning processes", e); } } private Map<Integer, ProcessInfo> getCurrentProcesses() { Map<Integer, ProcessInfo> processes = new HashMap<>(); try { ProcessHandle.allProcesses().forEach(handle -> { ProcessInfo info = new ProcessInfo(); info.setPid((int) handle.pid()); info.setCommand(handle.info().command().orElse("")); info.setUser(handle.info().user().orElse("")); info.setStartTime(handle.info().startInstant().orElse(Instant.now())); processes.put(info.getPid(), info); }); } catch (Exception e) { log.error("Error getting current processes", e); } return processes; } private void handleNewProcess(ProcessInfo process) { // Check if process is suspicious if (isSuspiciousProcess(process)) { log.warn("Suspicious process started: {} (PID: {})", process.getCommand(), process.getPid()); // Report security event SecurityEvent event = SecurityEvent.builder() .eventType("SUSPICIOUS_PROCESS_START") .severity(Severity.MEDIUM) .description("Suspicious process started: " + process.getCommand()) .timestamp(Instant.now()) .source("ProcessMonitor") .details(Map.of( "pid", process.getPid(), "command", process.getCommand(), "user", process.getUser() )) .build(); // Send to security event service } } private void handleTerminatedProcess(ProcessInfo process) { // Log process termination if it was being monitored if (monitoredProcesses.contains(process.getCommand())) { log.info("Monitored process terminated: {} (PID: {})", process.getCommand(), process.getPid()); } } private boolean isSuspiciousProcess(ProcessInfo process) { Set<String> suspiciousPatterns = Set.of( "meterpreter", "beacon", "cobaltstrike", "empire", "powershell -enc", "cmd /c", "wscript.shell", "regsvr32", "rundll32", "mshta" ); String command = process.getCommand().toLowerCase(); return suspiciousPatterns.stream().anyMatch(command::contains); } private void initializeProcessMonitoring() { // Add known suspicious processes to monitor monitoredProcesses.addAll(Set.of( "nc", "netcat", "socat", "ncat", "wget", "curl", "powershell", "python", "perl", "ruby", "php" )); startProcessMonitoring(); } private boolean isLinuxSystem() { return System.getProperty("os.name").toLowerCase().contains("linux"); } private boolean isWindowsSystem() { return System.getProperty("os.name").toLowerCase().contains("windows"); } } /** * Process monitoring data models */ @Data public class ProcessPrivilegeInfo { private int pid; private String name; private String user; private String group; private boolean privileged; private Set<String> privileges = new HashSet<>(); public boolean isPrivileged() { return privileged || !privileges.isEmpty(); } } @Data public class ProcessExecution { private String processName; private String commandLine; private String user; private String targetUser; private Instant executionTime; } @Data public class ProcessAnomaly { private int pid; private String processName; private String anomalyType; private String description; private Severity severity; private Instant detectedAt; } @Data public class ProcessInfo { private int pid; private String command; private String user; private Instant startTime; private String parentPid; }

Spring Boot Integration

Security Configuration

/** * Security configuration for privilege escalation monitoring */ @Configuration @EnableConfigurationProperties(SecurityMonitorProperties.class) public class SecurityMonitorConfiguration { @Bean @ConditionalOnProperty(name = "security.monitoring.privilege-escalation.enabled", havingValue = "true") public PrivilegeEscalationMonitor privilegeEscalationMonitor( SecurityEventService securityEventService, AlertService alertService, SystemAccessMonitor systemAccessMonitor, FileSystemMonitor fileSystemMonitor, ProcessMonitor processMonitor) { return new PrivilegeEscalationMonitor( securityEventService, alertService, systemAccessMonitor, fileSystemMonitor, processMonitor); } @Bean public FileSystemMonitor fileSystemMonitor() throws IOException { return new FileSystemMonitor(); } @Bean public ProcessMonitor processMonitor() { return new ProcessMonitor(); } @Bean public SystemAccessMonitor systemAccessMonitor() { return new SystemAccessMonitor(); } @Bean public SecurityEventService securityEventService() { return new SecurityEventService(); } @Bean public AlertService alertService() { return new AlertService(); } } /** * Security monitor properties */ @ConfigurationProperties(prefix = "security.monitoring") @Data public class SecurityMonitorProperties { private PrivilegeEscalation privilegeEscalation = new PrivilegeEscalation(); private FileSystem fileSystem = new FileSystem(); private Process process = new Process(); private Reporting reporting = new Reporting(); @Data public static class PrivilegeEscalation { private boolean enabled = true; private int scanInterval = 60; private boolean realTimeMonitoring = true; private List<String> monitoredPaths = List.of("/etc", "/root", "/usr/bin"); } @Data public static class FileSystem { private boolean enabled = true; private int snapshotInterval = 300; private List<String> sensitiveFiles = List.of( "/etc/passwd", "/etc/shadow", "/etc/sudoers" ); } @Data public static class Process { private boolean enabled = true; private int scanInterval = 5; private List<String> suspiciousProcesses = List.of( "nc", "netcat", "socat", "meterpreter" ); } @Data public static class Reporting { private boolean enabled = true; private String logLevel = "WARN"; private Webhook webhook = new Webhook(); private Email email = new Email(); @Data public static class Webhook { private String url; private String secret; } @Data public static class Email { private List<String> recipients; private String subjectPrefix = "[SECURITY]"; } } } /** * Security monitor health indicator */ @Component public class SecurityMonitorHealthIndicator implements HealthIndicator { private final PrivilegeEscalationMonitor privilegeMonitor; private final FileSystemMonitor fileSystemMonitor; private final ProcessMonitor processMonitor; public SecurityMonitorHealthIndicator(PrivilegeEscalationMonitor privilegeMonitor, FileSystemMonitor fileSystemMonitor, ProcessMonitor processMonitor) { this.privilegeMonitor = privilegeMonitor; this.fileSystemMonitor = fileSystemMonitor; this.processMonitor = processMonitor; } @Override public Health health() { try { Map<String, Object> details = new HashMap<>(); // Check monitoring components details.put("privilege_monitoring", "ACTIVE"); details.put("file_system_monitoring", "ACTIVE"); details.put("process_monitoring", "ACTIVE"); // Get recent events count List<SecurityEvent> recentEvents = privilegeMonitor.getEventsBySeverity(Severity.HIGH); details.put("high_severity_events", recentEvents.size()); return Health.up() .withDetails(details) .build(); } catch (Exception e) { return Health.down() .withDetail("error", e.getMessage()) .build(); } } } /** * Security monitor REST controller */ @RestController @RequestMapping("/api/security/monitoring") @Slf4j public class SecurityMonitorController { private final PrivilegeEscalationMonitor privilegeMonitor; public SecurityMonitorController(PrivilegeEscalationMonitor privilegeMonitor) { this.privilegeMonitor = privilegeMonitor; } @GetMapping("/events") public List<SecurityEvent> getSecurityEvents( @RequestParam(defaultValue = "1") int hours, @RequestParam(required = false) Severity severity) { List<SecurityEvent> events = privilegeMonitor.getDetectedEvents(); Instant cutoff = Instant.now().minus(Duration.ofHours(hours)); return events.stream() .filter(event -> event.getTimestamp().isAfter(cutoff)) .filter(event -> severity == null || event.getSeverity() == severity) .collect(Collectors.toList()); } @PostMapping("/scan") public ResponseEntity<String> triggerSecurityScan() { try { privilegeMonitor.monitorPrivilegeEscalation(); return ResponseEntity.ok("Security scan completed successfully"); } catch (Exception e) { log.error("Security scan failed", e); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("Security scan failed: " + e.getMessage()); } } @GetMapping("/status") public Map<String, Object> getMonitoringStatus() { Map<String, Object> status = new HashMap<>(); List<SecurityEvent> events = privilegeMonitor.getDetectedEvents(); Instant lastHour = Instant.now().minus(Duration.ofHours(1)); long criticalEvents = events.stream() .filter(event -> event.getTimestamp().isAfter(lastHour)) .filter(event -> event.getSeverity() == Severity.CRITICAL) .count(); long highEvents = events.stream() .filter(event -> event.getTimestamp().isAfter(lastHour)) .filter(event -> event.getSeverity() == Severity.HIGH) .count(); status.put("critical_events_last_hour", criticalEvents); status.put("high_events_last_hour", highEvents); status.put("total_events", events.size()); status.put("monitoring_active", true); status.put("last_scan", Instant.now()); return status; } }

Best Practices Summary

/** * PRIVILEGE ESCALATION MONITORING BEST PRACTICES * * 1. Monitor file permissions for sensitive files and directories * 2. Track process privileges and elevation attempts * 3. Monitor user sessions and privilege changes * 4. Implement real-time file system monitoring * 5. Use behavioral analysis to detect anomalies * 6. Establish baseline security configurations * 7. Implement comprehensive logging and alerting * 8. Regular security scanning and compliance checks * 9. Use principle of least privilege for monitoring * 10. Maintain audit trails for security events */ /** * Utility class with security monitoring best practices */ public final class SecurityMonitoringBestPractices { private SecurityMonitoringBestPractices() { // Utility class } /** * Validates security monitoring configuration */ public static List<String> validateConfiguration(SecurityMonitorProperties properties) { List<String> issues = new ArrayList<>(); if (properties.getPrivilegeEscalation().isEnabled() && properties.getPrivilegeEscalation().getMonitoredPaths().isEmpty()) { issues.add("No monitored paths configured for privilege escalation monitoring"); } if (properties.getFileSystem().isEnabled() && properties.getFileSystem().getSensitiveFiles().isEmpty()) { issues.add("No sensitive files configured for file system monitoring"); } if (properties.getReporting().isEnabled() && properties.getReporting().getWebhook().getUrl() == null && properties.getReporting().getEmail().getRecipients().isEmpty()) { issues.add("No reporting destinations configured"); } return issues; } /** * Generates security monitoring policy template */ public static String generateSecurityPolicy() { return """ security_monitoring: privilege_escalation: enabled: true scan_interval: 60 real_time_monitoring: true monitored_paths: - /etc - /root - /usr/bin - /usr/sbin file_system: enabled: true snapshot_interval: 300 sensitive_files: - /etc/passwd - /etc/shadow - /etc/sudoers - /root/.ssh/ process: enabled: true scan_interval: 5 suspicious_processes: - nc - netcat - socat - meterpreter """; } /** * Creates security monitoring checklist */ public static List<String> getMonitoringChecklist() { return Arrays.asList( "Enable file system permission monitoring", "Configure process privilege monitoring", "Set up user session monitoring", "Implement real-time file system watchers", "Configure security event logging", "Set up alerting for critical events", "Establish baseline security configurations", "Implement regular security scans", "Configure compliance checking", "Set up audit trail maintenance" ); } /** * Gets common privilege escalation indicators */ public static Set<String> getPrivilegeEscalationIndicators() { return Set.of( "World-writable sensitive files", "Suspicious SUID/SGID binaries", "Unauthorized privilege changes", "Suspicious process executions", "Unusual user session patterns", "Sudo/su abuse attempts", "Service permission changes", "Scheduled task modifications", "Environment variable tampering", "Process injection attempts" ); } }

Conclusion

The Privilege Escalation Monitor provides comprehensive security monitoring for Java applications:

  1. File System Security - Monitors permissions, ownership, and sensitive file access
  2. Process Monitoring - Tracks process privileges, executions, and suspicious activities
  3. User Session Security - Monitors user sessions, logins, and privilege changes
  4. Real-time Detection - Immediate detection of security events and anomalies
  5. Behavioral Analysis - Identifies suspicious patterns and escalation attempts
  6. Comprehensive Reporting - Detailed security event logging and alerting
  7. Integration Ready - Spring Boot integration with REST API endpoints
  8. Platform Support - Cross-platform monitoring for Linux and Windows

By implementing this monitoring solution, organizations can significantly improve their security posture by detecting and preventing privilege escalation attacks in real-time while maintaining comprehensive audit trails for compliance and forensic analysis.

Advanced Java Supply Chain Security, Kubernetes Hardening & Runtime Threat Detection

Sigstore Rekor in Java – https://macronepal.com/blog/sigstore-rekor-in-java/
Explains integrating Sigstore Rekor into Java systems to create a transparent, tamper-proof log of software signatures and metadata for verifying supply chain integrity.

Securing Java Applications with Chainguard Wolfi – https://macronepal.com/blog/securing-java-applications-with-chainguard-wolfi-a-comprehensive-guide/
Explains using Chainguard Wolfi minimal container images to reduce vulnerabilities and secure Java applications with hardened, lightweight runtime environments.

Cosign Image Signing in Java Complete Guide – https://macronepal.com/blog/cosign-image-signing-in-java-complete-guide/
Explains how to digitally sign container images using Cosign in Java-based workflows to ensure authenticity and prevent unauthorized modifications.

Secure Supply Chain Enforcement Kyverno Image Verification for Java Containers – https://macronepal.com/blog/secure-supply-chain-enforcement-kyverno-image-verification-for-java-containers/
Explains enforcing Kubernetes policies with Kyverno to verify container image signatures and ensure only trusted Java container images are deployed.

Pod Security Admission in Java Securing Kubernetes Deployments for JVM Applications – https://macronepal.com/blog/pod-security-admission-in-java-securing-kubernetes-deployments-for-jvm-applications/
Explains Kubernetes Pod Security Admission policies that enforce security rules like restricted privileges and safe configurations for Java workloads.

Securing Java Applications at Runtime Kubernetes Security Context – https://macronepal.com/blog/securing-java-applications-at-runtime-a-guide-to-kubernetes-security-context/
Explains how Kubernetes security contexts control runtime permissions, user IDs, and access rights for Java containers to improve isolation.

Process Anomaly Detection in Java Behavioral Monitoring – https://macronepal.com/blog/process-anomaly-detection-in-java-comprehensive-behavioral-monitoring-2/
Explains detecting abnormal runtime behavior in Java applications to identify potential security threats using process monitoring techniques.

Achieving Security Excellence CIS Benchmark Compliance for Java Applications – https://macronepal.com/blog/achieving-security-excellence-implementing-cis-benchmark-compliance-for-java-applications/
Explains applying CIS security benchmarks to Java environments to standardize hardening and improve overall system security posture.

Process Anomaly Detection in Java Behavioral Monitoring – https://macronepal.com/blog/process-anomaly-detection-in-java-comprehensive-behavioral-monitoring/
Explains behavioral monitoring of Java processes to detect anomalies and improve runtime security through continuous observation and analysis.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper