Kamis, 25 Desember 2008

OSSEC and Pf on FreeBSD to Limit SSH Brute Forcing

Disclaimer: This post is neither original nor particularly illuminating. It does, however, document how I configured software on systems I administer. Therefore, I post it here mainly for my own future reference, but know it might be useful to someone else.

If you run OpenSSH on any Internet-facing server, you're likely to see entries like these every day:


r200a:/root# bzcat /var/log/auth.log.0.bz2 | head -n 5 | grep -v turned
Dec 23 20:00:02 r200a sshd[33320]: Invalid user httpd from 87.106.142.217
Dec 23 20:00:03 r200a sshd[33322]: Invalid user dima from 87.106.142.217
Dec 23 20:00:04 r200a sshd[33324]: Invalid user bane from 87.106.142.217
Dec 23 20:00:05 r200a sshd[33326]: Invalid user juan from 87.106.142.217

I like to run OSSEC on servers as a means to monitor and analyze log files. OSSEC would report that activity as follows.

2008 Dec 23 20:00:44 Rule Id: 5712 level: 10
Location: (r200a) 172.16.2.1->/var/log/auth.log
Src IP: 87.106.142.217
SSHD brute force trying to get access to the system.
...edited...
Dec 23 20:00:02 r200a sshd[33320]: Invalid user httpd from 87.106.142.217

In the setup for this post I am running an OSSEC agent on an Internet-facing gateway with an internal IP of 172.16.2.1 (r200a). My OSSEC server is 192.168.2.13 (macmini). My simulated attack box is 192.168.2.101 (debian40r0).

The first thing I need is a program to brute force SSH on 172.16.2.1. I wanted something simple so I installed sshbrute.py by d3hydr8.

tws@debian40r0:~$ wget http://www.darkc0de.com/bruteforce/sshbrute.py
...edited...
tws@debian40r0:~$ su -
Password:
debian40r0:~# apt-get install python-pexpect
...edited...
debian40r0:~# logout
tws@debian40r0:~$ python sshbrute.py

d3hydr8:darkc0de.com sshBrute v1.0
----------------------------------------

Usage : ./sshbrute.py
Eg: ./sshbrute.py 198.162.1.1 root words.txt

I decided to use /etc/dictionaries-common/words for my wordlist because this is only a test and I don't really care if I can brute force my own user accounts in this scenario. I just want to be sure I can configure OSSEC to tell Pf to block the offending source IP for a period of time.

Now I need to configure Pf on the FreeBSD gateway to ensure OSSEC can work with it. I make certain OSSEC changes to /etc/pf.conf.

ext_if = "bge0"
int_if = "bge1"
localnet = $int_if:network
# needed by OSSEC
table <ossec_fwtable> persist
...now come some rules...
# needed by OSSEC
block in quick from <ossec_fwtable> to any
block out quick from any to <ossec_fwtable>

To verify the OSSEC firewall table is currently blank I run this:

r200a:/root# pfctl -t ossec_fwtable -T show
No ALTQ support in kernel
ALTQ related functions disabled

The next step is to configure my OSSEC server to take an action when an offending IP address takes a sufficiently hostile step against a host running an OSSEC agent. This took a second thought, because I am configuring the OSSEC server to tell the OSSEC agent to take a blocking action using the firewall-deny.sh script on the host running the OSSEC agent reporting the SSH brute forcing. That isn't the only way to configure this option, but it works for me. The block will persist for 600 seconds or 10 minutes.

<command>
<name>firewall-drop</name>
<executable>firewall-drop.sh</executable>
<expect>srcip</expect>
<timeout_allowed>yes</timeout_allowed>
</command>

<!-- Active Response Config -->

<active-response>
<!-- Firewall Drop response. Block the IP for
- 600 seconds on the firewall (iptables,
- ipfilter, etc).
-->
<command>firewall-drop</command>
<location>local</location>
<level>10</level>
<timeout>600</timeout>
</active-response>
</ossec_config>

I restart OSSEC on both client and server using /var/ossec/bin/ossec-control restart.

Now it's show time; I run the brute force from the attack box.

tws@debian40r0:~$ python sshbrute.py 172.16.2.1 root /etc/dictionaries-common/words

d3hydr8:darkc0de.com sshBrute v1.0
----------------------------------------
[+] Loaded: 98569 words
[+] Server: 172.16.2.1
[+] User: root
[+] BruteForcing...
Trying:
Trying: A
Trying: A's
Trying: AOL
Trying: AOL's
Trying: Aachen
Trying: Aachen's
Trying: Aaliyah
Trying: Aaliyah's
...stalled...

Checking /var/ossec/logs/alerts/alerts.log on the OSSEC server shows messages like this:

** Alert 1230260722.392334: - syslog,sshd,authentication_failed,
2008 Dec 25 22:05:22 (r200a) 172.16.2.1->/var/log/messages
Rule: 5716 (level 5) -> 'SSHD authentication failed.'
Src IP: 192.168.2.101
User: root
Dec 25 22:05:19 r200a sshd[49425]: error: PAM: authentication error
for root from 192.168.2.101

Then I see OSSEC's report of a level 10 event.

** Alert 1230260730.394490: mail - syslog,sshd,authentication_failures,
2008 Dec 25 22:05:30 (r200a) 172.16.2.1->/var/log/messages
Rule: 5720 (level 10) -> 'Multiple SSHD authentication failures.'
Src IP: 192.168.2.101
User: root
Dec 25 22:05:25 r200a sshd[49450]: error: PAM: authentication error
for root from 192.168.2.101
Dec 25 22:05:24 r200a sshd[49445]: error: PAM: authentication error
for root from 192.168.2.101
...truncated...

A look at the active-responses.log on the gateway shows a new rule adding that blocks the offending IP.

r200a:/root# tail -n 1 /var/ossec/logs/active-responses.log
Thu Dec 25 22:05:28 EST 2008 /var/ossec/active-response/bin/firewall-drop.sh
add - 192.168.2.101 1230260730.395394 5720

Checking Pf we see the new rule.

r200a:/root# pfctl -t ossec_fwtable -T show
No ALTQ support in kernel
ALTQ related functions disabled
192.168.2.101

If I want to manually remove the block I can do this:

r200a:/root# /var/ossec/active-response/bin/firewall-drop.sh
delete - 192.168.2.101
r200a:/root# pfctl -t ossec_fwtable -T show
No ALTQ support in kernel
ALTQ related functions disabled

That worked just as I hoped. Now I have a way to limit scanners who hammer at SSH on port 22. Yes, I could take a lot of other actions, but this is what I wanted to document.


Richard Bejtlich is teaching new classes in DC and Europe in 2009. Register by 1 Jan and 1 Feb, respectively, for the best rates.

0 komentar:

Posting Komentar