Implementing open-source Wazuh SIEM

Wazuh is a free, open-source, and enterprise-ready security monitoring solution for threat detection, integrity monitoring, incident response, and compliance.

Below is a topology to implement Wazuh solution.

Below are a couple of steps in this lab.

  • Install Wazuh on LinuxMint
  • Configure Agentless on LAMP server
  • Install Agent on WordPress

+ Install Wazuh on LinuxMint 20.

Following Wazuh link below to install it into LinuxMint 20

https://documentation.wazuh.com/current/installation-guide/open-distro/distributed-deployment/step-by-step-installation/index.html

Login to Wazuh management interface.

+ Using a link below to Configure Agentless monitoring on Wazuh.

https://documentation.wazuh.com/current/user-manual/capabilities/agentless-monitoring/how-it-works.html

To set up that method of access, firstly you need to create ssh keys for the user ossec which is the account the agentless scripts run.

sudo -u ossec ssh-keygen

Copy SSH public key to Debian server that you want to monitor via agentless.

Using the add the option will specify a new device to be added to the manager. “NOPASS” may be entered as the password to use public-key authentication rather than using a password.

Back to Wazuh management interface and add the code below into ossec.conf file to monitor Linux servers with any changes on /bin / etc and /sbin directory.

<agentless>
  <type>ssh_integrity_check_linux</type>
  <frequency>3600</frequency>
  <host>root@192.168.5.41</host>
  <state>periodic</state>
  <arguments>/bin /etc/ /sbin</arguments>
</agentless>

Create a new file under /etc/tung and tung1 user. Security events have been generated on Wazuh from Debian server.

/var/ossec/bin/wazuh-control restart

Wazuh Security Dashboard.

+ Install Wazuh agent on Debian server.

Follow the link below to install Wazuh agent.

https://documentation.wazuh.com/current/installation-guide/wazuh-agent/wazuh-agent-package-linux.html

# Add the Wazuh repository
curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | apt-key add -
# Add the repository:
echo "deb https://packages.wazuh.com/4.x/apt/ stable main" | tee -a /etc/apt/sources.list.d/wazuh.list
# Update the package information:
apt-get update
# Deploy a Wazuh agent
WAZUH_MANAGER="192.168.5.34" apt-get install wazuh-agent
# Enable and start Wazuh
systemctl daemon-reload
systemctl enable wazuh-agent
systemctl start wazuh-agent

Wazuh agent on Windows machine.

Get LastReboot and Uptime value on Windows 10 and Windows Server via PS

In this lab, I have used PS to get LastReboot and Uptime value on Windows servers and clients. PS script will query “Get-WmiObject” to get the last boot time of the computers/servers.

Firstly, I will test with Windows Servers.

$OS1 = Get-WmiObject Win32_OperatingSystem -ComputerName DC1 -ErrorAction Stop
$LastReboot =($OS1.ConvertToDateTime($OS1.LastBootUpTime))
# Print LastReboot
$LastReboot
$Uptime = (Get-Date) -$OS1.ConvertToDateTime($OS1.LastBootUpTime)
$Uptime  = ([String]$Uptime.Days + " Days " + $Uptime.Hours + " Hours " + $Uptime.Minutes + " Minutes")
# Print uptime

Write a full PS script.

