Runtime Application Self-Protection (RASP) in Java

Overview

Runtime Application Self-Protection (RASP) is a security technology that runs on a server and detects attacks in real-time by analyzing application behavior and context. RASP provides deep security instrumentation within the application runtime environment.

Architecture Components

1. Core RASP Engine

@Component
public class RaspEngine {
private final SecurityPolicyManager policyManager;
private final ThreatDetectionEngine threatDetector;
private final ResponseOrchestrator responseOrchestrator;
private final EventCollector eventCollector;
private final RaspConfiguration config;
private final Map<HookType, List<SecurityHook>> hooks;
private volatile boolean enabled = true;
public RaspEngine(SecurityPolicyManager policyManager,
ThreatDetectionEngine threatDetector,
ResponseOrchestrator responseOrchestrator,
EventCollector eventCollector,
RaspConfiguration config) {
this.policyManager = policyManager;
this.threatDetector = threatDetector;
this.responseOrchestrator = responseOrchestrator;
this.eventCollector = eventCollector;
this.config = config;
this.hooks = new ConcurrentHashMap<>();
initializeHooks();
startMonitoring();
}
private void initializeHooks() {
// Initialize security hooks for different instrumentation points
registerHook(HookType.HTTP_REQUEST, new HttpRequestHook(this));
registerHook(HookType.SQL_QUERY, new SqlQueryHook(this));
registerHook(HookType.FILE_OPERATION, new FileOperationHook(this));
registerHook(HookType.REFLECTION, new ReflectionHook(this));
registerHook(HookType.SERIALIZATION, new SerializationHook(this));
registerHook(HookType.JNDI_LOOKUP, new JndiLookupHook(this));
registerHook(HookType.EXECUTION, new ExecutionHook(this));
}
public SecurityAssessment assessRequest(RaspContext context) {
if (!enabled) {
return SecurityAssessment.allowed();
}
try {
// Collect baseline metrics
collectBaselineMetrics(context);
// Apply security policies
PolicyEvaluationResult policyResult = policyManager.evaluatePolicies(context);
// Perform threat detection
ThreatDetectionResult threatResult = threatDetector.analyzeBehavior(context);
// Combine results
SecurityAssessment assessment = combineResults(policyResult, threatResult);
// Record assessment
eventCollector.recordAssessment(context, assessment);
return assessment;
} catch (Exception e) {
// Fail open - allow request but log error
eventCollector.recordError(context, e);
return SecurityAssessment.allowed();
}
}
public void handleSecurityEvent(SecurityEvent event) {
if (!enabled) {
return;
}
try {
// Analyze event for threats
ThreatDetectionResult result = threatDetector.analyzeEvent(event);
if (result.isMalicious()) {
// Trigger response actions
responseOrchestrator.orchestrateResponse(event, result);
// Record security incident
eventCollector.recordIncident(event, result);
}
} catch (Exception e) {
eventCollector.recordError(event.getContext(), e);
}
}
public void registerHook(HookType type, SecurityHook hook) {
hooks.computeIfAbsent(type, k -> new CopyOnWriteArrayList<>()).add(hook);
}
public List<SecurityHook> getHooks(HookType type) {
return hooks.getOrDefault(type, Collections.emptyList());
}
public void enable() {
this.enabled = true;
eventCollector.recordEngineEvent(EngineEvent.ENGINE_ENABLED);
}
public void disable() {
this.enabled = false;
eventCollector.recordEngineEvent(EngineEvent.ENGINE_DISABLED);
}
public boolean isEnabled() {
return enabled;
}
public RaspStatus getStatus() {
return new RaspStatus(
enabled,
hooks.values().stream().mapToInt(List::size).sum(),
eventCollector.getStats(),
threatDetector.getDetectionStats()
);
}
private void collectBaselineMetrics(RaspContext context) {
// Collect application-specific baseline metrics
BaselineMetrics metrics = new BaselineMetrics(
System.currentTimeMillis(),
Runtime.getRuntime().freeMemory(),
Thread.activeCount()
);
context.setBaselineMetrics(metrics);
}
private SecurityAssessment combineResults(PolicyEvaluationResult policyResult,
ThreatDetectionResult threatResult) {
SecurityAssessment assessment = new SecurityAssessment();
// Combine policy violations and threat detections
assessment.setAllowed(!policyResult.isBlocked() && !threatResult.isMalicious());
assessment.setPolicyViolations(policyResult.getViolations());
assessment.setThreatIndicators(threatResult.getIndicators());
assessment.setConfidenceScore(calculateConfidence(policyResult, threatResult));
assessment.setRecommendedActions(generateRecommendedActions(policyResult, threatResult));
return assessment;
}
private double calculateConfidence(PolicyEvaluationResult policyResult,
ThreatDetectionResult threatResult) {
double policyConfidence = policyResult.getConfidence();
double threatConfidence = threatResult.getConfidence();
// Weight threat detection higher for malicious behavior
return threatResult.isMalicious() ? 
Math.max(threatConfidence, policyConfidence) :
(policyConfidence + threatConfidence) / 2;
}
private List<SecurityAction> generateRecommendedActions(PolicyEvaluationResult policyResult,
ThreatDetectionResult threatResult) {
List<SecurityAction> actions = new ArrayList<>();
if (policyResult.isBlocked()) {
actions.add(SecurityAction.BLOCK_REQUEST);
}
if (threatResult.isMalicious()) {
actions.add(SecurityAction.BLOCK_REQUEST);
actions.add(SecurityAction.LOG_INCIDENT);
if (threatResult.getSeverity() == ThreatSeverity.CRITICAL) {
actions.add(SecurityAction.ALERT_SECURITY_TEAM);
}
}
return actions;
}
private void startMonitoring() {
// Start background monitoring tasks
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(this::performHealthCheck, 1, 1, TimeUnit.MINUTES);
}
private void performHealthCheck() {
try {
// Verify all components are functioning
policyManager.healthCheck();
threatDetector.healthCheck();
responseOrchestrator.healthCheck();
eventCollector.healthCheck();
eventCollector.recordEngineEvent(EngineEvent.HEALTH_CHECK_PASSED);
} catch (Exception e) {
eventCollector.recordEngineEvent(EngineEvent.HEALTH_CHECK_FAILED);
}
}
}

2. RASP Data Models

