Cloud Threat Protection with OSSEC and Suricata
The idea of this setup is to protect the Small Systems as well as we protect the Big Systems.
This solution uses a proven stack to protect webservers from modern threats. Using OSSEC, Suricata, and the built-in firewall capabilities of a modern Linux system it is possible to build a low maintenance and stable threat protection platform with relatively low performance impacts.
It’s been specifically designed to be simple. The idea is that it will keep you on a ‘need to know basis’ and otherwise stay quiet and do it’s job.
Overview
Together, these components protect a web server from hacks, bots, spammers, and other nasty network attacks.
The components of this system are:
- Suricata to detect malicious network traffic,
- OSSEC for system integrity checking and log analysis,
- MailGun for mail relay services
However, there are some substantial limitations of this system. Here’s what it’s not:
- NOT a performance monitoring system
- NOT a downtime detection system
- NOT really an IPS (OSSEC will block high-scoring threats)
- NOT an accounting/auditing system
- Probably not going to get you past a HIPAA/FIPS/PCI-DSS auditor - that will be a lot more involved
Note: IPv4 Addresses
Throughout this post, I will be using RFC-5737 specified public IPv4 addresses. These will represent the three hosts used:
Name | Address |
---|---|
Server | 198.51.100.44 |
Client | 203.0.113.12 |
Hacker/Bot | 192.0.2.241 |
These IPv4 addresses are ‘fake’ and non-routable. Don’t try any weird stuff with these.
Configure Emails
Since the primary means for notifications will be good-old-Email, that’s the staring place.
Set up MailGun
To send monitoring emails we’ll set up MailGun as an SMTP relay. This simplifies things slighly by using a dedicated subdomain for mail relay where the Postfix server will connect. It also prevents the server from holding credentials for the main email account.
Mailgun is essentially free, but it does require payment information to prevent abuse of the system.
Once the account is set up, the domain ‘example.com’ is verified, the required TXT and MX records are added to the DNS zone. I will be working with ‘mail.example.com’ for this project, and my primary email server lives under the root ‘example.com’ domain.
After it’s set up, the wizard will produce a set of SMTP credentials. Save those for the next step.
Set up Postfix
On the server, a mail relay is set up using the Postfix package. This will let the server send emails to the admin mailbox, but it will not be able to receive any or read any mailboxes outside of its own spool.
First, install the packages on the server:
sudo apt install postfix mailutils
Then, the config can be written into /etc/postfix/main.cf
mynetworks = 127.0.0.0/8, [::1]/128
inet_interfaces = 127.0.0.1
relayhost = [smtp.mailgun.org]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_CAfile = /etc/ssl/certs/thawte_Primary_Root_CA.pem
smtp_use_tls = yes
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
Then, the address where alerts will be received is added to /etc/aliases
postmaster: root
root: name@example.com
Next, the credentials can be added to /etc/postfix/sasl_passwd
[smtp.mailgun.org]:587 postmaster@mail.example.com:xxx-password-xxx
After the file is created, make sure the permissions are correct:
sudo chown root:root /etc/postfix/sasl_passwd
sudo chmod 0600 /etc/postfix/sasl_passwd
Once all the config files are in place the SASL db can be created.
sudo postmap /etc/postfix/sasl_passwd
Finally, the Postfix service can be restarted to pick up the new config.
sudo systemctl restart postfix
The mail relay can be tested by sending yourself an email:
echo "Hello!" | mail -s 'Test Email' you@example.com
If the email doesn’t arrive within a minute or two, double check the config and look in the syslog for clues.
Suricata Network IDS
Suricata is one of my all time favourite tools for security monitoring. It’s fast, scalable, uses surprisingly few resources, and creates high quality network alerts. I’ve previously used it in another project for a custom Firewall/IDS appliance. In this project, it will only be used to generate an alert feed.
Install Suricata
This will be a typical installation of Suricata based on the official Install Docs.
First, set up the Ubuntu PPA repository.
sudo add-apt-repository ppa:oisf/suricata-stable
The package lists will need to be refreshed before the package can be installed.
sudo apt update
Then the package itself, along with all the runtime dependancies, can be installed on the system.
sudo apt install suricata
Configure Suricata
Once installed, the most important config change to make is to disable the eve.json
log output. While this is very useful when building a SIEM, we’re working on something much simpler, so the disk space usage of writing every single packet that hits the server isn’t a great idea.
These changes can be made towards the top of the default config file:
...
outptus:
...
- eve-log:
#enabled: yes
enabled: no
Make sure the classic snort-style output is enabled:
...
outputs:
- fast:
enabled: yes
filename: fast.log
append: yes
Otherwise, the default settings will be sufficient for this system.
sudo systemctl restart suricata
sudo systemctl enable suricata
Then a set of rules can be loaded. With version 4 and higher, all rule management is handled through the suricata-update
utility. So, the initial set of rules (ET Open) can be downloaded and installed.
sudo suricata-update
sudo kill -USR2 `pidof suricata`
Examine the output of /var/log/suricata/suricata.log
and check that all the rules were loaded correctly.
OSSEC Host IDS
OSSEC is a host-based Intrusion Detection System with a proven track record in the field. While it is very scalable and can connect hundreds of nodes to a central server, for this deployment we will install a single standalone system.
Install OSSEC
The OSSEC mainainers have published an easy-install script. It seems to work fairly well for setting up the Apt repository and keys.
wget -q -O - https://updates.atomicorp.com/installers/atomic | sudo bash
Once the repository is set up, update the package lists:
sudo apt update
And install OSSEC.
sudo apt install ossec-hids-server
Once the package and dependancies are installed, stop the service until it can be fully configured.
sudo systemctl stop ossec
Configure OSSEC
Most of the configuration pieces for OSSEC are hidden from normal linux users, so for the rest of this seciton we’ll have to run as an interactive root user:
sudo -i
cd /var/ossec
The main configuration file is located at /var/ossec/etc/ossec.conf
and is structured as XML. The first part to change is the email notification settings inside the ‘global’ section. The notable piece is that ossec itself is not sending email directly - instead, it’s handing it off to the local Postfix relay server on localhost.
<global>
<email_notification>yes</email_notification>
<email_to>name@example.com</email_to>
<smtp_server>localhost</smtp_server>
<email_from>ossec@mail.example.com</email_from>
<email_maxperhour>6</email_maxperhour>
</global>
If desired, you can whitelist your own IPv4 address as well. This will prevent being locked out of the system if you do something dumb.
<global>
<white_list>203.0.113.12</white_list>
</global>
Next, modify the email alert threshold if desired. The default level is ‘7’ - Which does give a lot of useful albeit slightly spammy notifications about integrity changes. If this isn’t desired it can be increased. In my case, I prefer to set up unattended-upgrades on my cloud servers so that they stay up to date on security patches. This can generate lots of unnecessary email alerts that are just annoying. Like everything security related, there are tradeoffs.
<alerts>
<log_alert_level>1</log_alert_level>
<email_alert_level>9</email_alert_level>
</alerts>
Active Responses
Active-response is a built in system that will take action to block a detected attack. In a base OSSEC install it is configured reasonably - however once we add network alerts it can quickly start to block legitimate traffic. So, the default intervention level will be increased from 7 to 9. I also suggest decreasing the ‘ban time’ from the default (30 minutes) to 5 minutes until all the false-positives can be resolved.
<!-- Active Response Config -->
<active-response>
<command>host-deny</command>
<location>local</location>
<level>9</level>
<timeout>300</timeout>
</active-response>
<active-response>
<command>firewall-drop</command>
<location>local</location>
<level>9</level>
<timeout>300</timeout>
</active-response>
Full documentation for this feature is available in the ossec manual.
Integrate Suricata logs into OSSEC
Finally, the most important piece of the puzzle is to direct OSSEC to read the Suricata alert log. This gives the monitoring system full visibility into both OS behaviour, and incoming/outgoing network activity.
<localfile>
<log_format>snort-fast</log_format>
<location>/var/log/suricata/fast.log</location>
</localfile>
Once complete, the OSSEC service can be started.
sudo systemctl start ossec
The log file, /var/ossec/logs/ossec.log
can be checked for errors after startup. If it’s successful, there should be an email sent within a minute of startup.
OSSEC HIDS Notification.
2020 May 16 02:17:16
Received From: my-cool-server->ossec-monitord
Rule: 502 fired (level 3) -> "Ossec server started."
Portion of the log(s):
ossec: Ossec started.
Create Alert Rules
After the service iteslf is configured, there are a few tweaks to make.
Without adding custom rules, OSSEC’s understanding of Network IDS alerts is fairly basic, only generating a level 8 alert the first time a ‘new’ Suricata/Snort alert is fired. Fortunately, we can add some rules to help make sense of the Suricata output. Remember, suricata alerts range from 1-3 with 1 being most severe, and ossec alerts range from 0-15 with 15 being most severe.
Rule ID | OSSEC Level | Suricata Level | Alert Count |
---|---|---|---|
3000001 | 7 | 2 | 1 |
3000002 | 8 | 2 | 5 |
3000003 | 9 | 2 | 10 |
3000004 | 10 | 2 | 20 |
3000005 | 11 | 2 | 50 |
3000011 | 10 | 1 | 1 |
3000012 | 11 | 1 | 5 |
3000013 | 12 | 1 | 10 |
3000014 | 13 | 1 | 20 |
3000015 | 14 | 1 | 50 |
These rules can be added to the /var/ossec/rules/local_rules.xml
file.
Most important is to establish OSSEC alerts for the higher severity Suricata alerts:
<group name="snort-fast,">
<!-- Alert if a level 1 threat is identified -->
<rule id="300011" level="10">
<category>ids</category>
<match>[Priority: 1]</match>
<description>Suricata level 1 alert</description>
</rule>
<!-- Alert if multiple level 1 threats are identified -->
<rule id="300012" level="11" frequency="5" timeframe="120" ignore="90">
<if_matched_sid>300011</if_matched_sid>
<same_source_ip />
<description>Many high-severity Suricata alerts</description>
</rule>
<rule id="300013" level="12" frequency="10" timeframe="120" ignore="90">
<if_matched_sid>300011</if_matched_sid>
<same_source_ip />
<description>Several high-severity Suricata alerts</description>
</rule>
<rule id="300014" level="13" frequency="20" timeframe="120" ignore="90">
<if_matched_sid>300011</if_matched_sid>
<same_source_ip />
<description>Numerous high-severity Suricata alerts</description>
</rule>
<rule id="3000015" level="14" frequency="50" timeframe="120" ignore="90">
<if_matched_sid>300011</if_matched_sid>
<same_source_ip />
<description>Multiple high-severity Suricata alerts</description>
</rule>
</group>
Then additional rules can be created to deal with less-severe Suricata alerts:
<group name="snort-fast,">
<!-- Alert if a level 2 threat is identified -->
<rule id="300001" level="7">
<category>ids</category>
<match>[Priority: 2]</match>
<description>Suricata level 2 alert</description>
</rule>
<!-- Alert if multiple level 2 threats are identified -->
<rule id="300002" level="8" frequency="5" timeframe="120" ignore="90">
<if_matched_sid>300001</if_matched_sid>
<same_source_ip />
<description>Many medium-severity Suricata alerts</description>
</rule>
<rule id="300003" level="9" frequency="10" timeframe="120" ignore="90">
<if_matched_sid>300001</if_matched_sid>
<same_source_ip />
<description>Several medium-severity Suricata alerts</description>
</rule>
<rule id="300004" level="10" frequency="20" timeframe="120" ignore="90">
<if_matched_sid>300001</if_matched_sid>
<same_source_ip />
<description>Numerous medium-severity Suricata alerts</description>
</rule>
<rule id="300005" level="11" frequency="50" timeframe="120" ignore="90">
<if_matched_sid>300001</if_matched_sid>
<same_source_ip />
<description>Multiple medium-severity Suricata alerts</description>
</rule>
</group>
Finally, reload the service for the rules to update.
/var/ossec/bin/ossec_control reload
Check for errors in the log file - /var/ossec/logs/ossec.log
Test Alerts
Once set up, a few tests can be performed on the system. The most likely to create an alert is to simply nmap the system:
nmap -A 198.51.100.44
Within a second or two there will be many alerts generated in the suricata log file. Then, OSSEC will pick these up and add them to the alerts spool. Next these alerts will be aggregated and counted which should trigger the higher-severity events. And, ideally this will generate an email alert like this one:
OSSEC HIDS Notification.
2020 May 14 22:10:18
Received From: my-cool-server->/var/log/suricata/fast.log
Rule: 300012 fired (level 11) -> "Many high-severity Suricata alerts"
Src IP: 192.0.2.241
Dst IP: 198.51.100.44
Portion of the log(s):
05/14/2020-22:10:17.391373 [**] [1:2024364:3] ET SCAN Possible Nmap User-Agent Observed [**] [Classification: Web Application Attack] [Priority: 1] {TCP} 192.0.2.241:35004 -> 198.51.100.44:80
....
--END OF NOTIFICATION
If you’re lucky, this will also kick in an active response. When this happens, OSSEC will add a firewall block to IPTables preventing any communication with the ‘offending’ endpoint.
Real Alerts
After a couple days of being exposed to the internet, it’s quite likely that one or two bots will try to hack your server. So, given some time there should be an email or two like this:
OSSEC HIDS Notification.
2020 May 17 20:16:34
Received From: my-cool-server->/var/log/suricata/fast.log
Rule: 300011 fired (level 10) -> "Suricata level 1 alert"
Src IP: 192.0.2.241
Dst IP: 198.51.100.44
Portion of the log(s):
05/17/2020-20:16:33.926136 [**] [1:2029790:3] ET SCAN ELF/Mirai Variant User-Agent (Inbound) [**] [Classification: Attempted Administrator Privilege Gain] [Priority: 1] {TCP} 192.0.2.241:47586 -> 198.51.100.44:80
--END OF NOTIFICATION
This means that a real live Marai botnet node tried to assimilate my box!
Since it generated a high severity network alert, the intrusion was immediately blocked and the offending IP banned. You can find this in the log file:
/var/ossec/logs/active-responses.log
Sun May 17 21:11:31 UTC 2020 /var/ossec/active-response/bin/firewall-drop.sh add - 192.0.2.241 1589749891.52882 300001
This can also be verified by checking IPtables rules:
sudo iptables -L -v
Conclusion
After all the pieces are set up, this becomes a fairly low maintenance system. Of course, there will be incidents where the IDS/IPS blocks some legitimate traffic. But that’s part of life in the modern security landscape.
With high profile hacks and cyberattacks more and more frequently, it’s all of our responsibility to do our best to secure our servers to the best of our abilities.
If you have any suggestions, feel free to reach out. Quarantine is killing me!