Management, compliance & auditing

OSSEC

Dejan Lukan
January 2, 2014 by
Dejan Lukan

Introduction

In this article we'll present the open source host-based intrusion detection system, which is needed if we would like to detect host-based attacks on our computer. First of all, we should emphasize that OSSEC is supported on most platforms including Linux, MAC, Windows, Solaris, HP-UX, ESX, etc and is completely open source. OSSEC supports both kinds of monitoring: agent-based and agentless, which is needed in case we're not allowed to install the agent on some systems, like the network switch or router.

It supports the following features [1]:

  • File Integrity Checking: checks whether something suspicious was written to the file and reports it.
  • Log Analysis: uses the syslog log data already available on a computer and analyzes it, trying to detect some anomaly.
  • Rootkit Detection: is able to detect the presence of rootkits.
  • Policy Monitoring: checks whether all the components in the system adhere to the security policy.
  • Active Response: is able to actively respond to the malicious threat, so we can eliminate it as soon as possible.

All the data of all the agents is collected by the OSSEC manager, which is a central server that receives alerts from every configured agent. Therefore we need to remember that we need to install the OSSEC Manager on a central location where all the logs will be analyzed and OSSEC Agent on every server or client system that we would like to monitor. When the manager needs the information, it will contact the agent over an encrypted channel and pull the information from it and store it locally in its own database.

Installing the OSSEC Manager

Let's first install the OSSEC manager from [2], where we can choose between Beta, Latest Stable and Previous Releases. We will select the latest stable release and choose the "Server 2.7 – Linux/BSD" archive as seen on the picture below.

After downloading and unpacking the archive, we need to run the ./install.sh script, which is an installation Bash script that we can use to install OSSEC. After running the script, we have to choose a language that we would like to use, which is the default English in our case. If we run the script as normal user, it will tell us that we need to be root to execute it, which is presented below. Actually I wanted to include this picture just to show you guys my recent accomplishment, the UTF-8 characters in my terminal emulator. Notice how the Japanese characters are actually being written to the console?

Since we can't run the installation script as a normal user, we have to become root first and then execute the "./install.sh" command again. The installation procedure will first ask us which OSSEC component we would like to install: server, agent, local or hybrid? We'll input the 'server' string, since we want to install the OSSEC manager onto the server. After that we will also have a chance to select the directory where the OSSEC will be installed, which is /var/ossec/ by default.

Then we would have to choose whether we would want email notifications sent to our email address on every triggered alert and choose the features we would like to enable; this can be seen on the picture below.

Once we've answered all the questions, the installation script will compile the OSSEC manager. The installation is very good, since it also detects the version of Linux operation system we're running, adds appropriate init script and adds it to the default runlevel to be started when booting a computer. The configuration file is stored at /var/ossec/etc/ossec.conf, while the ossec-control binary is at /var/ossec/bin/ossec-control and can be used to start/stop ossec:

[python]

# /var/ossec/bin/ossec-control start

# /var/ossec/bin/ossec-control stop

[/python]

At the end of the installation ossec tells us that in order to connect the agent and server together, we need to add the agent to the server by running /var/ossec/bin/manage_agents program. Below we've run the manage_agents program on the server, which gives us 5 options to choose from: Add, Extract, List, Remove and Quit.

[python]
# /var/ossec/bin/manage_agents

****************************************

* OSSEC HIDS v2.7.1 Agent manager. *

* The following options are available: *

****************************************

(A)dd an agent (A).

(E)xtract key for an agent (E).

(L)ist already added agents (L).

(R)emove an agent (R).

(Q)uit.

Choose your action: A,E,L,R or Q:
[/python]

At this point we want to add an OSSEC agent, which is why we must type in the 'A' letter. After that we need to enter the name of the agent, it's IP and an ID. Once the agent has been added, we can use the 'E' letter to extract the agent key, which we'll need later on.

[python]

Agent key information for '001' is:

MDAyIHRlc3QgMTkyLjE2OC4xLjIgMWM1ODMxYzBjZDRhYjgxMzc5NTQ5N2I5YTQ5OGVlN2VjZTYyMjViNDgxNDkzYWEyODMwOGZhZTI4NmIyODg3Zg==

** Press ENTER to return to the main menu
[/python]

We need to copy that key into pastebin, because we'll need it later. Then we can quit the manage_agent command by issuing the 'Q' command. After that we can use the netstat command to confirm that the OSSEC manager is listening on port 1514 as can be seen below. Notice that it's listening on UDP port and not TCP.

[python]

# netstat -luntp | grep ossec

udp 0 0 0.0.0.0:1514 0.0.0.0:* 18173/ossec-remoted

[/python]

If we specified wrong mail settings during the installation we can always change them in the top of the /var/ossec/etc/ossec.conf configuration file, which holds the following global settings.

[python]


yes

name.surname@gmail.com

localhost

ossecm@monitor


[/python]