// Core RASP Models
public class RaspContext {
private final String requestId;
private final Instant timestamp;
private final String sessionId;
private final String userId;
private final String sourceIp;
private final Map<String, String> headers;
private final Map<String, Object> parameters;
private final String requestPath;
private final String httpMethod;
private final String userAgent;
private final Map<String, Object> attributes;
private BaselineMetrics baselineMetrics;
public RaspContext(String requestId, String sourceIp, String requestPath, String httpMethod) {
this.requestId = requestId;
this.timestamp = Instant.now();
this.sourceIp = sourceIp;
this.requestPath = requestPath;
this.httpMethod = httpMethod;
this.headers = new HashMap<>();
this.parameters = new HashMap<>();
this.attributes = new HashMap<>();
}
// Builder methods
public RaspContext withSessionId(String sessionId) {
this.sessionId = sessionId;
return this;
}
public RaspContext withUserId(String userId) {
this.userId = userId;
return this;
}
public RaspContext withHeaders(Map<String, String> headers) {
this.headers.putAll(headers);
return this;
}
public RaspContext withParameters(Map<String, Object> parameters) {
this.parameters.putAll(parameters);
return this;
}
public RaspContext withUserAgent(String userAgent) {
this.userAgent = userAgent;
return this;
}
public RaspContext withAttribute(String key, Object value) {
this.attributes.put(key, value);
return this;
}
// Getters
public String getRequestId() { return requestId; }
public Instant getTimestamp() { return timestamp; }
public String getSessionId() { return sessionId; }
public String getUserId() { return userId; }
public String getSourceIp() { return sourceIp; }
public Map<String, String> getHeaders() { return Collections.unmodifiableMap(headers); }
public Map<String, Object> getParameters() { return Collections.unmodifiableMap(parameters); }
public String getRequestPath() { return requestPath; }
public String getHttpMethod() { return httpMethod; }
public String getUserAgent() { return userAgent; }
public Map<String, Object> getAttributes() { return Collections.unmodifiableMap(attributes); }
public BaselineMetrics getBaselineMetrics() { return baselineMetrics; }
public void setBaselineMetrics(BaselineMetrics baselineMetrics) { 
this.baselineMetrics = baselineMetrics; 
}
}
public class SecurityAssessment {
private boolean allowed;
private double confidenceScore;
private List<PolicyViolation> policyViolations;
private List<ThreatIndicator> threatIndicators;
private List<SecurityAction> recommendedActions;
private String assessmentId;
private Instant assessedAt;
public SecurityAssessment() {
this.allowed = true;
this.confidenceScore = 1.0;
this.policyViolations = new ArrayList<>();
this.threatIndicators = new ArrayList<>();
this.recommendedActions = new ArrayList<>();
this.assessmentId = UUID.randomUUID().toString();
this.assessedAt = Instant.now();
}
public static SecurityAssessment allowed() {
return new SecurityAssessment();
}
public static SecurityAssessment blocked(String reason) {
SecurityAssessment assessment = new SecurityAssessment();
assessment.setAllowed(false);
assessment.getPolicyViolations().add(new PolicyViolation("BLOCKED", reason));
return assessment;
}
// Getters and setters
}
public class PolicyViolation {
private final String ruleId;
private final String description;
private final ViolationSeverity severity;
private final Map<String, Object> context;
public PolicyViolation(String ruleId, String description) {
this(ruleId, description, ViolationSeverity.MEDIUM, new HashMap<>());
}
public PolicyViolation(String ruleId, String description, ViolationSeverity severity,
Map<String, Object> context) {
this.ruleId = ruleId;
this.description = description;
this.severity = severity;
this.context = new HashMap<>(context);
}
// Getters
}
public class ThreatIndicator {
private final String type;
private final String description;
private final double confidence;
private final Map<String, Object> evidence;
public ThreatIndicator(String type, String description, double confidence) {
this(type, description, confidence, new HashMap<>());
}
public ThreatIndicator(String type, String description, double confidence,
Map<String, Object> evidence) {
this.type = type;
this.description = description;
this.confidence = confidence;
this.evidence = new HashMap<>(evidence);
}
// Getters
}
public enum SecurityAction {
ALLOW_REQUEST,
BLOCK_REQUEST,
LOG_INCIDENT,
ALERT_SECURITY_TEAM,
THROTTLE_REQUEST,
CHALLENGE_USER,
TERMINATE_SESSION
}
public enum ViolationSeverity {
LOW,
MEDIUM,
HIGH,
CRITICAL
}
public enum ThreatSeverity {
LOW,
MEDIUM,
HIGH,
CRITICAL
}
// Event Models
public class SecurityEvent {
private final String eventId;
private final EventType eventType;
private final RaspContext context;
private final Map<String, Object> data;
private final Instant timestamp;
public SecurityEvent(EventType eventType, RaspContext context, Map<String, Object> data) {
this.eventId = UUID.randomUUID().toString();
this.eventType = eventType;
this.context = context;
this.data = new HashMap<>(data);
this.timestamp = Instant.now();
}
// Getters
}
public enum EventType {
HTTP_REQUEST,
SQL_QUERY,
FILE_ACCESS,
REFLECTION_OPERATION,
SERIALIZATION_OPERATION,
JNDI_LOOKUP,
EXECUTION_OPERATION,
MEMORY_ACCESS,
NETWORK_OPERATION
}
// Status and Configuration Models
public class RaspStatus {
private final boolean enabled;
private final int activeHooks;
private final EventCollectorStats eventStats;
private final DetectionStats detectionStats;
private final Instant reportedAt;
public RaspStatus(boolean enabled, int activeHooks, EventCollectorStats eventStats,
DetectionStats detectionStats) {
this.enabled = enabled;
this.activeHooks = activeHooks;
this.eventStats = eventStats;
this.detectionStats = detectionStats;
this.reportedAt = Instant.now();
}
// Getters
}
public class BaselineMetrics {
private final long timestamp;
private final long freeMemory;
private final int activeThreads;
private final double systemLoad;
public BaselineMetrics(long timestamp, long freeMemory, int activeThreads) {
this.timestamp = timestamp;
this.freeMemory = freeMemory;
this.activeThreads = activeThreads;
this.systemLoad = ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage();
}
// Getters
}
public enum EngineEvent {
ENGINE_ENABLED,
ENGINE_DISABLED,
HEALTH_CHECK_PASSED,
HEALTH_CHECK_FAILED,
POLICY_UPDATED,
THREAT_SIGNATURE_UPDATED
}
public enum HookType {
HTTP_REQUEST,
SQL_QUERY,
FILE_OPERATION,
REFLECTION,
SERIALIZATION,
JNDI_LOOKUP,
EXECUTION,
MEMORY_ACCESS,
NETWORK
}

Security Hooks Implementation

1. HTTP Request Hook

