Visualize, analyze and search your host IDS alerts. Elastic Stack is the combination of three popular Open Source projects for log management, known as Elasticsearch, Logstash and Kibana(ELK). Together they provide a real-time and user-friendly console for your OSSEC alerts. OSSEC Wazuh integration with Elastic Stack comes with out-of-the-box dashboards for PCI DSS compliance and CIS benchmarks. You can do forensic and historical analysis of OSSEC alerts and store your data for several years, in a reliable and scalable platform. This post is updating a pervious post of mine using Wazuh 1.0 and version 2.0 of the ELK stack. This post will contain a general setup and configuration for a central logging server.
Install/Setup Wazuh server on CentOS 7 64-bit
Install/Setup NTPd
- yum update -y && yum upgrade -y
- yum install ntp ntpdate ntp-doc -y
- systemctl enable ntpd
- systemctl start ntpd
- ntpdate pool.ntp.org || true
Install/Setup Wazuh server
cat > /etc/yum.repos.d/wazuh.repo << 'EOF'
[wazuh_repo]
gpgcheck=1
gpgkey=https://packages.wazuh.com/key/GPG-KEY-WAZUH
enabled=1
name=CentOS-$releasever - Wazuh
baseurl=https://packages.wazuh.com/yum/el/$releasever/$basearch
protect=1
EOF
- yum install wazuh-manager -y
Setup/Configure Syslog input via udp
sed -i '/<\/remote>/a\ \<remote>\n\ \<connection>syslog</connection>\n\ \<allowed-ips><NETWORK IP ADDRESS>/24</allowed-ips>\n\ \</remote>' /var/ossec/etc/ossec.conf
- /var/ossec/bin/ossec-control restart
Install Wazuh API
- curl –silent –location https://rpm.nodesource.com/setup_6.x | bash –
- yum install nodejs -y
- yum install wazuh-api -y
Install/Setup Elasticsearch
- yum install java -y
- rpm –import https://packages.elastic.co/GPG-KEY-elasticsearch
cat > /etc/yum.repos.d/elastic.repo << EOF
[elastic-5.x]
name=Elastic repository for 5.x packages
baseurl=https://artifacts.elastic.co/packages/5.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
EOF
- yum install elasticsearch -y
- systemctl daemon-reload
- systemctl enable elasticsearch.service
- systemctl start elasticsearch.service
- Wait about 30 seconds for Elasticsearch to fully start
curl https://raw.githubusercontent.com/wazuh/wazuh-kibana-app/master/server/startup/integration_files/template_file.json | curl -XPUT 'http://localhost:9200/_template/wazuh' -H 'Content-Type: application/json' -d @-
- Command may fail if Elasticsearch hasn’t fully started and listening on port 9200.
Elasticsearch data rotation
cat >/etc/yum.repos.d/curator.repo << 'EOF'
[curator-5]
name=CentOS/RHEL 7 repository for Elasticsearch Curator 5.x packages
baseurl=http://packages.elastic.co/curator/5/centos/7
gpgcheck=1
gpgkey=http://packages.elastic.co/GPG-KEY-elasticsearch
enabled=1
EOF
- yum install elasticsearch-curator -y
- mkdir /etc/curator
cat > /etc/curator/config.yml << 'EOF'
# Remember, leave a key empty if there is no value. None will be a string,
# not a Python "NoneType"client: hosts: - 127.0.0.1 port: 9200 url_prefix: use_ssl: False certificate: client_cert: client_key: aws_key: aws_secret_key: aws_region: ssl_no_validate: False http_auth: timeout: 30 master_only: False logging: loglevel: INFO logfile: logformat: default blacklist: ['elasticsearch']
EOF
cat > /etc/curator/delete_wazuh.yml << 'EOF'
# Remember, leave a key empty if there is no value. None will be a string, # not a Python "NoneType" # # Also remember that all examples have 'disable_action' set to True. If you # want to use this action as a template, be sure to set this to False after # copying it. actions: 1: action: delete_indices description: >- Delete indices older than 90 days (based on index name), for logstash- prefixed indices. Ignore the error if the filter does not result in an actionable list of indices (ignore_empty_list) and exit cleanly. options: ignore_empty_list: True timeout_override: continue_if_exception: False disable_action: False filters: - filtertype: pattern kind: prefix value: wazuh-alerts- exclude: - filtertype: age source: name direction: older timestring: '%Y.%m.%d' unit: days unit_count: 90 exclude:
2: action: delete_indices description: >- Delete indices older than 90 days (based on index name), for logstash- prefixed indices. Ignore the error if the filter does not result in an actionable list of indices (ignore_empty_list) and exit cleanly. options: ignore_empty_list: True timeout_override: continue_if_exception: False disable_action: False filters: - filtertype: pattern kind: prefix value: wazuh-monitoring- exclude: - filtertype: age source: name direction: older timestring: '%Y.%m.%d' unit: days unit_count: 90 exclude:
EOF
echo "@daily /usr/bin/curator --config /etc/curator/config.yml /etc/curator/delete_wazuh.yml" >> /etc/crontab
- systemctl enable crond
- systemctl start crond
Install/Setup Logstash + OpenSSL
- yum install logstash -y
curl -so /etc/logstash/conf.d/01-wazuh.conf https://raw.githubusercontent.com/wazuh/wazuh/2.0/extensions/logstash/01-wazuh.conf
curl -so /etc/logstash/wazuh-elastic5-template.json https://raw.githubusercontent.com/wazuh/wazuh/2.0/extensions/elasticsearch/wazuh-elastic5-template.json
sed -i -e '/## Remote Wazuh Manager - Filebeat input/,+9 s/^/#/' /etc/logstash/conf.d/01-wazuh.conf
- Comment out remote Wazuh section
sed -i -e '/## Local Wazuh Manager - JSON file input/,+7 s/#//' /etc/logstash/conf.d/01-wazuh.conf
- Uncomment local Wazuh section
openssl req -x509 -batch -nodes -days 3650 -newkey rsa:2048 -keyout /etc/logstash/logstash.key -out /etc/logstash/logstash.cert
cat > /etc/logstash/conf.d/02-beats-input.conf << 'EOF'
input {
beats {
port => 5044
ssl => true
ssl_certificate => "/etc/logstash/logstash.cert"
ssl_key => "/etc/logstash/logstash.key"
}
}
EOF
cat > /etc/logstash/conf.d/30-elasticsearch-output.conf << 'EOF'
output {
elasticsearch {
hosts => ["http://localhost:9200"]
index => "%{type}-%{[@metadata][beat]}-%{+YYYY.MM.dd}"
document_type => "%{[@metadata][type]}"
}
}
EOF
- These two configs will take in any beats input from Filebeats and create an Elasticsearch index for it.
curl -O "https://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz"
- gzip -d GeoLiteCity.dat.gz && sudo mv GeoLiteCity.dat /etc/logstash/
- usermod -a -G ossec logstash
- This command is assuming you are running OSSEC/Wazuh and ELK on the same box
- systemctl daemon-reload
- systemctl enable logstash.service
- systemctl start logstash.service
Install/Setup Kibana with Wazuh dashboard
- yum install kibana -y
- /usr/share/kibana/bin/kibana-plugin install https://packages.wazuh.com/wazuhapp/wazuhapp.zip
- This command may take a while to install
- systemctl daemon-reload
- systemctl enable kibana.service
- systemctl start kibana.service
Install/Setup Nginx with OpenSSL
- yum -y install epel-release
- yum -y install nginx httpd-tools
- htpasswd -c /etc/nginx/htpasswdKibana.users kibanaadmin
- Enter password for kibana login
- cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
- sed -i -e ‘38,87d’ /etc/nginx/nginx.conf
- Removes default config settings that we don’t need
- mkdir /etc/nginx/ssl
- openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt
- openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
cat > /etc/nginx/conf.d/kibana.conf << 'EOF'
server {
listen 80 default_server;
listen [::]:80 default_server;server_name _;
return 301 https://$host$request_uri;
}server {
listen 443 ssl;
server_name _;root /usr/share/nginx/html;
index index.html index.htm;ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_session_timeout 1d;ssl_session_cache shared:SSL:50m;
ssl_stapling on;
ssl_stapling_verify on;add_header Strict-Transport-Security max-age=15768000;
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/htpasswdKibana.users;location / {
proxy_pass http://localhost:5601;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
EOF
- systemctl start nginx
- systemctl enable nginx
- setsebool -P httpd_can_network_connect 1
Setup Wazuh API
cat > /etc/nginx/conf.d/wazuh-api.conf << 'EOF'
server {
listen 55000 ssl;ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;location / {
proxy_pass http://127.0.0.1:5000;
}
}
EOF
sed -i 's/config.host = "0.0.0.0";/config.host = "127.0.0.1";/g' /var/ossec/api/configuration/config.js
sed -i 's/config.port = "55000";/config.port = "5000";/g' /var/ossec/api/configuration/config.js
sed -i 's/config.BehindProxyServer = "no";/config.BehindProxyServer = "yes";/g' /var/ossec/api/configuration/config.js
- cd /var/ossec/api/configuration/auth
- sudo node htpasswd -c user wazuhadmin
- systemctl restart wazuh-api
- Browse to “http://<ELK/OSSEC server IP addr> and login into Kibana
- May need to apply firewall rules below
- Select “Wazuh” on the left
- Select “Add new API”
- Enter “wazuhadmin” for username
- Enter password from above
- Enter “http://127.0.0.1” for URL
- Enter “5000” for port
- Select “Save”
Install/Setup FirewallD
- yum install firewalld -y
- systemctl start firewalld
- systemctl enable firewalld
- firewall-cmd –zone=public –permanent –add-service=http
- firewall-cmd –zone=public –permanent –add-service=https
- firewall-cmd –zone=public –permanent –add-port=55000/tcp
- firewall-cmd –zone=public –permanent –add-port=1514/udp
- firewall-cmd –zone=public –permanent –add-port=514/tcp
- firewall-cmd –zone=public –permanent –add-port=514/udp
- firewall-cmd –zone=public –permanent –add-service=ssh
- firewall-cmd –reload
Windows, and Linux Wazuh agent registration
When our agents are installed, it is necessary for them to communicate with the manager. The communication between an agent and the manager is performed via the OSSEC message protocol, which encrypts messages using a pre-shared key. The process of provisioning an agent authentication key on the manager and distributing it to an agent is called registration.
Generate Wazuh agent authentication key
- Login into Wazuh server
- /var/ossec/bin/manage_agents
- Enter “A” to add an agent
- Enter “<agent name preferable hostname>” for agent name
- Enter “<IP addr of agent>” for IP address
- Except default for agent ID
- Enter “y” to confirm
- Enter “E” to extract key for agent
- Enter “<ID of agent for key>”
Linux deployment
Manual deployment on Ubuntu 16.04 64-bit
Install Wazuh agent on Ubuntu
- sudo apt-get install curl apt-transport-https lsb-release -y
- curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | sudo apt-key add –
- CODENAME=$(lsb_release -cs)
echo "deb https://packages.wazuh.com/apt $CODENAME main" \| sudo tee /etc/apt/sources.list.d/wazuh.list
- sudo apt-get update -y && sudo apt-get install wazuh-agent -y
Add key to Ubuntu agent
- sudo su
- /var/ossec/bin/manage_agents
- Enter “I” to import key
- Paste key from above
- Enter “Y” to confirm adding key
- vim /var/ossec/etc/ossec.conf
- Replace “MANAGER_IP” between <server-ip></server-ip> with Wazuh IP
- save, exit
- /var/ossec/bin/ossec-control start
Confirm agent has been registered
- Browse to “http://<ELK/Wazuh server IP addr>”and login into Kibana
- Select “Wazuh” on the left
- Select the “agents” tab at the top
- As you can see our “ubuntu” agent was added
- localhost.localdomain agent is the actual Wazuh manager running in hybrid mode. Hybrid mode is when the Wazuh manager and wazuh agent run on the same box.
API deployment on Centos 7 Server 64-bit
cat > /etc/yum.repos.d/wazuh.repo <<'EOF'
[wazuh_repo]
gpgcheck=1
gpgkey=https://packages.wazuh.com/key/GPG-KEY-WAZUH
enabled=1
name=CentOS-$releasever - Wazuh
baseurl=https://packages.wazuh.com/yum/el/$releasever/$basearch
protect=1
EOF
- yum install wazuh-agent -y
wget https://raw.githubusercontent.com/wazuh/wazuh-api/2.0/examples/api-register-agent.sh
- sed -i ‘s/API_IP=”10.0.0.1″/API_IP=”<IP addr of Wazuh>”/g’ api-register-agent.sh
- sed -i ‘s/PROTOCOL=”http”/PROTOCOL=”https”/g’ api-register-agent.sh
- sed -i ‘s/USER=”foo”/USER=”wazuhadmin”/g’ api-register-agent.sh
- sed -i ‘s/PASSWORD=”bar”/PASSWORD=”<password of Wazuh api>”/g’ api-register-agent.sh
- chmod +x api-register-agent.sh
- ./api-register-agent.sh
- sed -i ‘s#<server-ip>MANAGER_IP</server-ip>#<server-ip><IP addr of Wazuh></server-ip>#g’ /var/ossec/etc/ossec.conf
- /var/ossec/bin/ossec-control restart
Windows 10 deployment
Wazuh manual deployment
- Open Powershell as Administrator
Invoke-WebRequest https://packages.wazuh.com/windows/wazuh-winagent-v2.0.1-1.exe -OutFile wazuh_agent.exe
- .\wazuh_agent.exe /S
- & ‘C:\Program Files (x86)\ossec-agent\win32ui.exe’
- Enter “<IP addr of Wazuh>” for Manager IP
- Enter “<Generated agent key>” for Authentication key
- Enter “Save”
- Select “Manage” then “Start”
Wazuh API deployment
- Open Powershell prompt as Admin
- cd C:\Users\$env:username
Invoke-WebRequest https://packages.wazuh.com/windows/wazuh-winagent-v2.0.1-1.exe -OutFile wazuh_agent.exe
- .\wazuh_agent.exe /S
Invoke-WebRequest https://raw.githubusercontent.com/wazuh/wazuh-api/master/examples/api-register-agent.ps1 -OutFile wazuh-api-register-agent.ps1
- Set-ExecutionPolicy RemoteSigned
- Need administration privileges for this
(Get-Content wazuh-api-register-agent.ps1).replace('$username = "foo"', '$username = "wazuhadmin"') | Set-Content wazuh-api-register-agent.ps1
(Get-Content wazuh-api-register-agent.ps1).replace('$password = "bar"', '$password = ""') | Set-Content wazuh-api-register-agent.ps1
(Get-Content wazuh-api-register-agent.ps1).replace('$base_url = "http://:55000"
', '$base_url = "https://:55000"') | Set-Content wazuh-api-register-agent.ps1(Get-Content wazuh-api-register-agent.ps1).replace('', '') | Set-Content wazuh-api-register-agent.ps1
REG ADD “HKCU\SOFTWARE\Microsoft\Internet Explorer\PhishingFilter” /v EnabledV9 /t REG_DWORD /d 0 /f
- This will DISABLE SmartScreen filter on Internet Explorer, what I’m lazy
- .\wazuh-api-register-agent.ps1
Setup/Configure Active Response
Linux blocking brute force attempts
- In this example, a command with the name “firewall-drop” is configured to use the “firewall-drop.sh” script using the data element “scrip”. The Active response is configured to initiate the “firewall-block” command on all systems when a rule in either the “authentificaiton_failed” or “authentification_failures” rule group fires. This is a Stateful response with a timeout of 700 seconds. The repeated offenders parameter increases the timeout period for each subsequent offence by a specific IP address.
- cp /var/ossec/etc/ossec.conf /var/ossec/etc/ossec.conf.bak
- vim /var/ossec/etc/ossec.conf
<active-response>
<!--- Linux block srcip on ALL machines for multiple failed authentication attempts--->
<command>firewall-block</command>
<location>all</location>
<rules_group>authentication_failed,authentication_failures</rules_group>
<timeout>700</timeout>
<repeated_offenders>30,60,120</repeated_offenders>
</active-response>
- /var/ossec/bin/ossec-control restart
- This should push out the new config to all agents
Windows blocking anything above a threat level
- In this example, a command with the name “win_rout-null” is configured to use the “route-null.cmd” script using the data element “srcip”. The Active response is configured to initiate the “win_rout-null” command on the local host when the rule has a higher alert level than 7. This is a Stateful response with a timeout set at 900 seconds.
- vim /var/ossec/etc/ossec.conf
<active-response>
<!--- Windows block srcip on local machine when rule level is greater than 8-->
<command>win_route‐null</command>
<location>local</location>
<level>8</level>
<timeout>900</timeout>
</active-response>
- /var/ossec/bin/ossec-control restart
Install/Setup Alerting via Slack
Setup/Configure Slack notifications
- /var/ossec/bin/ossec-control enable integrator
- /var/ossec/bin/ossec-control restart
- Add to/var/ossec/etc/ossec.conf:
slack
https://
when configuring Syslog in ossec.conf, i get this error Error reading XML file ‘/etc/ossec.conf’: (line 0).
Thank you
Hey Amine,
Make sure your config doesn’t have any weird newline characters with “vi” the text editor.