# This script is written by Tung on 2022-02-18
# This is used to get lastreboot and uptime on Windows servers.
# Get time when running the script
$filename = (Get-Date).tostring("dd-MM-yyyy-hh-mm")
# Change PowerShell working directory to C:\Shared
Set-Location C:\Shared
#$TestComputerName = get-content C:\Shared\tungmachine.txt
$servers = (Get-ADComputer -properties OperatingSystem -filter{(operatingsystem -like "*Windows Server*")}).name
Foreach ($server in $servers) {
        # Only check the machine if it is online
        $ping_result = Test-Connection -ComputerName $server -Count 1 -Quiet
        # If the machine is online
        if($ping_result){
        # Using "Get-WmiObject Win32_OperatingSystem" to get $OS object
        # Using "Get-WmiObject Win32_OperatingSystem -ComputerName $Testcomputer -ErrorAction Stop" to get $OS object on remote machines.
        $OS = Get-WmiObject Win32_OperatingSystem -ComputerName $server -ErrorAction Stop
        # Get LastReboot via $OS.LastBootUpTime variable
        $LastReboot =($OS.ConvertToDateTime($OS.LastBootUpTime)).tostring("dd-MM-yyyy")    
        # Get Uptime via $OS.LastBootUpTime variable
        $Uptime = (Get-Date) -$OS.ConvertToDateTime($OS.LastBootUpTime)
        # Create a hash table (dictionary type) with 3 columns: PSComputerName, LastReboot and Uptime
        $lastlogonproperties = @{
        # Add PSComputerName into column #1
        PSComputerName  = $server
        # Convert and only get dd-mm-yyyy on last reboot variable.
        # Add LastReboot into column #2
        # Only get dd-mm-yyy field on LastReboot record.
        LastReboot =($OS.ConvertToDateTime($OS.LastBootUpTime)).tostring("dd-MM-yyyy")
        # Add LastReboot into column #3
        Uptime  = ([String]$Uptime.Days + " Days " + $Uptime.Hours + " Hours " + $Uptime.Minutes + " Minutes")
        }

    # Create a new table object on PS to append the hash table values above   
    $forcecsv = New-Object psobject -Property $lastlogonproperties
    # change order of columns before appending to csv file. 
    # Convert it to csv file and save under LastReboot directory.
    $forcecsv | select-object PSComputerName, LastReboot, Uptime | export-csv -NoTypeInformation -append "C:\Shared\LastReboot\Server\$filename.csv"
    }
}

Run the script.

Then, do the same PS script to query Windows 10 machines.

Change “(operatingsystem -like “*Windows Server*”)” to (operatingsystem -like “*Windows 10*”)

$computers = (Get-ADComputer -properties OperatingSystem -filter{(operatingsystem -like "*Windows 10*")}).name
# This script is written by Tung on 2022-02-18
# This is is used t get lastreboot and uptime on Windows 10 machines.
# Get time when running the script
$filename = (Get-Date).tostring("dd-MM-yyyy-hh-mm")
# Change PowerShell working directory to C:\Shared
Set-Location C:\Shared
#$TestComputerName = get-content C:\Shared\tungmachine.txt
$computers = (Get-ADComputer -properties OperatingSystem -filter{(operatingsystem -like "*Windows 10*")}).name
Foreach ($Computer in $computers) {
        # Only check the machine if it is online
        $ping_result = Test-Connection -ComputerName $Computer -Count 1 -Quiet
        # If the machine is online
        if($ping_result){
        # Using "Get-WmiObject Win32_OperatingSystem" to get $OS object
        # Using "Get-WmiObject Win32_OperatingSystem -ComputerName $Testcomputer -ErrorAction Stop" to get $OS object on remote machines.
        $OS = Get-WmiObject Win32_OperatingSystem -ComputerName $Computer -ErrorAction Stop
        # Get LastReboot via $OS.LastBootUpTime variable
        $LastReboot =($OS.ConvertToDateTime($OS.LastBootUpTime)).tostring("dd-MM-yyyy")    
        # Get Uptime via $OS.LastBootUpTime variable
        $Uptime = (Get-Date) -$OS.ConvertToDateTime($OS.LastBootUpTime)
        # Create a hash table (dictionary type) with 3 columns: PSComputerName, LastReboot and Uptime
        $lastlogonproperties = @{
        # Add PSComputerName into column #1
        PSComputerName  = $Computer
        # Convert and only get dd-mm-yyyy on last reboot variable.
        # Add LastReboot into column #2
        # Only get dd-mm-yyy field on LastReboot record.
        LastReboot =($OS.ConvertToDateTime($OS.LastBootUpTime)).tostring("dd-MM-yyyy")
        # Add LastReboot into column #3
        Uptime  = ([String]$Uptime.Days + " Days " + $Uptime.Hours + " Hours " + $Uptime.Minutes + " Minutes")
        }

    # Create a new table object on PS to append the hash table values above   
    $forcecsv = New-Object psobject -Property $lastlogonproperties
    # change order of columns before appending to csv file. 
    # Convert it to csv file and save under LastReboot directory.
    $forcecsv | select-object PSComputerName, LastReboot, Uptime | export-csv -NoTypeInformation -append "C:\Shared\LastReboot\Client\$filename.csv"
    }
}