public class HttpRequestHook implements SecurityHook {
private final RaspEngine raspEngine;
private final List<HttpSecurityRule> rules;
public HttpRequestHook(RaspEngine raspEngine) {
this.raspEngine = raspEngine;
this.rules = initializeHttpRules();
}
@Override
public HookType getType() {
return HookType.HTTP_REQUEST;
}
public SecurityAssessment interceptRequest(HttpServletRequest request, 
HttpServletResponse response) {
RaspContext context = createContextFromRequest(request);
// Perform security assessment
SecurityAssessment assessment = raspEngine.assessRequest(context);
if (!assessment.isAllowed()) {
handleBlockedRequest(request, response, assessment);
}
// Record security event
SecurityEvent event = createSecurityEvent(context, assessment);
raspEngine.handleSecurityEvent(event);
return assessment;
}
public void interceptResponse(HttpServletRequest request, HttpServletResponse response, 
Object handler, ModelAndView modelAndView) {
RaspContext context = createContextFromRequest(request);
// Analyze response for sensitive data exposure
analyzeResponse(context, response, modelAndView);
// Record response event
SecurityEvent event = createResponseEvent(context, response);
raspEngine.handleSecurityEvent(event);
}
private RaspContext createContextFromRequest(HttpServletRequest request) {
String requestId = (String) request.getAttribute("X-Request-ID");
if (requestId == null) {
requestId = UUID.randomUUID().toString();
request.setAttribute("X-Request-ID", requestId);
}
RaspContext context = new RaspContext(
requestId,
getClientIp(request),
request.getRequestURI(),
request.getMethod()
);
// Extract headers
Map<String, String> headers = new HashMap<>();
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
headers.put(headerName, request.getHeader(headerName));
}
// Extract parameters
Map<String, Object> parameters = new HashMap<>();
Enumeration<String> paramNames = request.getParameterNames();
while (paramNames.hasMoreElements()) {
String paramName = paramNames.nextElement();
parameters.put(paramName, request.getParameter(paramName));
}
return context
.withHeaders(headers)
.withParameters(parameters)
.withUserAgent(request.getHeader("User-Agent"))
.withSessionId(request.getSession(false) != null ? 
request.getSession().getId() : null)
.withAttribute("contentType", request.getContentType())
.withAttribute("contentLength", request.getContentLength());
}
private String getClientIp(HttpServletRequest request) {
String xForwardedFor = request.getHeader("X-Forwarded-For");
if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
return xForwardedFor.split(",")[0].trim();
}
return request.getRemoteAddr();
}
private void handleBlockedRequest(HttpServletRequest request, HttpServletResponse response,
SecurityAssessment assessment) {
try {
// Set response status
response.setStatus(HttpStatus.FORBIDDEN.value());
// Add security headers
response.setHeader("X-Security-Blocked", "true");
response.setHeader("X-Security-Reason", 
assessment.getPolicyViolations().stream()
.map(PolicyViolation::getDescription)
.collect(Collectors.joining("; ")));
// Write response body
response.getWriter().write(createBlockedResponse(assessment));
response.getWriter().flush();
} catch (IOException e) {
// Log error but don't throw to avoid breaking the application
System.err.println("Failed to write blocked response: " + e.getMessage());
}
}
private String createBlockedResponse(SecurityAssessment assessment) {
Map<String, Object> response = new HashMap<>();
response.put("error", "Request blocked by security policy");
response.put("requestId", assessment.getAssessmentId());
response.put("violations", assessment.getPolicyViolations());
response.put("timestamp", Instant.now().toString());
try {
return new ObjectMapper().writeValueAsString(response);
} catch (JsonProcessingException e) {
return "{\"error\": \"Request blocked by security policy\"}";
}
}
private SecurityEvent createSecurityEvent(RaspContext context, SecurityAssessment assessment) {
Map<String, Object> eventData = new HashMap<>();
eventData.put("assessment", assessment);
eventData.put("httpMethod", context.getHttpMethod());
eventData.put("requestPath", context.getRequestPath());
return new SecurityEvent(EventType.HTTP_REQUEST, context, eventData);
}
private SecurityEvent createResponseEvent(RaspContext context, HttpServletResponse response) {
Map<String, Object> eventData = new HashMap<>();
eventData.put("statusCode", response.getStatus());
eventData.put("contentType", response.getContentType());
eventData.put("headers", extractResponseHeaders(response));
return new SecurityEvent(EventType.HTTP_REQUEST, context, eventData);
}
private Map<String, String> extractResponseHeaders(HttpServletResponse response) {
Map<String, String> headers = new HashMap<>();
Collection<String> headerNames = response.getHeaderNames();
for (String headerName : headerNames) {
headers.put(headerName, response.getHeader(headerName));
}
return headers;
}
private void analyzeResponse(RaspContext context, HttpServletResponse response, 
ModelAndView modelAndView) {
// Check for sensitive data in response
checkForSensitiveData(context, response, modelAndView);
// Verify security headers
verifySecurityHeaders(response);
}
private void checkForSensitiveData(RaspContext context, HttpServletResponse response,
ModelAndView modelAndView) {
// Implementation to check for sensitive data exposure
// This could involve checking response content, headers, etc.
}
private void verifySecurityHeaders(HttpServletResponse response) {
// Verify security headers are present
String[] requiredHeaders = {
"X-Content-Type-Options",
"X-Frame-Options", 
"X-XSS-Protection",
"Strict-Transport-Security"
};
for (String header : requiredHeaders) {
if (response.getHeader(header) == null) {
// Log missing security header
System.err.println("Missing security header: " + header);
}
}
}
private List<HttpSecurityRule> initializeHttpRules() {
List<HttpSecurityRule> rules = new ArrayList<>();
// SQL Injection detection
rules.add(new SqlInjectionRule());
// XSS detection
rules.add(new XssDetectionRule());
// Path traversal detection
rules.add(new PathTraversalRule());
// SSRF detection
rules.add(new SsrfDetectionRule());
// Command injection detection
rules.add(new CommandInjectionRule());
return rules;
}
}
// HTTP Security Rules
public interface HttpSecurityRule {
PolicyViolation checkRequest(RaspContext context);
String getRuleId();
ViolationSeverity getSeverity();
}
public class SqlInjectionRule implements HttpSecurityRule {
private final Pattern[] sqlInjectionPatterns = {
Pattern.compile("(?i)(\\b(union|select|insert|update|delete|drop|alter)\\b.*\\b(union|select|insert|update|delete|drop|alter)\\b)"),
Pattern.compile("(?i)(\\b(union|select)\\b.*\\b(from|where)\\b)"),
Pattern.compile("([';]+\\s*(or|and)\\s*[';]+)"),
Pattern.compile("(\\b(exec|execute|xp_cmdshell)\\b)"),
Pattern.compile("(\\b(script|javascript|vbscript|expression)\\b)", Pattern.CASE_INSENSITIVE)
};
@Override
public PolicyViolation checkRequest(RaspContext context) {
// Check parameters for SQL injection patterns
for (Map.Entry<String, Object> entry : context.getParameters().entrySet()) {
String paramValue = String.valueOf(entry.getValue());
for (Pattern pattern : sqlInjectionPatterns) {
if (pattern.matcher(paramValue).find()) {
return new PolicyViolation(
getRuleId(),
"Potential SQL injection detected in parameter: " + entry.getKey(),
getSeverity(),
Map.of("parameter", entry.getKey(), "pattern", pattern.pattern())
);
}
}
}
// Check headers
for (Map.Entry<String, String> entry : context.getHeaders().entrySet()) {
String headerValue = entry.getValue();
for (Pattern pattern : sqlInjectionPatterns) {
if (pattern.matcher(headerValue).find()) {
return new PolicyViolation(
getRuleId(),
"Potential SQL injection detected in header: " + entry.getKey(),
getSeverity(),
Map.of("header", entry.getKey(), "pattern", pattern.pattern())
);
}
}
}
return null;
}
@Override
public String getRuleId() {
return "SQL_INJECTION_DETECTION";
}
@Override
public ViolationSeverity getSeverity() {
return ViolationSeverity.HIGH;
}
}
public class XssDetectionRule implements HttpSecurityRule {
private final Pattern[] xssPatterns = {
Pattern.compile("<script[^>]*>.*?</script>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL),
Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE),
Pattern.compile("on\\w+\\s*=", Pattern.CASE_INSENSITIVE),
Pattern.compile("expression\\s*\\(", Pattern.CASE_INSENSITIVE),
Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE)
};
@Override
public PolicyViolation checkRequest(RaspContext context) {
// Implementation similar to SqlInjectionRule
return null; // Simplified
}
@Override
public String getRuleId() {
return "XSS_DETECTION";
}
@Override
public ViolationSeverity getSeverity() {
return ViolationSeverity.HIGH;
}
}
// Additional rule implementations...