Notice that the <smtp_server> specifies the IP/Hostname of the SMTP server, which is localhost in this case. This means that we have a SMTP server running locally on port 25, but we could just as easily have specified another SMTP server. If we would like to test whether the local SMTP server works and OSSEC will be able to send emails with this command:

[python]

# echo "Test Body" | mail -s "Test Subject" name.surname@gmail.com

[/python]

When we login to the name.surname Gmail inbox, the email should be there. If that is the case, then we don't have to worry about OSSEC not being able to send emails when something is wrong.

Installing the OSSEC Agent

At first we should install the build-essential package, which provides the compiler gcc/g++ and other binaries that are used when compiling OSSEC.

[python]

# apt-get install build-essential

[/python]

Next, we need to install OSSEC Agent by again going to the [2] web page and downloading the "Server – Linux/BSD" as shown below.

But when running the install.sh Bash script, we shouldn't select the 'server' installation type, we must choose 'agent'. We must basically go through the same steps as when installing the manager, but we must also enter the IP of the manager; we can choose between enabling the integrity check, rootkit detection and whether we would like a active response or not. At the end, the make script will compile the agent to the /var/ossec/ directory.

At that time we must run the /var/ossec/bin/manage_agents tool to import the agent key to enable that the agent can authenticate to the server successfully. Below, we can see that the manage_agents has offered Import and Quit options to us.

[python]
# /var/ossec/bin/manage_agents

****************************************

* OSSEC HIDS v2.7 Agent manager. *

* The following options are available: *

****************************************

(I)mport key from the server (I).

(Q)uit.

Choose your action: I or Q:

[/python]

We must choose import option by specifying the letter 'I' and then input the previously exported key. After the key has been added, we can quit the manage_agents program by issuing the 'Q' command.

We should also check whether the agent could reach the server's 1514 UDP port. We can simply scan an UDP port 1514 with an Nmap scanner as seen below:

[python]
# nmap 192.168.1.2 -p 1514 -sU