Run the script.

Using Ansible to install Wazuh agent

This is a topology to use Ansible to automatically install Wazuh agent.

This image has an empty alt attribute; its file name is image-460.png

On Debian server, edit sshd_configle file to allow root login and restart Opensshd daemon.

vi /etc/ssh/sshd_config Add the line “PermitRootLogin yes”

On LinutMint Ansible Controller.

Configure to access SSH daemon on Debian server via public key authentication.

Next, we need to set up Public key authentication on LinuxMint.

ssh-keygen -b 4096

Copy the key to the Debian server that you want to access.

Modify hosts on Ansible.

Create Wazuh file under /etc/ansible/group_vars.

ansible_ssh user:root
cd /etc/ansible/roles/
sudo git clone --branch v4.2.5 https://github.com/wazuh/wazuh-ansible.git
ls
Create Wazuh.yml file under /etc/ansible
---
- hosts: Wazuh
  roles:
    - /etc/ansible/roles/wazuh-ansible/roles/wazuh/ansible-wazuh-agent 
  vars:

    wazuh_managers:
      - address: 192.168.5.34
        port: 1514
        protocol: udp
        api_port: 55000
        api_proto: 'http'
        api_user: ansible
    wazuh_agent_authd:
      registration_address: 192.168.5.31
      enable: true
      port: 1515
      ssl_agent_ca: null
      ssl_auto_negotiate: 'no'

Run ansible to test on Debian host.

 ansible -m ping Wazuh -i /etc/ansible/hosts

Run ansible-playbook to install wazuh agent on Linux Debian server.

ansible-playbook -i /etc/ansible/hosts Wazuh.yml -u root

Using Ansible to install WordPress

This is one of the interesting labs that I have done in the program.

Below are a couple of steps to automatically deploy WordPress via Ansible.

# /etc/ansible/hosts
[tunglamp]
host1 ansible_ssh_host=192.168.5.27

# Create a group_vars (/etc/ansible) and tunglamp file under this directory.
ansible_ssh_user: root

# Create a files (/etc/ansible) directory and index.html.j2 file.
<html>
<head>
	<title>{{ firstname}} - {{ lastname }}</title> 
</head>
<body>
	<h1>{{ firstname }} - {{ lastname }}</h1> 
	<h3>Welcome to Tung's Ansbile Test Page</h3>
	<img src="http://xyz.ca/wp-content/uploads/2015/08/BCIT-demands-LNG-lobby-drop-its-name-from-partner-list.gif">
</body>
</html>

# Create a tungwordpress.yml file.
---
- hosts: tunglamp
  become: root
  gather_facts: false
# we can put variables here too that work in addition to what is in group_vars
  ignore_errors: yes
  vars:
    firstname: "ABC"
    lastname: "XYZ"
    #auser: hellothere
    ansible_ssh_user: root
    wpdbname: tungdbname
    wpdbuser: tungdbuser
    wpdbpass: tungdbpass
    wpdbhost: localhost
    wppath: "/var/www/html"

  tasks:
    - name: Install apache2
      apt: name=apache2 state=latest

    - name: Install MySQL (really MariaDB now)
      apt: name=mariadb-server state=latest

    - name: Install MySQL python module 
      apt: name=python-mysqldb state=latest

    - name: Install php
      apt: name=php state=latest
    - name: "Install php-cli"
      apt: name=php-cli state=latest
#    - name: "Install php-mcrypt"
#      apt: name=php-mcrypt state=latest
    - name: "Install php-gd"
      apt: name=php-gd state=latest
    - name: Install php-fpm
      apt: name=php-fpm state=latest
    - name: Install php-common
      apt: name=php-common state=latest
    - name: Install php-mbstring
      apt: name=php-mbstring state=latest
    - name: Install php-xmlrpc
      apt: name=php-xmlrpc state=latest
    - name: Install php-xml
      apt: name=php-xml state=latest
    - name: Install php zip
      apt: name=php-zip state=latest
    - name: Install php-curl
      apt: name=php-curl state=latest
    
    - name: Install apache2 php module
      apt: name=libapache2-mod-php state=latest

    - name: Install php-mysql