2. SQL Query Hook

public class SqlQueryHook implements SecurityHook {
private final RaspEngine raspEngine;
private final SqlInjectionDetector sqlDetector;
private final SensitiveDataDetector dataDetector;
public SqlQueryHook(RaspEngine raspEngine) {
this.raspEngine = raspEngine;
this.sqlDetector = new SqlInjectionDetector();
this.dataDetector = new SensitiveDataDetector();
}
@Override
public HookType getType() {
return HookType.SQL_QUERY;
}
public SecurityAssessment interceptQuery(String sql, Object[] parameters, 
String dataSource, RaspContext context) {
SecurityAssessment assessment = new SecurityAssessment();
// Check for SQL injection
SqlInjectionResult injectionResult = sqlDetector.detectInjection(sql, parameters);
if (injectionResult.isMalicious()) {
assessment.setAllowed(false);
assessment.getThreatIndicators().addAll(injectionResult.getIndicators());
}
// Check for sensitive data access
SensitiveDataResult dataResult = dataDetector.analyzeQuery(sql, context);
if (dataResult.hasSensitiveAccess()) {
assessment.getThreatIndicators().addAll(dataResult.getIndicators());
}
// Record SQL query event
SecurityEvent event = createSqlEvent(context, sql, parameters, dataSource, assessment);
raspEngine.handleSecurityEvent(event);
return assessment;
}
public void interceptResult(String sql, ResultSet resultSet, RaspContext context) {
// Analyze query results for sensitive data exposure
analyzeResults(sql, resultSet, context);
// Record result event
SecurityEvent event = createResultEvent(context, sql, resultSet);
raspEngine.handleSecurityEvent(event);
}
private SecurityEvent createSqlEvent(RaspContext context, String sql, Object[] parameters,
String dataSource, SecurityAssessment assessment) {
Map<String, Object> eventData = new HashMap<>();
eventData.put("sql", sql);
eventData.put("parameters", parameters != null ? Arrays.asList(parameters) : Collections.emptyList());
eventData.put("dataSource", dataSource);
eventData.put("assessment", assessment);
return new SecurityEvent(EventType.SQL_QUERY, context, eventData);
}
private SecurityEvent createResultEvent(RaspContext context, String sql, ResultSet resultSet) {
Map<String, Object> eventData = new HashMap<>();
eventData.put("sql", sql);
eventData.put("resultSize", getResultSetSize(resultSet));
eventData.put("sensitiveColumns", detectSensitiveColumns(resultSet));
return new SecurityEvent(EventType.SQL_QUERY, context, eventData);
}
private void analyzeResults(String sql, ResultSet resultSet, RaspContext context) {
try {
// Check if sensitive data is being returned
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
List<String> sensitiveColumns = new ArrayList<>();
for (int i = 1; i <= columnCount; i++) {
String columnName = metaData.getColumnName(i);
if (isSensitiveColumn(columnName)) {
sensitiveColumns.add(columnName);
}
}
if (!sensitiveColumns.isEmpty()) {
// Log sensitive data access
ThreatIndicator indicator = new ThreatIndicator(
"SENSITIVE_DATA_ACCESS",
"Query returned sensitive columns: " + String.join(", ", sensitiveColumns),
0.8,
Map.of("columns", sensitiveColumns, "sql", sql)
);
SecurityEvent event = new SecurityEvent(EventType.SQL_QUERY, context, 
Map.of("sensitiveColumns", sensitiveColumns, "sql", sql));
raspEngine.handleSecurityEvent(event);
}
} catch (SQLException e) {
// Log error but don't throw
System.err.println("Failed to analyze SQL results: " + e.getMessage());
}
}
private int getResultSetSize(ResultSet resultSet) {
try {
int size = 0;
if (resultSet != null) {
resultSet.last();
size = resultSet.getRow();
resultSet.beforeFirst();
}
return size;
} catch (SQLException e) {
return -1;
}
}
private List<String> detectSensitiveColumns(ResultSet resultSet) {
List<String> sensitiveColumns = new ArrayList<>();
try {
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
String columnName = metaData.getColumnName(i);
if (isSensitiveColumn(columnName)) {
sensitiveColumns.add(columnName);
}
}
} catch (SQLException e) {
// Ignore
}
return sensitiveColumns;
}
private boolean isSensitiveColumn(String columnName) {
String[] sensitivePatterns = {
"password", "passwd", "pwd", "secret", "token", "key", 
"credit", "card", "ssn", "social", "birth", "address"
};
String lowerColumn = columnName.toLowerCase();
return Arrays.stream(sensitivePatterns)
.anyMatch(pattern -> lowerColumn.contains(pattern));
}
}
// SQL Detection Components
public class SqlInjectionDetector {
private final Pattern[] sqlPatterns = {
Pattern.compile("'.*--"),
Pattern.compile("'.*;"),
Pattern.compile("union.*select", Pattern.CASE_INSENSITIVE),
Pattern.compile("insert.*into", Pattern.CASE_INSENSITIVE),
Pattern.compile("drop.*table", Pattern.CASE_INSENSITIVE),
Pattern.compile("exec\\s*\\(", Pattern.CASE_INSENSITIVE)
};
public SqlInjectionResult detectInjection(String sql, Object[] parameters) {
SqlInjectionResult result = new SqlInjectionResult();
// Check SQL string
for (Pattern pattern : sqlPatterns) {
if (pattern.matcher(sql).find()) {
result.addIndicator(new ThreatIndicator(
"SQL_INJECTION_PATTERN",
"SQL injection pattern detected: " + pattern.pattern(),
0.9,
Map.of("pattern", pattern.pattern(), "sql", sql)
));
}
}
// Check parameters
if (parameters != null) {
for (int i = 0; i < parameters.length; i++) {
Object param = parameters[i];
if (param instanceof String) {
String paramValue = (String) param;
for (Pattern pattern : sqlPatterns) {
if (pattern.matcher(paramValue).find()) {
result.addIndicator(new ThreatIndicator(
"SQL_INJECTION_PARAMETER",
"SQL injection in parameter " + i + ": " + pattern.pattern(),
0.8,
Map.of("parameterIndex", i, "pattern", pattern.pattern())
));
}
}
}
}
}
return result;
}
}
public class SqlInjectionResult {
private final List<ThreatIndicator> indicators;
private boolean malicious;
public SqlInjectionResult() {
this.indicators = new ArrayList<>();
this.malicious = false;
}
public void addIndicator(ThreatIndicator indicator) {
indicators.add(indicator);
malicious = true;
}
// Getters
public boolean isMalicious() { return malicious; }
public List<ThreatIndicator> getIndicators() { return indicators; }
}
public class SensitiveDataDetector {
private final Pattern[] sensitiveTablePatterns = {
Pattern.compile("(?i).*user.*"),
Pattern.compile("(?i).*customer.*"),
Pattern.compile("(?i).*account.*"),
Pattern.compile("(?i).*password.*"),
Pattern.compile("(?i).*credit.*card.*"),
Pattern.compile("(?i).*social.*security.*")
};
public SensitiveDataResult analyzeQuery(String sql, RaspContext context) {
SensitiveDataResult result = new SensitiveDataResult();
// Check for sensitive table access
for (Pattern pattern : sensitiveTablePatterns) {
if (pattern.matcher(sql).find()) {
result.addIndicator(new ThreatIndicator(
"SENSITIVE_TABLE_ACCESS",
"Query accesses sensitive table: " + pattern.pattern(),
0.6,
Map.of("pattern", pattern.pattern(), "sql", sql)
));
}
}
// Check for excessive data retrieval
if (isExcessiveDataQuery(sql)) {
result.addIndicator(new ThreatIndicator(
"EXCESSIVE_DATA_RETRIEVAL",
"Query may retrieve excessive data",
0.5,
Map.of("sql", sql)
));
}
return result;
}
private boolean isExcessiveDataQuery(String sql) {
String lowerSql = sql.toLowerCase();
return !lowerSql.contains("limit") && 
!lowerSql.contains("where") && 
!lowerSql.contains("top") &&
lowerSql.contains("select") &&
lowerSql.contains("from");
}
}
public class SensitiveDataResult {
private final List<ThreatIndicator> indicators;
public SensitiveDataResult() {
this.indicators = new ArrayList<>();
}
public void addIndicator(ThreatIndicator indicator) {
indicators.add(indicator);
}
public boolean hasSensitiveAccess() {
return !indicators.isEmpty();
}
// Getters
public List<ThreatIndicator> getIndicators() { return indicators; }
}