Starting Nmap 6.25 ( http://nmap.org ) at 2013-12-07 17:58 CET

Nmap scan report for monitor (192.168.1.2)

Host is up (0.0028s latency).

PORT STATE SERVICE

1514/udp open|filtered fujitsu-dtcns

Nmap done: 1 IP address (1 host up) scanned in 0.47 seconds
[/python]

Notice that nmap couldn't decide whether the port is open or filtered; this is always the case when scanning the UDP port, but most often it indicates that the port is open. If we use the same command to scan for port 1515, which is clearly not open, we can confirm that it's reported as closed:

[python]
# nmap 192.168.1.2 -p 1515 -sU

Starting Nmap 6.25 ( http://nmap.org ) at 2013-12-07 17:58 CET

Nmap scan report for monitor (192.168.1.2)

Host is up (0.0024s latency).

PORT STATE SERVICE

1515/udp closed ifor-protocol

Nmap done: 1 IP address (1 host up) scanned in 0.20 seconds
[/python]

We can also test the active clients by executing the following command on the server. We can see that only the server is Active and also Local, but there are no clients listed. If a client is connected there would have to be an additional line with the client ID, IP and keyword Active.

[python]
# /var/ossec/bin/agent_control -lc

OSSEC HIDS agent_control. List of available agents:

ID: 000, Name: myossec (server), IP: 127.0.0.1, Active/Local

[/python]

The next step thing that we can do is take a look into the OSSEC log /var/ossec/logs/ossec.log, which clearly states that the message from our client is not allowed.

[python]

# tail -F /var/ossec/logs/ossec.log

2013/12/07 18:10:53 ossec-remoted(1213): WARN: Message from 192.168.1.4 not allowed.

[/python]

At this time I realized that I've entered the wrong IP of 192.168.1.2 and not 192.168.1.4, which is the actual IP of my client. In order to solve the issue I edited the /var/ossec/etc/client.keys file and changed the IP of the client, but at that time the authentication string also changed, so I had to run manage_agents export the key of the client again. On the client I ran /var/ossec/bin/manage_agents to import the new key and restarted the ossec.

At that time the ossec.log reported the following:

[python]

2013/12/07 18:24:20 ossec-remoted(1409): INFO: Authentication file changed. Updating.

2013/12/07 18:24:21 ossec-remoted(1410): INFO: Reading authentication keys file.

2013/12/07 18:24:21 ossec-remoted: INFO: No previous counter available for 'myclient'.

2013/12/07 18:24:21 ossec-remoted: INFO: Assigning counter for agent myclient: '0:0'.

2013/12/07 18:24:21 ossec-remoted: INFO: No previous sender counter.

2013/12/07 18:24:21 ossec-remoted: INFO: Assigning sender counter: 0:0

[/python]

This clearly states that the client is now connected and a new counters are created for it. We can also verify whether the client is active by using agent_control command as seen below, where it clearly states that myclient is now active.

[python]
# /var/ossec/bin/agent_control -lc

OSSEC HIDS agent_control. List of available agents:

ID: 000, Name: monitor (server), IP: 127.0.0.1, Active/Local

ID: 001, Name: myclient, IP: 192.168.1.4, Active

[/python]

At that point we can be sure that the client-server communication is working and OSSEC is set-up properly. Now we can test the OSSEC by first opening the /var/ossec/logs/alerts/alerts.log file on the server with the tail command, which will enable us to see all the triggered alerts. Then, we need to authenticate to root with the wrong password on the client, so an alert is triggered. When that happens the following will be printed to the alerts.log:

[python]

# tail -f /var/ossec/logs/alerts/alerts.log

** Alert 1386441223.31369: - pam,syslog,authentication_failed,

2013 Dec 07 19:33:43 (myuser) 192.168.1.4->/var/log/auth.log

Rule: 5503 (level 5) -> 'User login failed.'

Dec 7 19:31:38 myuser su[29739]: pam_unix(su:auth): authentication failure; logname= uid=1000 euid=0 tty=/dev/pts/3 ruser=myuser rhost= user=root

** Alert 1386441225.31691: - syslog,access_control,authentication_failed,

2013 Dec 07 19:33:45 (myuser) 192.168.1.4->/var/log/auth.log

Rule: 2501 (level 5) -> 'User authentication failure.'

Dec 7 19:31:40 myuser su[29739]: pam_authenticate: Authentication failure

** Alert 1386441225.31960: - syslog, su,authentication_failed,

2013 Dec 07 19:33:45 (myuser) 192.168.1.4->/var/log/auth.log

Rule: 5301 (level 5) -> 'User missed the password to change UID (user id).'

Dec 7 19:31:40 myuser su[29739]: FAILED su for root by myuser

** Alert 1386441225.32228: mail - syslog, su,authentication_failed,

2013 Dec 07 19:33:45 (myuser) 192.168.1.4->/var/log/auth.log

Rule: 5302 (level 9) -> 'User missed the password to change UID to root.'

User: root

Dec 7 19:31:40 myuser su[29739]: - /dev/pts/3 myuser:root

[/python]

We can see that the user myuser failed to authenticate to root account by using the su command. At that point no mail will be sent to the server, since there was only one invalid login attempt, but the threshold is much higher than that; OSSEC is trying to detect bruteforce login attempts, so issuing an email alert every time a user fails to login would really spam our inbox folder.

If we open the file /var/ossec/rules/syslog_rules.xml, we can see the following written in it: this is the group of rules for syslog/su. Note that all OSSEC rules use the id and level argument, where the id is the identification number of the rule and the level identifies the severity of the rule. The noalert option means that the rule will never trigger an alert.

[python]



su

Initial grouping for su messages.


5300

authentication failure; |failed|BAD su|^-| -

User missed the password to change UID (user id).

authentication_failed,


5301

^root

User missed the password to change UID to root.

authentication_failed,


[/python]

We must concentrate our efforts on the rule 5302, which is of level 9, which means that it isn't a big deal when we miss a password to change to root uid. There is also the if_sid, where the rule 5301 is specified and acts as a parent to the current rule: this means that the rule 5302 will be checked only after the rule 5301 has been triggered. The rule also has a description, which describes it in detail and group that groups the rule into group, so we can easily find it later.

In the /var/ossec/etc/ossec.conf file, we also have the following directives, which specify that we should log all alerts on level 1 and always send an email when an alert of level 7 occurs.

[python]


1

7


[/python]

There's also one more tip we need to mention: if we have a client that has a dynamic IP, which changes often, we can't specify the static IP when running manage_agents tool. Instead we can add an IP with a netmask like 192.168.1.0/24. If we have already added the client, we can simply edit the /var/ossec/etc/client.keys file and change the IP address into an IP address with a netmask and restart ossec. After that we must also import the new key into the client and restart OSSEC. After that the client should be able to authenticate to the server by using any IP address in the specified IP range.

Conclusion

In this article we've taken a look at the very basics of OSSEC and how we can go about installing an OSSEC server as well as client. We also connected the client to the server where we had some difficulties, but we've learned how to view the log messages and solve the problems.

References:

[1] OSSEC Features, http://www.ossec.net/?page_id=165.

[2] OSSEC Downloads, http://www.ossec.net/?page_id=19.

Dejan Lukan
Dejan Lukan

Dejan Lukan is a security researcher for InfoSec Institute and penetration tester from Slovenia. He is very interested in finding new bugs in real world software products with source code analysis, fuzzing and reverse engineering. He also has a great passion for developing his own simple scripts for security related problems and learning about new hacking techniques. He knows a great deal about programming languages, as he can write in couple of dozen of them. His passion is also Antivirus bypassing techniques, malware research and operating systems, mainly Linux, Windows and BSD. He also has his own blog available here: http://www.proteansec.com/.