Root User Access Monitoring with OSSEC/Wazuh
Introduction
OSSEC can be used to monitor whether the SSH configuration file allows root user access. This is particularly useful for ensuring that systems are configured according to security best practices and compliance requirements. By using OSSEC’s rootcheck component, we can verify that critical security configurations are properly set across multiple systems.
The rootcheck component performs policy monitoring, which is invaluable when managing large numbers of hosts that need to comply with security baselines such as CIS hardening guidelines or PCI DSS requirements. This capability enables:
- 🔍 Configuration Verification: Ensure SSH settings match security policies
- 🛡️ Compliance Monitoring: Verify adherence to standards like PCI DSS
- 📊 Centralized Reporting: Monitor multiple systems from a single point
- 🚨 Real-time Alerting: Get notified when configurations drift from baseline
- 📋 Audit Trail: Maintain records for compliance audits
Understanding Rootcheck
How Rootcheck Works
flowchart TB
subgraph "Rootcheck Engine"
P1[Policy Files]
P2[System Audit Rules]
P3[CIS Benchmarks]
end
subgraph "System Checks"
S1[Configuration Files]
S2[File Permissions]
S3[Running Processes]
S4[Network Settings]
end
subgraph "Alert Generation"
A1[Rule Matching]
A2[Alert Creation]
A3[Dashboard Display]
end
P1 --> S1
P2 --> S1
P3 --> S1
S1 --> A1
S2 --> A1
S3 --> A1
S4 --> A1
A1 --> A2
A2 --> A3
style P1 fill:#51cf66
style A1 fill:#4dabf7
style A3 fill:#ffd43b
Policy Monitoring Components
- System Audit Files: Define what to check
- Rootcheck Rules: Specify compliance requirements
- Alert Rules: Determine severity and notifications
- Reporting: Visualize compliance status
Implementation Guide
Prerequisites
- Wazuh Manager: Installed and running (our OSSEC fork)
- Linux Agents: Ubuntu/CentOS with Wazuh agents
- Access: Administrative privileges on all systems
- Network: Agents can communicate with manager
Phase 1: Create Rootcheck Rule for SSH Configuration
Create a custom system audit file on the manager:
sudo vim /var/ossec/etc/shared/system_audit_test.txtAdd the following rootcheck rule:
# PermitRootLogin no allowed# PermitRootLogin indicate if the user root can log in by ssh.$sshd_file=/etc/ssh/sshd_config;
[SSH Configuration - 1: Root can log in] [any] [1]f:$sshd_file -> !r:^# && r:PermitRootLogin\.+yes;f:$sshd_file -> r:^#\s*PermitRootLogin;This rule checks:
- If PermitRootLogin is set to “yes” (not desirable)
- If PermitRootLogin is commented out (uses default, which may allow root)
Phase 2: Configure Agent Policy Monitoring
Option 1: Local Configuration (Manager Only)
Edit /var/ossec/etc/ossec.conf:
<ossec_config> <rootcheck> <system_audit>/var/ossec/etc/shared/system_audit_test.txt</system_audit> </rootcheck></ossec_config>Option 2: Centralized Configuration (All Linux Agents)
Edit /var/ossec/etc/shared/agent.conf:
<agent_config os="Linux"> <rootcheck> <system_audit>/var/ossec/etc/shared/system_audit_test.txt</system_audit> </rootcheck></agent_config>Restart the manager:
sudo /var/ossec/bin/ossec-control restartPhase 3: Testing the Configuration
Enable Detailed Logging
To see rootcheck results in real-time, enable logall:
<ossec_config> <global> <logall>yes</logall> </global></ossec_config>Modify SSH Configuration (Test Only)
On a test agent, temporarily allow root login:
sudo vim /etc/ssh/sshd_configChange or add:
PermitRootLogin yesRestart SSH service:
sudo service ssh restartTrigger Rootcheck Scan
From the manager, force a rootcheck scan:
sudo /var/ossec/bin/agent_control -r -u <agent-id>Monitor Results
Check archives.log:
tail -f /var/ossec/logs/archives/archives.logExpected output:
2016 Apr 07 13:40:26 (ubuntu) 10.0.0.144->rootcheck Starting rootcheck scan.2016 Apr 07 13:40:28 (ubuntu) 10.0.0.144->rootcheck System Audit: SSH Configuration - 1: Root can log in. File: /etc/ssh/sshd_config. Reference: 1 .Alert Configuration
Default Alert Rule
The default rule for system audit events:
<rule id="516" level="3"> <if_sid>510</if_sid> <match>^System Audit</match> <description>System Audit event.</description> <group>rootcheck</group></rule>Custom High-Priority Alert
To increase alert severity for email notifications, add to /var/ossec/etc/rules/local_rules.xml:
<rule id="100002" level="9"> <if_sid>516</if_sid> <match>Root can log in</match> <description>Critical: SSH allows root login</description> <group>rootcheck,ssh_security,</group></rule>Use Cases
Use Case 1: PCI DSS Compliance
PCI Requirement 2.2.4
“Configure system security parameters to prevent misuse.”
Wazuh includes comprehensive SSH security checks in system_audit_ssh.txt:
# Some key checks from system_audit_ssh.txt[SSH Configuration - Protocol version 1 enabled] [any] [1]f:$sshd_file -> !r:^# && r:Protocol\.+1;
[SSH Configuration - Root login allowed] [any] [1]f:$sshd_file -> !r:^# && r:PermitRootLogin\.+yes;
[SSH Configuration - Empty passwords permitted] [any] [1]f:$sshd_file -> !r:^# && r:^PermitEmptyPasswords\.+yes;
[SSH Configuration - Host based authentication enabled] [any] [1]f:$sshd_file -> !r:^# && r:HostbasedAuthentication\.+yes;Enable these checks:
<agent_config os="Linux"> <rootcheck> <system_audit>/var/ossec/etc/shared/system_audit_ssh.txt</system_audit> </rootcheck></agent_config>Use Case 2: CIS Benchmark Compliance
Custom CIS Checks
Create /var/ossec/etc/shared/cis_sshd_hardening.txt:
# CIS 5.2.1 Ensure permissions on /etc/ssh/sshd_config are configured[CIS - SSH Configuration - 5.2.1: Incorrect permissions] [any] [1]f:/etc/ssh/sshd_config -> !r:^-rw-------.*;
# CIS 5.2.2 Ensure SSH Protocol is set to 2[CIS - SSH Configuration - 5.2.2: Protocol not set to 2] [any] [1]f:$sshd_file -> !r:^# && !r:Protocol\.+2;
# CIS 5.2.3 Ensure SSH LogLevel is set to INFO[CIS - SSH Configuration - 5.2.3: LogLevel not INFO] [any] [1]f:$sshd_file -> !r:^# && !r:LogLevel\.+INFO;
# CIS 5.2.4 Ensure SSH X11 forwarding is disabled[CIS - SSH Configuration - 5.2.4: X11 forwarding enabled] [any] [1]f:$sshd_file -> !r:^# && r:X11Forwarding\.+yes;
# CIS 5.2.5 Ensure SSH MaxAuthTries is set to 4 or less[CIS - SSH Configuration - 5.2.5: MaxAuthTries too high] [any] [1]f:$sshd_file -> !r:^# && r:MaxAuthTries\.+[5-9];Use Case 3: Multi-Environment Monitoring
Development Environment
<agent_config os="Linux" profile="development"> <rootcheck> <system_audit>/var/ossec/etc/shared/ssh_audit_dev.txt</system_audit> <frequency>86400</frequency> <!-- Daily --> </rootcheck></agent_config>Production Environment
<agent_config os="Linux" profile="production"> <rootcheck> <system_audit>/var/ossec/etc/shared/ssh_audit_prod.txt</system_audit> <frequency>3600</frequency> <!-- Hourly --> </rootcheck></agent_config>Advanced Configuration
Comprehensive SSH Security Monitoring
# Authentication Settings[SSH - Password authentication enabled] [any] [1]f:$sshd_file -> !r:^# && r:PasswordAuthentication\.+yes;
[SSH - Challenge response authentication enabled] [any] [1]f:$sshd_file -> !r:^# && r:ChallengeResponseAuthentication\.+yes;
[SSH - Public key authentication disabled] [any] [1]f:$sshd_file -> !r:^# && r:PubkeyAuthentication\.+no;
# Access Controls[SSH - AllowUsers not configured] [any] [1]f:$sshd_file -> !r:^# && !r:AllowUsers;
[SSH - DenyUsers not configured] [any] [1]f:$sshd_file -> !r:^# && !r:DenyUsers;
# Security Features[SSH - StrictModes disabled] [any] [1]f:$sshd_file -> !r:^# && r:StrictModes\.+no;
[SSH - IgnoreRhosts disabled] [any] [1]f:$sshd_file -> !r:^# && r:IgnoreRhosts\.+no;
# Timeout Settings[SSH - ClientAliveInterval not set] [any] [1]f:$sshd_file -> !r:^# && !r:ClientAliveInterval;
[SSH - ClientAliveCountMax not set] [any] [1]f:$sshd_file -> !r:^# && !r:ClientAliveCountMax;Custom Alert Rules with Context
<group name="ssh_policy,"> <!-- Critical: Root access misconfiguration --> <rule id="100010" level="10"> <if_sid>516</if_sid> <match>Root can log in</match> <description>SSH configuration allows root login - Critical security risk</description> <options>alert_by_email</options> <group>pci_dss_2.2.4,cis_5.2.8,</group> </rule>
<!-- High: Weak authentication methods --> <rule id="100011" level="8"> <if_sid>516</if_sid> <match>Empty passwords permitted|Password authentication enabled</match> <description>Weak SSH authentication method detected</description> <group>authentication_failed,pci_dss_2.2.4,</group> </rule>
<!-- Medium: Missing security controls --> <rule id="100012" level="6"> <if_sid>516</if_sid> <match>AllowUsers not configured|DenyUsers not configured</match> <description>SSH access controls not properly configured</description> <group>access_control,</group> </rule>
<!-- Correlation: Multiple SSH misconfigurations --> <rule id="100013" level="12" frequency="3" timeframe="120"> <if_matched_sid>100010,100011,100012</if_matched_sid> <description>Multiple SSH security misconfigurations detected</description> <options>alert_by_email</options> </rule></group>Dashboard Integration
Kibana Visualization
Create custom visualizations for SSH compliance:
{ "visualization": { "title": "SSH Configuration Compliance", "visState": { "type": "pie", "params": { "addTooltip": true, "addLegend": true, "legendPosition": "right", "isDonut": true }, "aggs": [ { "id": "1", "enabled": true, "type": "count", "schema": "metric", "params": {} }, { "id": "2", "enabled": true, "type": "terms", "schema": "segment", "params": { "field": "rule.pci_dss", "size": 10, "order": "desc", "orderBy": "1" } } ] } }}Compliance Dashboard Components
- SSH Security Status: Overall compliance percentage
- Failed Checks by Host: Which systems have issues
- Trending Compliance: Historical compliance data
- Critical Findings: High-priority misconfigurations
Automation and Remediation
Automated Response Script
#!/bin/bash# ssh_remediation.sh - Automatically fix SSH misconfigurations
SSHD_CONFIG="/etc/ssh/sshd_config"BACKUP_DIR="/etc/ssh/backups"TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# Create backupmkdir -p "$BACKUP_DIR"cp "$SSHD_CONFIG" "$BACKUP_DIR/sshd_config.$TIMESTAMP"
# Function to update SSH settingupdate_ssh_setting() { local setting=$1 local value=$2
if grep -q "^#*${setting}" "$SSHD_CONFIG"; then sed -i "s/^#*${setting}.*/${setting} ${value}/" "$SSHD_CONFIG" else echo "${setting} ${value}" >> "$SSHD_CONFIG" fi}
# Apply security settingsupdate_ssh_setting "PermitRootLogin" "no"update_ssh_setting "PasswordAuthentication" "no"update_ssh_setting "PermitEmptyPasswords" "no"update_ssh_setting "Protocol" "2"update_ssh_setting "X11Forwarding" "no"update_ssh_setting "MaxAuthTries" "3"update_ssh_setting "ClientAliveInterval" "300"update_ssh_setting "ClientAliveCountMax" "0"
# Validate configurationif sshd -t; then echo "SSH configuration valid, restarting service..." systemctl restart sshd echo "SSH hardening completed successfully"else echo "ERROR: Invalid SSH configuration, restoring backup..." cp "$BACKUP_DIR/sshd_config.$TIMESTAMP" "$SSHD_CONFIG" exit 1fiActive Response Configuration
<ossec_config> <command> <name>ssh-hardening</name> <executable>ssh_remediation.sh</executable> <expect></expect> <timeout_allowed>yes</timeout_allowed> </command>
<active-response> <command>ssh-hardening</command> <location>local</location> <rules_id>100010</rules_id> <timeout>300</timeout> </active-response></ossec_config>Troubleshooting
Common Issues
Issue 1: Rootcheck Not Running
# Check if rootcheck is enabledgrep -A5 "<rootcheck>" /var/ossec/etc/ossec.conf
# Verify rootcheck databasels -la /var/ossec/queue/rootcheck/
# Force rootcheck execution/var/ossec/bin/rootcheck_control -u allIssue 2: Alerts Not Generating
# Test rule matchingecho "System Audit: SSH Configuration - 1: Root can log in" | \ /var/ossec/bin/ossec-logtest
# Check alert logtail -f /var/ossec/logs/alerts/alerts.log | grep rootcheckIssue 3: Agent Not Receiving Configuration
# Verify shared configurationls -la /var/ossec/etc/shared/
# Check agent configuration/var/ossec/bin/agent_control -i <agent-id>
# Force configuration sync/var/ossec/bin/agent_control -R <agent-id>Best Practices
1. Policy Development
SSH Security Policy: Mandatory Settings: - PermitRootLogin: no - Protocol: 2 - PasswordAuthentication: no - PermitEmptyPasswords: no
Recommended Settings: - MaxAuthTries: 3 - ClientAliveInterval: 300 - X11Forwarding: no - AllowUsers: [specific users]
Monitoring: - Daily compliance checks - Real-time alerts for changes - Monthly compliance reports2. Deployment Strategy
Rollout Phases: Phase 1 - Assessment: - Deploy monitoring only - Identify non-compliant systems - Document exceptions
Phase 2 - Remediation: - Fix non-critical systems - Test automated responses - Update documentation
Phase 3 - Enforcement: - Enable auto-remediation - Monitor compliance metrics - Regular audits3. Exception Management
# Create exception listcat > /var/ossec/etc/lists/ssh_exceptions << EOF# Systems allowed to have root loginlegacy-server1.example.combackup-server.example.comEOF
# Update rules to check exceptions<rule id="100020" level="3"> <if_sid>100010</if_sid> <list field="hostname" lookup="match_key">etc/lists/ssh_exceptions</list> <description>SSH root login allowed (exception granted)</description> <options>no_email_alert</options></rule>Integration Examples
1. Compliance Reporting
#!/usr/bin/env python3import requestsimport jsonfrom datetime import datetime
def generate_ssh_compliance_report(): """Generate SSH compliance report from Wazuh API"""
# API configuration api_url = "https://localhost:55000" api_user = "wazuh" api_pass = "wazuh"
# Get rootcheck findings response = requests.get( f"{api_url}/rootcheck/000", auth=(api_user, api_pass), verify=False )
findings = response.json()['data']['items']
# Generate report report = { 'timestamp': datetime.now().isoformat(), 'total_checks': len(findings), 'failed_checks': sum(1 for f in findings if 'SSH' in f['event']), 'compliance_rate': 0, 'critical_findings': [] }
# Calculate compliance rate if report['total_checks'] > 0: report['compliance_rate'] = ( (report['total_checks'] - report['failed_checks']) / report['total_checks'] * 100 )
# Identify critical findings for finding in findings: if 'Root can log in' in finding['event']: report['critical_findings'].append({ 'host': finding['agent_id'], 'issue': finding['event'], 'file': finding.get('file', 'Unknown') })
return report
if __name__ == "__main__": report = generate_ssh_compliance_report() print(json.dumps(report, indent=2))2. Slack Notifications
#!/usr/bin/env python3import jsonimport sysimport requests
def send_slack_alert(alert_file): """Send SSH compliance alerts to Slack"""
webhook_url = "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
with open(alert_file) as f: alert = json.load(f)
if 'SSH' in alert.get('rule', {}).get('description', ''): message = { "attachments": [{ "color": "danger", "title": "SSH Security Alert", "fields": [ { "title": "Host", "value": alert['agent']['name'], "short": True }, { "title": "Issue", "value": alert['rule']['description'], "short": True }, { "title": "Details", "value": alert.get('full_log', 'No details'), "short": False } ], "footer": "Wazuh Security", "ts": alert['timestamp'] }] }
requests.post(webhook_url, json=message)
if __name__ == "__main__": send_slack_alert(sys.argv[1])Conclusion
Monitoring SSH configuration with OSSEC/Wazuh rootcheck provides organizations with a powerful tool for ensuring security compliance across their infrastructure. By implementing policy monitoring, you can:
- ✅ Enforce Security Standards: Ensure SSH configurations meet security requirements
- 🛡️ Maintain Compliance: Meet PCI DSS, CIS, and other regulatory requirements
- 📊 Centralize Monitoring: Track compliance across all systems from one location
- 🚨 Rapid Detection: Identify configuration drift immediately
- 🔧 Automate Remediation: Fix misconfigurations automatically
The flexibility of rootcheck allows organizations to customize checks according to their specific security policies and compliance requirements.
Key Takeaways
- Start with Basics: Monitor critical settings like root login first
- Expand Gradually: Add more checks as your program matures
- Automate Responses: Implement remediation for common issues
- Document Exceptions: Maintain clear records of approved deviations
- Regular Reviews: Update policies based on threat landscape
Resources
Secure your SSH configurations with OSSEC/Wazuh policy monitoring! 🔐🛡️