Threat Detection Engine

1. Behavioral Analysis Engine

@Component
public class ThreatDetectionEngine {
private final List<ThreatDetector> detectors;
private final AnomalyDetectionEngine anomalyDetector;
private final MachineLearningEngine mlEngine;
private final ThreatIntelligenceService threatIntel;
private final Map<String, DetectionStats> detectionStats;
public ThreatDetectionEngine(AnomalyDetectionEngine anomalyDetector,
MachineLearningEngine mlEngine,
ThreatIntelligenceService threatIntel) {
this.anomalyDetector = anomalyDetector;
this.mlEngine = mlEngine;
this.threatIntel = threatIntel;
this.detectors = initializeDetectors();
this.detectionStats = new ConcurrentHashMap<>();
}
public ThreatDetectionResult analyzeBehavior(RaspContext context) {
ThreatDetectionResult result = new ThreatDetectionResult();
// Run all detectors
for (ThreatDetector detector : detectors) {
ThreatDetectionResult detectorResult = detector.detect(context);
result.merge(detectorResult);
}
// Perform anomaly detection
AnomalyDetectionResult anomalyResult = anomalyDetector.detectAnomalies(context);
result.merge(anomalyResult);
// Apply machine learning
MLDetectionResult mlResult = mlEngine.analyze(context);
result.merge(mlResult);
// Check threat intelligence
ThreatIntelResult intelResult = threatIntel.checkContext(context);
result.merge(intelResult);
// Update statistics
updateDetectionStats(result);
return result;
}
public ThreatDetectionResult analyzeEvent(SecurityEvent event) {
ThreatDetectionResult result = new ThreatDetectionResult();
// Analyze event using specialized detectors
switch (event.getEventType()) {
case SQL_QUERY:
result.merge(analyzeSqlEvent(event));
break;
case FILE_ACCESS:
result.merge(analyzeFileEvent(event));
break;
case EXECUTION_OPERATION:
result.merge(analyzeExecutionEvent(event));
break;
default:
result.merge(analyzeGenericEvent(event));
}
return result;
}
public void trainModel(List<SecurityEvent> trainingData) {
mlEngine.train(trainingData);
}
public DetectionStats getDetectionStats() {
DetectionStats overall = new DetectionStats();
detectionStats.values().forEach(overall::combine);
return overall;
}
public void healthCheck() {
// Verify all detectors are functioning
for (ThreatDetector detector : detectors) {
detector.healthCheck();
}
anomalyDetector.healthCheck();
mlEngine.healthCheck();
threatIntel.healthCheck();
}
private List<ThreatDetector> initializeDetectors() {
List<ThreatDetector> detectors = new ArrayList<>();
detectors.add(new RateLimitDetector());
detectors.add(new ResourceUsageDetector());
detectors.add(new BehavioralPatternDetector());
detectors.add(new SessionAnomalyDetector());
detectors.add(new InputValidationDetector());
return detectors;
}
private ThreatDetectionResult analyzeSqlEvent(SecurityEvent event) {
ThreatDetectionResult result = new ThreatDetectionResult();
// Analyze SQL event for suspicious patterns
String sql = (String) event.getData().get("sql");
if (sql != null) {
// Check for unusual SQL patterns
if (isUnusualSqlPattern(sql)) {
result.addIndicator(new ThreatIndicator(
"UNUSUAL_SQL_PATTERN",
"Unusual SQL pattern detected",
0.7,
Map.of("sql", sql)
));
}
// Check for data exfiltration patterns
if (isDataExfiltrationSql(sql)) {
result.addIndicator(new ThreatIndicator(
"DATA_EXFILTRATION_SQL",
"Potential data exfiltration SQL detected",
0.8,
Map.of("sql", sql)
));
}
}
return result;
}
private ThreatDetectionResult analyzeFileEvent(SecurityEvent event) {
ThreatDetectionResult result = new ThreatDetectionResult();
// Analyze file access patterns
String filePath = (String) event.getData().get("filePath");
if (filePath != null) {
// Check for sensitive file access
if (isSensitiveFile(filePath)) {
result.addIndicator(new ThreatIndicator(
"SENSITIVE_FILE_ACCESS",
"Access to sensitive file detected",
0.9,
Map.of("filePath", filePath)
));
}
// Check for path traversal
if (isPathTraversal(filePath)) {
result.addIndicator(new ThreatIndicator(
"PATH_TRAVERSAL",
"Path traversal attempt detected",
0.95,
Map.of("filePath", filePath)
));
}
}
return result;
}
private ThreatDetectionResult analyzeExecutionEvent(SecurityEvent event) {
ThreatDetectionResult result = new ThreatDetectionResult();
// Analyze execution operations
String command = (String) event.getData().get("command");
if (command != null) {
// Check for command injection patterns
if (isSuspiciousCommand(command)) {
result.addIndicator(new ThreatIndicator(
"SUSPICIOUS_COMMAND",
"Suspicious command execution detected",
0.85,
Map.of("command", command)
));
}
}
return result;
}
private ThreatDetectionResult analyzeGenericEvent(SecurityEvent event) {
// Generic event analysis
return new ThreatDetectionResult();
}
private boolean isUnusualSqlPattern(String sql) {
// Implementation to detect unusual SQL patterns
return sql.toLowerCase().contains("union") && 
sql.toLowerCase().contains("select") &&
sql.split("select").length > 2;
}
private boolean isDataExfiltrationSql(String sql) {
// Implementation to detect data exfiltration patterns
return sql.toLowerCase().contains("select * from") &&
!sql.toLowerCase().contains("where") &&
!sql.toLowerCase().contains("limit");
}
private boolean isSensitiveFile(String filePath) {
String[] sensitivePaths = {
"/etc/passwd", "/etc/shadow", "/etc/hosts", 
"/proc/", "/sys/", "/boot/", "/root/"
};
for (String sensitivePath : sensitivePaths) {
if (filePath.contains(sensitivePath)) {
return true;
}
}
return false;
}
private boolean isPathTraversal(String filePath) {
return filePath.contains("../") || 
filePath.contains("..\\") ||
filePath.contains("%2e%2e") ||
filePath.contains("..%2f");
}
private boolean isSuspiciousCommand(String command) {
String[] suspiciousPatterns = {
"rm -rf", "format", "del ", "erase", "shutdown", 
"reboot", "kill", "chmod 777", "wget", "curl"
};
for (String pattern : suspiciousPatterns) {
if (command.toLowerCase().contains(pattern)) {
return true;
}
}
return false;
}
private void updateDetectionStats(ThreatDetectionResult result) {
String detectorType = result.getSource();
DetectionStats stats = detectionStats.computeIfAbsent(
detectorType, k -> new DetectionStats());
stats.incrementTotalDetections();
if (result.isMalicious()) {
stats.incrementMaliciousDetections();
}
}
}
// Threat Detection Models
public class ThreatDetectionResult {
private final List<ThreatIndicator> indicators;
private double confidence;
private boolean malicious;
private String source;
public ThreatDetectionResult() {
this.indicators = new ArrayList<>();
this.confidence = 0.0;
this.malicious = false;
this.source = "UNKNOWN";
}
public void addIndicator(ThreatIndicator indicator) {
indicators.add(indicator);
updateConfidence();
}
public void merge(ThreatDetectionResult other) {
this.indicators.addAll(other.indicators);
this.confidence = Math.max(this.confidence, other.confidence);
this.malicious = this.malicious || other.malicious;
}
private void updateConfidence() {
if (indicators.isEmpty()) {
confidence = 0.0;
malicious = false;
return;
}
// Calculate average confidence
confidence = indicators.stream()
.mapToDouble(ThreatIndicator::getConfidence)
.average()
.orElse(0.0);
// Consider result malicious if confidence is above threshold
malicious = confidence > 0.7;
}
// Getters and setters
}
public class DetectionStats {
private long totalDetections;
private long maliciousDetections;
private long falsePositives;
private long truePositives;
private Instant lastUpdated;
public DetectionStats() {
this.totalDetections = 0;
this.maliciousDetections = 0;
this.falsePositives = 0;
this.truePositives = 0;
this.lastUpdated = Instant.now();
}
public void incrementTotalDetections() {
totalDetections++;
lastUpdated = Instant.now();
}
public void incrementMaliciousDetections() {
maliciousDetections++;
lastUpdated = Instant.now();
}
public void incrementFalsePositives() {
falsePositives++;
lastUpdated = Instant.now();
}
public void incrementTruePositives() {
truePositives++;
lastUpdated = Instant.now();
}
public void combine(DetectionStats other) {
this.totalDetections += other.totalDetections;
this.maliciousDetections += other.maliciousDetections;
this.falsePositives += other.falsePositives;
this.truePositives += other.truePositives;
}
public double getAccuracy() {
return totalDetections > 0 ? 
(double) truePositives / totalDetections * 100 : 0.0;
}
public double getFalsePositiveRate() {
return totalDetections > 0 ? 
(double) falsePositives / totalDetections * 100 : 0.0;
}
// Getters
}