## your php installation appears to be missing the mysql extension if we have used ## apt: name=php-mysql state=latest
      apt: name=php7.3-mysql state=latest


#MySQL config
    - name: Create MySQL Database
      mysql_db:
        name: "{{wpdbname}}"
#     ignore_errors: yes

    - name: Create DB user/pass and give the user all privileges
      mysql_user:
        name: "{{wpdbuser}}"
        password: "{{wpdbpass}}"
        priv: '{{wpdbname}}.*:ALL'
        state: present
#     ignore_errors: yes

    - name: Copy index test page
      template:
        src: "files/index.html.j2"
        dest: "/var/www/html/index.html"

    - name: enable Apache2 service
      service: name=apache2 enabled=yes

#Wordpress stuff
    - name: Download and tar -zxvf wordpress
      unarchive:
        src: https://wordpress.org/latest.tar.gz
        remote_src: yes
        dest: "{{ wppath }}"
        extra_opts: [--strip-components=1]
       #creates: "{{ wppath }}"

    - name: Set permissions
      file:
        path: "{{wppath}}"
        state: directory
        recurse: yes
        owner: www-data
        group: www-data
 
    - name: copy the config file wp-config-sample.php to wp-config.php so we can edit it
      command: mv {{wppath}}/wp-config-sample.php {{wppath}}/wp-config.php 
      #creates={{wppath}}/wp-config.php
      become: yes
 
    - name: Update WordPress config file
      lineinfile:
        path: "{{wppath}}/wp-config.php"
        regexp: "{{item.regexp}}"
        line: "{{item.line}}"
      with_items:
        - {'regexp': "define\\( 'DB_NAME', '(.)+' \\);", 'line': "define( 'DB_NAME', '{{wpdbname}}' );"}
        - {'regexp': "define\\( 'DB_USER', '(.)+' \\);", 'line': "define( 'DB_USER', '{{wpdbuser}}' );"}
        - {'regexp': "define\\( 'DB_PASSWORD', '(.)+' \\);", 'line': "define( 'DB_PASSWORD', '{{wpdbpass}}' );"}
     

  handlers:
    - name: restart apache2 
      service: name=apache2 state=restarted
    - name: enable Apache2 service
      service: name=apache2 enabled=yes
    - name: Apache Module - mod_rewrite
      apache2_module:
        state: present
        name: rewrite
  
    - name: Copy index test page
      template:
        src: "files/index.html.j2"
        dest: "/var/www/html/index.html"  

The Debian server is running 192.168.5.27.

Make sure we can access SSH on the Debian server via public key authentication.

Run ansible-playbook

#/etc/ansible
ansible-playbook -i /etc/ansible/hosts tungwordpress.yml -u root

WordPress has been installed automatically via Ansible.

Install IIS Web server on Windows 2019 via Ansible

This is a lab topology that is used to deploy the IIS Web server via Ansible.

Configure WinRM service.

# Download a script to configure WinRM service on Windows Server 2019
# This script sets up both HTTP and HTTPS listeners with a self-signed certificate # and enables the Basic authentication option on the service # (https://docs.ansible.com/ansible/2.5/user_guide/windows_setup.html)
https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1 -OutFile ConfigureRemotingForAnsible.ps1
# Run the PS file.
powershell -ExecutionPolicy RemoteSigned .\ConfigureRemotingForAnsible.ps1
.\ConfigureRemotingForAnsible.ps1

Check WinRM service is running and WinRM port status is listening.

Get-nettcpconnection -state listen
get-service | where-object {$_.name -like "*WInRM*"}

Check Windows Firewall to make sure only allow WinRM over SSL on 5986 port, instead of using 5985 port.

Get-NetFirewallRule | where {$_.enabled -eq 'True' -and $_.Direction -eq 'Inbound' -and $_.DisplayName -like "*Allow  WinRM*"}

Add Windows Server 2019 IP address into /etc/ansible/hosts.

[Windows2019]
192.168.5.4

