Soar Security Orchestration
LogZilla documentation for Soar Security Orchestration
SOAR Security Orchestration
Security Orchestration, Automation, and Response (SOAR) capabilities detect sophisticated attack patterns that span multiple events, systems, and time periods. LogZilla's pre-processing extracts security fields, while SEC handles complex correlation logic. SEC generates synthetic events back to LogZilla, where triggers perform intelligent automated responses.
Prerequisites: Ensure Event Correlation is enabled and forwarder reloading is available as shown in the Event Correlation Overview.
Geographic Anomaly Detection
Impossible Travel Detection
Detect when the same user logs in from geographically distant locations within an impossible timeframe.
Required Apps and Configuration
Required Apps:
linux__pam
app (forPAM User Tracking
andPAM Remote Host
user tags)geoip
app (forSrcIP Country
,SrcIP City
,SrcIP State
user tags)
IP Address Mapping Rule
The GeoIP app requires SrcIP
user tags, but PAM creates PAM Remote Host
.
Create a mapping rule:
File: /etc/logzilla/rules/enabled/601-pam-mapping.lua
lua-- Map PAM Remote Host to SrcIP for GeoIP processing
function process(event)
if event.user_tags["PAM Remote Host"] then
event.user_tags["SrcIP"] = event.user_tags["PAM Remote Host"]
end
end
LogZilla Forwarder Configuration
yaml# /etc/logzilla/forwarder.d/geographic-security.yaml
type: sec
sec_name: geographic-security
rules:
- match:
- field: program
op: "eq"
value: ["sshd", "rdp", "vpn", "web_auth"]
- field: message
op: "=~"
value: "(Accepted password|session opened|login successful)"
rewrite:
message: "AUTH_SUCCESS $MESSAGE"
SEC Rule: Impossible Travel Detection
File: /etc/logzilla/sec/geographic-security/rules/impossible-travel.sec
text# Detect impossible travel - same user from different countries within 1 hour type=Single ptype=SubStr pattern=AUTH_SUCCESS desc=Checking for impossible travel action=eval %username $ENV{EVENT_USER_TAGS_PAM_USER_TRACKING}; \ eval %new_country $ENV{EVENT_USER_TAGS_SRCIP_COUNTRY}; \ eval %new_ip $ENV{EVENT_USER_TAGS_SRCIP}; \ eval %old_country (context("USER_LOGIN_%username", "country")); \ eval %old_ip (context("USER_LOGIN_%username", "ip")); \ if ((%new_country ne %old_country) && (%old_country ne "")) { \ shellcmd (logger -t SEC-SECURITY -p local0.alert \ "IMPOSSIBLE_TRAVEL user=\"%username\" old_ip=\"%old_ip\" old_country=\"%old_country\" new_ip=\"%new_ip\" new_country=\"%new_country\""); \ }; \ setcontext USER_LOGIN_%username 3600 (country %new_country, ip %new_ip)
Processing Chain
The complete geographic correlation works through this processing chain:
-
PAM Rule (
600-linux-pam.lua
) extracts authentication data:- Creates
PAM User Tracking
(username) - Creates
PAM Remote Host
(source IP)
- Creates
-
Mapping Rule (
601-pam-mapping.lua
) prepares for GeoIP:- Copies
PAM Remote Host
→SrcIP
- Copies
-
GeoIP Rule (
999-add-geodata.lua
) adds geographic data:- Creates
SrcIP Country
,SrcIP City
,SrcIP State
- Creates
-
Forwarder sends enriched event to SEC with all user tags appended
-
SEC Rule parses user tags from message and detects impossible travel
LogZilla Trigger: Impossible Travel Response
yaml# Trigger responds to SEC-generated impossible travel events
name: "Impossible Travel Incident Response"
filter:
- field: program
op: eq
value: SEC-SECURITY
- field: message
op: "=~"
value: "IMPOSSIBLE_TRAVEL"
actions:
send_email: true
send_email_template: |
Subject: SECURITY ALERT: Impossible Travel Detected
User: {{event:ut:username}}
Locations: {{event:ut:details}}
This indicates potential credential compromise.
exec_script: true
script_path: "/usr/local/bin/impossible-travel-response.sh"
issue_notification: true
Intelligent Response Script
bash#!/bin/bash
# /usr/local/bin/impossible-travel-response.sh
# Called by SEC shellcmd - receives data via command-line arguments
USERNAME="$1"
DETAILS="$2"
# Query HR system for user travel status
TRAVEL_STATUS=$(curl -s "https://hr-api.company.com/travel-status/$USERNAME")
# Query threat intelligence for IP reputation
# Note: IP would need to be extracted from DETAILS or passed as separate argument
IP_REPUTATION=$(curl -s "https://threat-intel.company.com/ip-reputation/$(echo $DETAILS | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')")
# Make intelligent decision based on context
if [[ "$TRAVEL_STATUS" == "approved_travel" ]]; then
# User has approved travel - lower priority
logger -t SECURITY-RESPONSE "Impossible travel for $USERNAME - approved travel detected"
# Create low-priority ticket
curl -X POST "https://servicedesk.company.com/api/tickets" \
-d "priority=low&subject=Travel Login Verification&user=$USERNAME"
elif [[ "$IP_REPUTATION" == "malicious" ]]; then
# High-risk scenario - immediate response
logger -t SECURITY-RESPONSE "Impossible travel for $USERNAME - malicious IP detected"
# Disable account immediately
curl -X POST "https://identity.company.com/api/disable-account" -d "username=$USERNAME"
# Create high-priority incident
curl -X POST "https://servicedesk.company.com/api/incidents" \
-d "priority=critical&subject=Account Compromise&user=$USERNAME&details=$DETAILS"
# Alert SOC team
curl -X POST "https://slack.company.com/api/webhooks/soc-alerts" \
-d "text=CRITICAL: Account compromise detected for $USERNAME"
else
# Standard response - investigate
logger -t SECURITY-RESPONSE "Impossible travel for $USERNAME - investigation required"
# Temporarily restrict account
curl -X POST "https://identity.company.com/api/restrict-account" -d "username=$USERNAME"
# Create medium-priority ticket
curl -X POST "https://servicedesk.company.com/api/tickets" \
-d "priority=medium&subject=Impossible Travel Investigation&user=$USERNAME"
fi
Lateral Movement Detection
Cross-System Access Correlation
Detect lateral movement by correlating edge system logins with internal network access.
SEC Rule: Lateral Movement Correlation
text# Create context for edge system logins type=Single ptype=SubStr pattern=AUTH_SUCCESS context=($ENV{EVENT_HOST} =~ /^(web|dmz|edge|vpn)/) desc=Edge system access by $ENV{EVENT_USER_TAGS_PAM_USER_TRACKING} action=eval %username $ENV{EVENT_USER_TAGS_PAM_USER_TRACKING}; \ eval %edge_host $ENV{EVENT_HOST}; \ eval %src_ip $ENV{EVENT_USER_TAGS_PAM_REMOTE_HOST}; \ create EDGE_ACCESS_%username_%edge_host 3600; \ shellcmd (logger -t SEC-AUDIT "EDGE_LOGIN user=\"%username\" host=\"%edge_host\" src_ip=\"%src_ip\"") # Detect internal network access from edge systems type=Single ptype=SubStr pattern=NETWORK_CONNECTION context=(EDGE_ACCESS_$ENV{EVENT_USER_TAGS_PAM_USER_TRACKING}_$ENV{EVENT_USER_TAGS_SRCIP}) && \ ($ENV{EVENT_USER_TAGS_DSTIP} =~ /^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.)/) desc=Potential lateral movement detected action=eval %username $ENV{EVENT_USER_TAGS_PAM_USER_TRACKING}; \ eval %src_host $ENV{EVENT_HOST}; \ eval %dst_ip $ENV{EVENT_USER_TAGS_DSTIP}; \ eval %dst_port $ENV{EVENT_USER_TAGS_DSTPORT}; \ shellcmd (logger -t SEC-SECURITY -p local0.crit \ "LATERAL_MOVEMENT user=%username src_host=%src_host dst_ip=%dst_ip dst_port=%dst_port")
LogZilla Trigger: Lateral Movement Response
yamlname: "Lateral Movement Incident Response"
filter:
- field: program
op: eq
value: SEC-SECURITY
- field: message
op: "=~"
value: "LATERAL_MOVEMENT"
actions:
exec_script: true
script_path: "/usr/local/bin/lateral-movement-response.sh"
issue_notification: true
send_webhook: true
send_webhook_template: |
{
"alert_type": "lateral_movement",
"user": "{{event:ut:username}}",
"source_host": "{{event:ut:src_host}}",
"destination": "{{event:ut:dst_ip}}:{{event:ut:dst_port}}",
"severity": "critical"
}
Advanced Persistent Threat (APT) Detection
Multi-Stage APT Correlation
Detect sophisticated attack campaigns across multiple stages and systems.
SEC Rule: APT Campaign Detection
text# Stage 1: Initial compromise indicators type=Single ptype=SubStr pattern=SUSPICIOUS_OUTBOUND context=($ENV{EVENT_USER_TAGS_DESTINATION} =~ /suspicious_domain|known_c2/) desc=Potential C2 communication detected action=eval %host $ENV{EVENT_HOST}; \ eval %dst $ENV{EVENT_USER_TAGS_DESTINATION}; \ create APT_INDICATOR_%host 86400; \ shellcmd (logger -t SEC-APT "APT_STAGE1 host=\"%host\" destination=\"%dst\"") # Stage 2: Credential harvesting type=Single ptype=SubStr pattern=PROCESS_CREATION context=(APT_INDICATOR_$ENV{EVENT_HOST}) && \ ($ENV{EVENT_USER_TAGS_PROCESS_NAME} =~ /(mimikatz|lsass|procdump)/) desc=Credential harvesting detected on compromised host action=eval %host $ENV{EVENT_HOST}; \ eval %process $ENV{EVENT_USER_TAGS_PROCESS_NAME}; \ shellcmd (logger -t SEC-APT "APT_STAGE2 host=\"%host\" process=\"%process\"") # Stage 3: Data exfiltration type=Single ptype=SubStr pattern=LARGE_DATA_TRANSFER context=(APT_INDICATOR_$ENV{EVENT_HOST}) && \ ($ENV{EVENT_USER_TAGS_BYTES_TRANSFERRED} > 100000000) desc=Potential data exfiltration from compromised host action=eval %host $ENV{EVENT_HOST}; \ eval %bytes $ENV{EVENT_USER_TAGS_BYTES_TRANSFERRED}; \ eval %dst $ENV{EVENT_USER_TAGS_DESTINATION}; \ shellcmd (logger -t SEC-APT -p local0.crit \ "APT_CAMPAIGN host=%host bytes=%bytes destination=%dst")
LogZilla Trigger: APT Campaign Response
yamlname: "APT Campaign Incident Response"
filter:
- field: program
op: eq
value: SEC-APT
- field: message
op: "=~"
value: "APT_CAMPAIGN"
actions:
exec_script: true
script_path: "/usr/local/bin/apt-campaign-response.sh"
send_email: true
send_email_template: |
Subject: CRITICAL: APT Campaign Detected
Host: {{event:ut:host}}
Data Exfiltrated: {{event:ut:bytes}} bytes
Destination: {{event:ut:destination}}
Immediate containment required.
Privilege Escalation Detection
Account Privilege Changes Correlation
Monitor for suspicious privilege escalations and administrative access patterns.
SEC Rule: Privilege Escalation Correlation
text# Track administrative access attempts type=SingleWithThreshold ptype=SubStr pattern=ADMIN_ACCESS_ATTEMPT context=($ENV{EVENT_USER_TAGS_AUTH_RESULT} eq "failed") desc=Multiple failed admin access attempts action=eval %username $ENV{EVENT_USER_TAGS_PAM_USER_TRACKING}; \ eval %target_host $ENV{EVENT_HOST}; \ shellcmd (logger -t SEC-SECURITY \ "PRIVILEGE_ESCALATION_ATTEMPT user=%username target=%target_host count=$thresh") thresh=5 window=300 # Detect successful admin access after failed attempts type=PairWithWindow ptype=SubStr pattern=PRIVILEGE_ESCALATION_ATTEMPT desc=Successful privilege escalation after failed attempts action=eval %username $ENV{EVENT_USER_TAGS_PAM_USER_TRACKING}; \ eval %target_host $ENV{EVENT_HOST}; \ shellcmd (logger -t SEC-SECURITY -p local0.alert \ "PRIVILEGE_ESCALATION_SUCCESS user=%username target=%target_host") ptype2=SubStr pattern2=ADMIN_ACCESS_ATTEMPT context2=($ENV{EVENT_USER_TAGS_AUTH_RESULT} eq "success") && \ ($ENV{EVENT_USER_TAGS_PAM_USER_TRACKING} eq "%username") && \ ($ENV{EVENT_HOST} eq "%target_host") desc2=Admin access granted after escalation attempts action2=logonly window=600