2. Anomaly Detection Engine

@Component
public class AnomalyDetectionEngine {
private final Map<String, BehavioralProfile> userProfiles;
private final Map<String, ApplicationProfile> appProfiles;
private final StatisticalAnalyzer statisticalAnalyzer;
private final PatternRecognitionEngine patternEngine;
public AnomalyDetectionEngine(StatisticalAnalyzer statisticalAnalyzer,
PatternRecognitionEngine patternEngine) {
this.userProfiles = new ConcurrentHashMap<>();
this.appProfiles = new ConcurrentHashMap<>();
this.statisticalAnalyzer = statisticalAnalyzer;
this.patternEngine = patternEngine;
}
public AnomalyDetectionResult detectAnomalies(RaspContext context) {
AnomalyDetectionResult result = new AnomalyDetectionResult();
// Detect user behavior anomalies
UserAnomalyResult userResult = detectUserAnomalies(context);
result.merge(userResult);
// Detect application behavior anomalies
AppAnomalyResult appResult = detectApplicationAnomalies(context);
result.merge(appResult);
// Detect statistical anomalies
StatisticalAnomalyResult statisticalResult = detectStatisticalAnomalies(context);
result.merge(statisticalResult);
// Detect pattern-based anomalies
PatternAnomalyResult patternResult = detectPatternAnomalies(context);
result.merge(patternResult);
return result;
}
public void updateUserProfile(String userId, UserBehavior behavior) {
BehavioralProfile profile = userProfiles.computeIfAbsent(
userId, k -> new BehavioralProfile(userId));
profile.update(behavior);
}
public void updateApplicationProfile(String endpoint, EndpointBehavior behavior) {
ApplicationProfile profile = appProfiles.computeIfAbsent(
endpoint, k -> new ApplicationProfile(endpoint));
profile.update(behavior);
}
public void trainBaseline(List<RaspContext> historicalData) {
// Train baseline models using historical data
statisticalAnalyzer.trainBaseline(historicalData);
patternEngine.trainPatterns(historicalData);
}
public void healthCheck() {
// Verify anomaly detection components are functioning
statisticalAnalyzer.healthCheck();
patternEngine.healthCheck();
}
private UserAnomalyResult detectUserAnomalies(RaspContext context) {
UserAnomalyResult result = new UserAnomalyResult();
String userId = context.getUserId();
if (userId != null) {
BehavioralProfile profile = userProfiles.get(userId);
if (profile != null) {
// Check for deviations from user's normal behavior
UserBehavior currentBehavior = extractUserBehavior(context);
double anomalyScore = profile.calculateAnomalyScore(currentBehavior);
if (anomalyScore > 0.8) {
result.addIndicator(new ThreatIndicator(
"USER_BEHAVIOR_ANOMALY",
"Unusual user behavior detected",
anomalyScore,
Map.of("userId", userId, "anomalyScore", anomalyScore)
));
}
}
}
return result;
}
private AppAnomalyResult detectApplicationAnomalies(RaspContext context) {
AppAnomalyResult result = new AppAnomalyResult();
String endpoint = context.getRequestPath();
ApplicationProfile profile = appProfiles.get(endpoint);
if (profile != null) {
// Check for deviations from normal endpoint behavior
EndpointBehavior currentBehavior = extractEndpointBehavior(context);
double anomalyScore = profile.calculateAnomalyScore(currentBehavior);
if (anomalyScore > 0.7) {
result.addIndicator(new ThreatIndicator(
"ENDPOINT_BEHAVIOR_ANOMALY",
"Unusual endpoint behavior detected",
anomalyScore,
Map.of("endpoint", endpoint, "anomalyScore", anomalyScore)
));
}
}
return result;
}
private StatisticalAnomalyResult detectStatisticalAnomalies(RaspContext context) {
return statisticalAnalyzer.analyze(context);
}
private PatternAnomalyResult detectPatternAnomalies(RaspContext context) {
return patternEngine.analyzePatterns(context);
}
private UserBehavior extractUserBehavior(RaspContext context) {
return new UserBehavior(
context.getUserId(),
context.getRequestPath(),
context.getHttpMethod(),
context.getTimestamp(),
context.getSourceIp(),
context.getUserAgent()
);
}
private EndpointBehavior extractEndpointBehavior(RaspContext context) {
return new EndpointBehavior(
context.getRequestPath(),
context.getHttpMethod(),
context.getParameters(),
context.getHeaders(),
context.getTimestamp()
);
}
}
// Anomaly Detection Models
public class BehavioralProfile {
private final String userId;
private final Map<String, RequestPattern> requestPatterns;
private final TemporalPattern temporalPattern;
private final GeoPattern geoPattern;
private final DevicePattern devicePattern;
private Instant lastUpdated;
public BehavioralProfile(String userId) {
this.userId = userId;
this.requestPatterns = new HashMap<>();
this.temporalPattern = new TemporalPattern();
this.geoPattern = new GeoPattern();
this.devicePattern = new DevicePattern();
this.lastUpdated = Instant.now();
}
public void update(UserBehavior behavior) {
// Update request patterns
String endpointKey = behavior.getHttpMethod() + ":" + behavior.getEndpoint();
RequestPattern pattern = requestPatterns.computeIfAbsent(
endpointKey, k -> new RequestPattern());
pattern.update(behavior);
// Update temporal patterns
temporalPattern.update(behavior);
// Update geo patterns
geoPattern.update(behavior);
// Update device patterns
devicePattern.update(behavior);
lastUpdated = Instant.now();
}
public double calculateAnomalyScore(UserBehavior currentBehavior) {
double score = 0.0;
int factors = 0;
// Check request pattern anomaly
String endpointKey = currentBehavior.getHttpMethod() + ":" + currentBehavior.getEndpoint();
RequestPattern pattern = requestPatterns.get(endpointKey);
if (pattern != null) {
score += pattern.calculateAnomalyScore(currentBehavior);
factors++;
}
// Check temporal anomaly
score += temporalPattern.calculateAnomalyScore(currentBehavior);
factors++;
// Check geo anomaly
score += geoPattern.calculateAnomalyScore(currentBehavior);
factors++;
// Check device anomaly
score += devicePattern.calculateAnomalyScore(currentBehavior);
factors++;
return factors > 0 ? score / factors : 0.0;
}
// Getters
}
public class UserBehavior {
private final String userId;
private final String endpoint;
private final String httpMethod;
private final Instant timestamp;
private final String sourceIp;
private final String userAgent;
public UserBehavior(String userId, String endpoint, String httpMethod,
Instant timestamp, String sourceIp, String userAgent) {
this.userId = userId;
this.endpoint = endpoint;
this.httpMethod = httpMethod;
this.timestamp = timestamp;
this.sourceIp = sourceIp;
this.userAgent = userAgent;
}
// Getters
}
public class RequestPattern {
private int totalRequests;
private double averageParameters;
private Set<String> commonParameterNames;
private Map<String, Integer> parameterValueFrequencies;
public RequestPattern() {
this.totalRequests = 0;
this.averageParameters = 0.0;
this.commonParameterNames = new HashSet<>();
this.parameterValueFrequencies = new HashMap<>();
}
public void update(UserBehavior behavior) {
totalRequests++;
// Update pattern statistics
}
public double calculateAnomalyScore(UserBehavior behavior) {
// Calculate how anomalous this request is compared to the pattern
return 0.0; // Implementation details
}
}
// Additional pattern classes...