Create a new WIndows2019 file under the group_vars directory. Ansible connects to Windows Server 2019 via WinRM over TLS with the listening port is 5986. The file name should be Windows2019.

Create a sample index.html file to copy to the IIS server directory on WIndows server 2019.

<html>
<head>
	<title>Tung Ansible</title> 
</head>
<body>
	<h1 style="background-color:DodgerBlue;"> Use Ansible to install and configure IIS on WIndows 2019</h1> 
	<h3 style="color:Tomato;"> Welcome to Tung's Ansbile Test Page</h3>
	<img src="http://imagefromtheinternet.jpg">
</body>
</html>

Run ansible to check to access Windows server 2019 machine.

ansible Windows2019 -m win_ping
ansible Windows2019 -m setup
Now, we are ready to create an Ansible playbook for automatically installing and configuring the IIS Web server on Windows server 2019. Also, using ansible to retrieve IP address and disable Windows update service on Windows server machine.
---
- name: Windows Feature
  hosts: Windows2019
  gather_facts: true
#  vars:
#    name:
#     - wuauserv

#  vars:
#    firstname: "ABC"
#    lastname: "XYZ"

  tasks:
    - name: Disable Windows Updates Service
      win_service:
        name: wuauserv
        state: stopped
        enabled: false

    - name: Run ipconfig and return IP address information.
      raw: ipconfig
      register: ipconfig
    - debug: var=ipconfig

#    - name: Reboot
#      win_reboot:
#      when: reboot.reboot_required

# Install and enable IIS on Windows server 2019
    - name: Install IIS
      win_feature:
        name: "Web-Server"
        state: present
        restart: yes
        include_sub_features: yes
        include_management_tools: yes
# Copy the index.html file and rename to ansible.html under C:\inetpub\wwwroot. Must use \\ instead of \ for accessing directory on Windows server.
    - name: Copy index text page
      win_copy:
        src: "files/index.html"
        dest: "C:\\inetpub\\wwwroot\\ansible.html"

Run ansible-playbook with Windows2019 Yaml file.

ansible-playbook Windows2019.yml

Access the website on Windows server 2019.

On Window server 2019.

Check connections on Windows server 2019.

Install Apache Web server with Ansible

Below is the topology that I have used to install the Apache webserver via Ansible.

This image has an empty alt attribute; its file name is image-460.png

Make sure the Debian server allows Linuxmint to access by using Public key authentication.

On Linuxmint sever.

Create a new tungapache.yaml file

---
- hosts: tunglamp
  become: yes
  vars:
    firstname: "XXX"
    lastname: "YYY"
  tasks:
    - name: Update Debian Server 10 System packages
      become: yes
      apt:  update_cache=yes
    - name: install apache2
      apt: name=apache2 state=latest
    - name: Copy index text page
        template:
          src: "files/index.html.j2"
          dest: "/var/www/html/index.html"

Add Debian server with corresponding IP address information on hosts file.

Go to /etc/ansible directory and create a new files directory.

#pwd /etc/ansible
sudo mkdir files
sudo touch index.html.j2 && sudo nano index.html.j2
<html>
<head>
	<title>{{ firstname}} - {{ lastname }}</title> 
</head>
<body>
	<h1>{{ firstname }} - {{ lastname }}</h1> 
	<h3>Welcome to Tung's Ansbile Test Page</h3>
	<img src="http://imagefromtheinternet.jpg">
</body>
</html>

Run ansible-playbook to install apache webserver on remote Debian Linux server.

ansible-playbook -i /etc/ansible/hosts tungapache.yaml -u root

Check web content on the Debian server.

http://192.168.5.27/index.html

Install Ansible on Linux

The lab below simulates how to check a Linux server with Ansible.

Install Ansible on Linuxmint.

sudo apt install ansible

Set a password root for Linuxmint.

sudo passwd root

Install a new Debian Linux Server to test.

Install sshd service on Linuxmint.

sudo apt install ssh

Modify /etc/hosts.

Create a hosts file under /etc/ansible directory.

Create a new group_vars directory under /etc/ansible.

sudo mkdir group_vars
cd /etc/ansible/group_vars

Create a new tunglamp file.

Try to run a command and it fails.

ansible -m ping all -vvv