Spring Boot Integration

1. Auto-Configuration

@Configuration
@EnableConfigurationProperties(RaspProperties.class)
public class RaspAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RaspEngine raspEngine(RaspProperties properties) {
SecurityPolicyManager policyManager = new SecurityPolicyManager();
ThreatDetectionEngine threatDetector = createThreatDetectionEngine();
ResponseOrchestrator responseOrchestrator = new ResponseOrchestrator();
EventCollector eventCollector = new EventCollector();
return new RaspEngine(policyManager, threatDetector, 
responseOrchestrator, eventCollector, properties);
}
@Bean
@ConditionalOnMissingBean
public HttpRequestHook httpRequestHook(RaspEngine raspEngine) {
return new HttpRequestHook(raspEngine);
}
@Bean
@ConditionalOnMissingBean
public SqlQueryHook sqlQueryHook(RaspEngine raspEngine) {
return new SqlQueryHook(raspEngine);
}
@Bean
@ConditionalOnMissingBean 
public RaspWebFilter raspWebFilter(HttpRequestHook httpRequestHook) {
return new RaspWebFilter(httpRequestHook);
}
@Bean
public RaspHealthIndicator raspHealthIndicator(RaspEngine raspEngine) {
return new RaspHealthIndicator(raspEngine);
}
private ThreatDetectionEngine createThreatDetectionEngine() {
AnomalyDetectionEngine anomalyDetector = new AnomalyDetectionEngine(
new StatisticalAnalyzer(), new PatternRecognitionEngine());
MachineLearningEngine mlEngine = new MachineLearningEngine();
ThreatIntelligenceService threatIntel = new ThreatIntelligenceService();
return new ThreatDetectionEngine(anomalyDetector, mlEngine, threatIntel);
}
}
@Component
public class RaspHealthIndicator implements HealthIndicator {
private final RaspEngine raspEngine;
public RaspHealthIndicator(RaspEngine raspEngine) {
this.raspEngine = raspEngine;
}
@Override
public Health health() {
RaspStatus status = raspEngine.getStatus();
if (status.isEnabled()) {
return Health.up()
.withDetail("status", "enabled")
.withDetail("activeHooks", status.getActiveHooks())
.withDetail("eventStats", status.getEventStats())
.build();
} else {
return Health.down()
.withDetail("status", "disabled")
.build();
}
}
}
@ConfigurationProperties(prefix = "rasp")
public class RaspProperties {
private boolean enabled = true;
private Mode mode = Mode.MONITOR;
private Blocking blocking = new Blocking();
private Logging logging = new Logging();
private Detection detection = new Detection();
// Getters and setters
public enum Mode {
MONITOR,
PROTECT,
LEARNING
}
public static class Blocking {
private boolean enabled = true;
private int responseCode = 403;
private String responseMessage = "Request blocked by security policy";
// Getters and setters
}
public static class Logging {
private boolean enabled = true;
private Level level = Level.INFO;
private String logFile = "./logs/rasp-security.log";
// Getters and setters
public enum Level {
DEBUG, INFO, WARN, ERROR
}
}
public static class Detection {
private boolean sqlInjection = true;
private boolean xss = true;
private boolean pathTraversal = true;
private boolean commandInjection = true;
private boolean anomalyDetection = true;
private double confidenceThreshold = 0.8;
// Getters and setters
}
}

2. Web Filter Integration

@Component
public class RaspWebFilter implements Filter {
private final HttpRequestHook httpRequestHook;
public RaspWebFilter(HttpRequestHook httpRequestHook) {
this.httpRequestHook = httpRequestHook;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain) throws IOException, ServletException {
if (!(request instanceof HttpServletRequest) || 
!(response instanceof HttpServletResponse)) {
chain.doFilter(request, response);
return;
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// Intercept request for security assessment
SecurityAssessment assessment = httpRequestHook.interceptRequest(httpRequest, httpResponse);
if (assessment.isAllowed()) {
// Create wrapper to intercept response
SecurityResponseWrapper responseWrapper = new SecurityResponseWrapper(httpResponse);
chain.doFilter(request, responseWrapper);
// Intercept response
httpRequestHook.interceptResponse(httpRequest, responseWrapper, null, null);
} else {
// Request was blocked - response already handled by hook
return;
}
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// Initialization logic
}
@Override
public void destroy() {
// Cleanup logic
}
}
public class SecurityResponseWrapper extends HttpServletResponseWrapper {
private final ByteArrayOutputStream capture;
private ServletOutputStream output;
private PrintWriter writer;
public SecurityResponseWrapper(HttpServletResponse response) {
super(response);
capture = new ByteArrayOutputStream(response.getBufferSize());
}
@Override
public ServletOutputStream getOutputStream() {
if (writer != null) {
throw new IllegalStateException("getWriter() has already been called");
}
if (output == null) {
output = new ServletOutputStream() {
@Override
public void write(int b) throws IOException {
capture.write(b);
}
@Override
public void flush() throws IOException {
capture.flush();
}
@Override
public void close() throws IOException {
capture.close();
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setWriteListener(WriteListener listener) {
// Not implemented
}
};
}
return output;
}
@Override
public PrintWriter getWriter() throws IOException {
if (output != null) {
throw new IllegalStateException("getOutputStream() has already been called");
}
if (writer == null) {
writer = new PrintWriter(new OutputStreamWriter(capture, getCharacterEncoding()));
}
return writer;
}
public byte[] getCaptureAsBytes() throws IOException {
if (writer != null) {
writer.close();
} else if (output != null) {
output.close();
}
return capture.toByteArray();
}
public String getCaptureAsString() throws IOException {
return new String(getCaptureAsBytes(), getCharacterEncoding());
}
}

Configuration

1. Application Configuration

rasp:
enabled: true
mode: PROTECT
blocking:
enabled: true
response-code: 403
response-message: "Request blocked by security policy"
logging:
enabled: true
level: INFO
log-file: ./logs/rasp-security.log
detection:
sql-injection: true
xss: true
path-traversal: true
command-injection: true
anomaly-detection: true
confidence-threshold: 0.8
management:
endpoints:
web:
exposure:
include: "health,rasp"
endpoint:
rasp:
enabled: true
logging:
level:
com.example.rasp: DEBUG

Conclusion

Runtime Application Self-Protection (RASP) in Java provides:

  1. Real-time Threat Detection: Monitor application behavior and detect attacks as they happen
  2. Deep Application Context: Understand application-specific context for accurate detection
  3. Automated Response: Block malicious requests and trigger security responses
  4. Behavioral Analysis: Detect anomalies and suspicious patterns using machine learning
  5. Comprehensive Coverage: Protect against OWASP Top 10 vulnerabilities and more

Key benefits:

  • Zero-day Protection: Detect attacks without relying on known signatures
  • Application-Aware Security: Understand application context for accurate detection
  • Real-time Protection: Block attacks as they happen without human intervention
  • Minimal Performance Impact: Optimized instrumentation and detection algorithms
  • Compliance Support: Meet security compliance requirements with detailed logging

This RASP implementation provides enterprise-grade application security that adapts to your specific application behavior and protects against both known and unknown threats.

Leave a Reply

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


Macro Nepal Helper