We need to setup Public key authentication on LinuxMint.

ssh-keygen -b 4096

Copy the key to the Debian server that you want to access.

ssh-copy-id root@192.168.5.27

Run the command below to make sure you can access to Debian server without a password.

ssh root@192.168.5.27

Check Debian server via Ansible.

ansible -m ping tunglamp
ansible -m shell -a 'free -m' tunglamp
ansible -m shell -s 'ifconfig -a | grep inet' tunglamp

Create an IPSEC site-to-site tunnel between Palo Alto And FortiGate.

This is the lab to use to set up the IPSEC site-to-site tunnel between both devices.

On Palo Alto.

IKE Crypto.

IPSEC Crypto.

IKE Gateway.

IPSec tunnel.

Create a virtual route from PA to Fortinet.

Create two Security Policies to allow traffic from the “Trusted Zone” of PA to the “Trusted Zone” of Fortinet.

Configure Fortinet.

config system interface
edit port1
set mode dhcp
set allowaccess ping httpd http fgfm
next
end
show system interface 
# show system interface to get IP Address from DHCP

Go to Webterm to configure Fortinet.

Configure a custom VPN Tunnel with the following information.

Configure a static route to allow traffic from Trusted Zone (192.168.20.0/24) on Fortinet to the Trusted Zone (192.168.10.0/24) on PA.

Create two Security policies to allow traffic from VPN to Trusted Zone and vice versa.

Ping and traceroute from a VM on Fortinet to another VM on Palo Alto.

Monitor IPSEC tunnel on Fortinet.

Monitor IPSEC tunnel on PA.

Create a VPN IPSEC site to site between Palo Alto and Cisco Router

This is a lab to set up a VPN site-to-site tunnel between both devices.

Configure interfaces and enable IPSEC VPN site to site on Cisco Router.

R1(config)#int g0/0
R1(config-if)#ip add 192.168.20.1 255.255.255.0
R1(config-if)#no shut


R1(config)#int g1/0
R1(config-if)#des "Connect to PA""
R1(config-if)#ip add 10.10.10.1 255.255.255.0
R1(config-if)#no shut

Create an ACL for VPN.
R1(config)#ip access-list extended ACL
R1(config-ext-nacl)#permit ip 192.168.20.0 0.0.0.255 192.168.10.0 0.0.0.255


Create ISAKMP phase 1 of the tunnel.


R1(config)#crypto isakmp policy 1
R1(config-isakmp)#encr aes
R1(config-isakmp)#hash md5
R1(config-isakmp)#authentication pre-share
R1(config-isakmp)#group 5
R1(config-isakmp)#lifetime 86400
# Assign authentication-key for remote peer.
R1(config)#crypto isakmp key cisco123 address 10.10.10.2


# Create IPSEC transfrom set for phase 2
R1(config)#crypto ipsec transform-set TSET esp-aes esp-sha-hmac

# Create cryoto map to apply the phase 2 settings to the interface
crypto map PA1 10 ipsec-isakmp
set peer 10.10.10.2
set transform-set TSET
match address ACL

# Applly crypto map to an interface.

R1(config-crypto-map)#int g1/0
R1(config-if)#crypto map PA1

# Create a static route to route traffic between both sites.
R1(config)#ip route 0.0.0.0 0.0.0.0 10.10.10.2

Access Palo Alto Web management.

Assign an IP address for interface e1/1 and e1/2.

Create a new tunnel 1 on PA.

Configure a static route between PA and Cisco Router and set next hop is “None”.

Configure IKECrypto as on Cisco Router.

Configure IKE Gateway.

Configure IPSEC Tunnel.

Configure Proxy ID.

Create both Security policies to allow traffic from the Trusted zone to the VPN zone and vice versa.

From Webterm2 (192.168.10.2) pings Webterm 3 (192.168.20.2).

Check PA, the IPSEC tunnel is up.

Deploy Palo Alto HA

This is a lab to deploy Palo Alto.

Set interface e1/1 is HA on both Firewalls.

Enable HA on Palo Alto.

Setup Election setting on both Firewalls.

configure the HA1 link.

On PA1:

On PA2:

Verify HA

On PA1.

On PA2.