Granular OSSEC Emails

Occasionally I see questions on the OSSEC mailing list on how to send a bunch of alerts only to a specific email address. An example for a typical use case would be different departments responsible for different groups of servers and having alerts only go to them. OSSEC has a few options for sending Alerts to specific email addresses, but it only adds those email addresses to the alert (meaning it always goes to the global email address). Sometimes this isn’t desirable.

A workaround is setting the global email recipient to a blackhole email address (something that is aliased to /dev/null on the mail server) and only using the granular settings for delivering mail.

You can then use attributes like the rule ID, group names, or event locations to split up alerts to different recipients. The downside is that by doing this, you will miss alerts with  <options>alert_by_email</options> and a low level, unless you add a few granular email alerts. Rule 1002 (catch-all $BAD_WORDS) is a good candidate you will want to keep on receiving. Rules 501-504 (OSSEC agent/master status alerts) could also be interesting; either add an <email_alert>  for each rule individually, or overwrite the rules adding  <group>ossec,</group> to then, so you can add one <email_alert>  for the group of rules.

We use this system pretty extensively assigning alerts to email groups by <event_location>  and/or <group>

An example for the email block could look like this:

 

A script to diff files/directories on two different servers

Ok,  short one today. This is a straightforward script that simplifies comparing directories on different servers. There is no magic in it, it just rsyncs the directories to a local temp directory and runs diff against them (then deletes the directory afterwards). Mainly intended for config files, I wouldn’t recommend trying to diff gigabytes of binaries with it.

 

Renewing “Let’s Encrypt” SSL certificates

Let’s Encrypt provides free DV SSL certificates for everyone and is now in the open beta phase. I’m not going to go into the details of which of the clients are best, since that depends entirely on your use case (I use acme-tiny and a rule in varnish to intercept all calls to /.well-known/acme-challenge/).

Since the certificates are only valid for 90 days, I often see people suggesting to just renew them via cronjob every 2 months. I find this to be really awful advice, if that renewal fails for any reasons (network problems, local problems, problems with let’s encrypt) the next renewal is a month after the certificate expired. It is also pretty inflexible (what if you would rather prefer to renew them after 80 days).

I use openssl to check daily how long the certificate is still valid, and if a threshold has been reached it tries to renew the certificate (I believe the official client has this functionality too). And if the certificate isn’t renewed by a 2nd threshold, it sends an email altering the admin of the problem (for manually intervening and fixing whatever went wrong).

At the end of this posting I’ll add the complete script, but the quickest way to check how long a certificate is still valid is to use openssl x509 -in -checkend. It will return 0 if the file is still valid in x seconds, and 1 if the certificate doesn’t exist or if the certificate will be expired by then. Just multiply the number of days by 86400 and check if the certificate is still valid:

The openssl binary has a few nice options for looking at certificates (both local files and remotely connecting to a server and looking at the provided certificate)
Show information about a local certificate file: openssl x509 -text -noout -in
Connect to a remote server and display the certificate provided: openssl s_client -showcerts -servername foo.bar -connect IP:PORT | openssl x509 -text -noout  (servername foo.bar is only required if you are connecting to a server and need to use SNI to request a cert for a specific domain, i.e. a webserver providing multiple domains on port 443 via SNI. It can of course be omitted if you don’t need it.)

This is the full script I use for checking and renewing certs. It basically just loops through a list of domains, checks if any of the date thresholds are met and then renews certificates/send emails.

Convert configuration files to ansible templates

I’ve been playing around with ansible a lot lately, and I noticed that while changing stuff from “installed and configured manually” to “installed and configured by ansible” I was running into quite a few configuration files that needed to be manually turned into templates. It can be quite tedious to replace values in a configuration file with placeholders and put all those placeholders in a .yml file with default values.
Automating this is something I would have typically done in perl, but since I wanted to learn more about using regex in bash I decided to have a go at it in bash using regex and ${BASH_REMATCH}

The script takes a configuration file and spits out an ansible template, as well as the variable definitions you will need to add to your defaults/main.yml or vars/main.yml

The whole script is a bit to long to post here, but the interesting part is:

(You can download the full script here ansible_template.sh).

You can use regular expressions in a [[ ]] with =~ (e.g. if [[ “boot” =~ ^b ]]), and you can access the result of the regular expression by using ( ) to mark what parts of the result to store and access them via $BASH_REMATCH (comparable to how you would do it for other languages). Here I am parsing out anything that looks like a key=value from the configfile (with multiple possible separators) and storing the results in BASH_REMATCH[1] and BASH_REMATCH[2]

Usage of the script is pretty straightforward. you give it a prefix for the variable names (so you don’t end up with multiple roles all using a common variable name like “port”), and either a local or remote file to work with, and it spits out something like this:

There a tons of different configuration file formats out there so this script won’t work perfectly 100% of the time, but it does do quite well and reduces the manually copy&pasting to a minimum.

How to prevent changes to a tag via svn hook

A colleague of mine recently asked if it was possible to keep people from committing changes to tags in subversion. I thought “Hey, that should be easy to do via the pre-commit hook. I bet someone already made one that I can just test and use“. Either my google-fu failed me or the request wasn’t as common as I had anticipated, because surprisingly I couldn’t find any hooks that truly accomplish blocking changes to a tag (probably right after I post this someone will say “hey, why didn’t you look $here, it is exactly what you wanted“).

I found people looking for such a feature, and I found a hook or two that kinda did what I needed (the best I could find was a hook that just blocked updates to /tags/* but it allowed deletes, adds and property changes), but none that really blocked all changes to tags. So I decided to just make my own configurable svn hook. You can tell it what to allow and what to block, and which directory to work on (since not everyone has the tags in their base directory of the repository).

You may have to change the SVNLOOK variable depending on where your svnlook binary is installed.

 

Native tcp/udp sockets in bash cheatsheet

Bash has a nifty feature to open tcp and udp connections and read/write data to that connection. The Advanced Bash Scripting Guide and the bash man page offers some information and examples, and google has some odd examples, but all in all there isn’t much variety of information on the internet on the topic. This feature is enabled in Bash at compile time with the flag –enable-net-redirections

It works by assigning a connection to a file descriptor with exec. Protocol must be udp or tcp, hostname must be either an IP or a FQDN. Use any free file-descriptor (3 or higher usually).

Use &- to close the connection instead of leaving it in the CLOSE_WAIT status.

Basic Example:

You may have noticed that the cat will hang around a while after delivering the content. As long as the connection is established it will sit there and wait for data, which can be quite a while depending on the daemon on the other end. If you want to avoid having to wait, kill or ctrl-c the cat  you can use read with an input timeout.

In the example if read has to wait longer than 2 seconds (-t 2) it will abort reading from the network connection.

If you only want to read a single line you can use head:

Although this will have the same timeout problems as cat if there is no more data but the connection is still established, it is useful and quick if you know exactly what kind of result you are expecting.

You don’t have to read the response right away, it will be buffered until you get around to accessing it (even if the other end terminates the connection).

What was and wasn’t fixed in bash after the Shellshock vulnerability (CVE-2014-6271)

By now there are a few websites/blog posts online that explain CVE-2014-6271 (code being executed that was inserted after the function definition) and  CVE-2014-7169 (parser error that also led to code being executed). Both CVEs have been patched. Check out “Quick notes about the bash bug, its impact, and the fixes so far“, “Shellshock proof of concept – Reverse shell“, or “Everything you need to know about the Shellshock Bash bug” if you want more information about the details and how CVE-2014-6271 worked.

Most websites focus on the remote exploitability of the vulnerability via CGI in web servers (understandably since this is the most dangerous aspect since how request headers are passed to scripts), and it didn’t take long after the announcement on the oss-security mailing list for requests starting to hit my webservers trying to exploit the vulnerability (from what I saw either people checking “how many servers does this really affect” or the more malicious “add your server to my DDoS botnet”).

What I would like to focus on is the functionality of exporting function definitions that has been drawn into the spotlight by CVE-2014-6271. You can define a function and make it accessible to the script/child shell that you invoke. This may sound really nifty (and it is … to a certain degree). The problem is that the script has no control over what functions are being imposed upon it. It is therefore possible to override any existing command or function, even builtin functions. No matter how hard you try to keep a sane environment within your script, anyone will be able to manipulate it from the outside (e.g. by overriding unset, set, …).

A small example script that initializes a variable, prints some output and then exits.

If we execute the script we get the following output:

Looks good, the if condition will never be true. Unless of course if we start overriding functions …

Sacrificed the trap function to set i=10. Or slightly more elaborate:

When echo is called we delete our function (so subsequent calls go to the original echo, to keep the code intact), execute an echo with whatever arguments were passed, and set i=10.

Obviously this is a simple example and you could override stuff like set, declare, test, …
Another problem is that this also affects binaries that execute a system() that calls a bash script. The following is a compiled simple C binary that uses system() to execute the bash script from the beginning of this posting.

As you see the environment gets passed along to the shell script. And in my opinion this is where it can start to get ugly. There are probably more bash scripts in your $PATH than you are aware of, do a quick
for dir in ${PATH//:/ }; do egrep "^#\!.*bash" ${dir}/* ;done  and have a look for yourself.
If any of these scripts are called by a setuid/setgid binary that doesn’t sanitize and clean up the environment beforehand, you might have a serious problem on your hands.

Obviously if you have a program that is calling any kind of script, it is your job to make sure the environment is in a sane condition. At the same time I feel that having a more robust and secure way to implement exported functions would take away a lot of the pressure on the parent process ensuring sane conditions it may have itself inherited.

The topic is being extensively discussed by security experts and I expect the problem to be addressed shortly. In my opinion it should never be possible to override builtin functions externally (if a script itself wants to override a builtin, that’s fine with me, or have a switch to explicitly allow it). But since any solution will break the feature of exported functions in existing scripts it is a delicate problem to solve.

Downtime, Backups, and IPv6

Sorry for the unexpected downtime that lasted a few days and affected all the services here. One of the hard drives in the raid on my server suddenly showing miserable I/O performance, since the other drive was fine according to tests, SMART and logs I decided to take the slow drive offline to have it replaced. That turned out fatal since the other drive was also kaput and all my virtual machines on that server were now corrupted.

On the bright side the 2nd MX server worked fine and held all the email like it supposed to do until I got the main server back up and running (yaay to “exim -Mvb” to at least be able to read important mails that are in the mail server queue).

Long story short, since these drives have caused me much trouble in the past too, I decided to just get a new server with different hardware and restore everything from backups. Like any sysadmin I have my regular backups and scripts to check that they are working and occasionally test them to ensure I can restore a server from backups, but I’ve never had to really actually restore everything from a backup  on one of my private servers. So when doing so I noticed minor things that aren’t perfect and needed to be changed to make my life easier in the future and decided to share my experience.

Backups. Instead of making one large archive with all the directories backed up (e.g. /etc, /home, /opt, …), split it up into multiple archives of the applications you are backing up (e.g. /etc/apache2, /var/www/). I should have known better since this is common practice at work. It makes your life a lot easier when restoring from a backup if you have one archive with everything in it associated to a specific application, Digging through a backup of /etc and trying to remember all sub-directories needed to get email back up and running was a chore (webinterface, greylisting, spamassassin, exim, dovecot … some of them store data you also want to restore in other parts of the filesystem). You can always tar all the application backups together into one package before uploading it to the backup server if you want.

Use some kind of configuration and/or deployment management software (Puppet, Chef, Ansible, Salt, own scripts, …). Don’t underestimate how relaxing it is to just press a button to get your server(s) back into the defined state you previously had, just drop in the data from the backups (configuration too depending on how you roll) and you are good to go. Getting networking up and running manually took me longer than it should have (VPN networks, routing on the VM host, sysctl settings, NAT, which interfaces are bridged, which are internal, guest network configuration, …), I’ve put that all into Ansible playbooks now so it’s just a press of a button.

IPv6 is still sorely underused in the internet. I always set it up on all my hosts and mainly I see it being used by core services like email servers, dns, package download servers of large distributions, sometimes ntp, that kind of stuff, not so much on normal websites. Ordering extra IPv4 IPs for my guests normally takes an extra day or so until they are assigned to me (and they each cost extra), so I do enjoy having a huge subnet ip IPv6 IPs free of charge to do with as I please. It’s nice to spin up a virtual server, assign it an IPv6 IP and have it online without having to worry about NAT or port forwarding or other stuff you are confronted with when getting a server/services online that reside on an internal IP.
While I like to push people to embrace IPv6 early and get used to it, it is also important to give it the same attention you give IPv4 to make sure that you aren’t opening yourself up to security problems. Make sure you have the same firewall policy for IPv6 as you do for IPv4 and IPv6 brings a few new features with it that IPv4 didn’t have. Unless you explicitly need/use them it is best to shut them off. Below I’ll ad some IPv6 settings you probably want to set per default unless you are explicitly using them.

How to install the latest Nmap for Debian/Ubuntu

A quick & dirty script to download the latest version of nmap (sourcecode) and generate a deb and install it (so that it’s correctly in the package management). Yes, I know this is not much more than a glorified configure && make && checkinstall

Bash snippet, verify ctrl+c

Lately I’ve been working on a pair of more elaborate scripts using ncat and openssl to transfer data between hosts. I’ll get around to posting it eventually, but until then a few small snippets that people may find useful.

Today we will catch ctrl+c and ask the user if he really want’s to terminate the script.

The initialize() and cleanup() are my usual function names I have in every script, making sure general settings and variables are defined and that on exit any tempfiles get deleted.
What has been added was a trap for the INT signal (ctrl+c) which calls the verify_quit() function, giving the user 10 seconds to press ctrl+c again to exit (via cleanup()) or return back to wherever we were in the code. There is one unavoidable caveat, the first ctrl+c will kill whatever the script was doing before it jumps into the verify_quit() function.

Simple “try” function for bash

Made a nice little try() function today for simplifying checking/dealing with  return codes from commands. It uses the function text() I posted earlier to colorfy output: How to easily add colored text output in bash scripts. The function accepts 2 parameters, how it should behave if a problem occurs and the command to be executed: try <silent|warn|fatal> command

silent: save the return status in the global variable command_status
warn: if the command has a return code > 0, print a warning and save the return status in the global variable command_status
fatal: if the command has a return code > 0, print an error and exit

Obviously not as versatile as a python try/except, bu streamlines verifying the command return codes.
Example Usage:

Output
Warning: ‘false‘ failed with return code –1
ls: cannot access doesnotexist: No such file or directory
Error: ‘ls -al doesnotexist‘ failed with return code –2

File: error_handling.sh

Virtualbox to 4.2.12 problems with Ubuntu

After updating Virtualbox to 4.2.12 and updating the guest additions on my Ubuntu 12.10 the guest suddenly started having problems with the graphics driver (X.org wouldn’t start correctly, only starts in “rescue” mode). I did a bit of googling, and it seems other users are also affected (mainly 12.04 and 12.10 Ubuntu), and it seems to affect people who upgraded from virtualbox guest addditions 4.2.10 -> 4.2.12

Here the quick and dirty workaround to the problem: download the 4.2.10 guest additions and use them.

Will need to reboot or make sure the new modules are loaded and restart X afterwards.

Script to start minion in tmux

Minion is a security project from Mozilla (link). It provides a user-friendly web interface to various security scanner tools. There is a webcast demonstrating the software (link).

The software requires a few services to run, and since I like having one script take care of starting everything with the right parameters, I threw together a simple shell script that sets up a tmux session with the services started in windows with the names of the services.

How to break down CIDR subnets in Bash

I was playing around with subnets in bash recently and needed an elegant/easy way to split up a subnet into smaller subnets. First I used 2 functions I found on stackoverflow.com to convert an IP addresse to and from an integer. After that it was just a bit of math in bash to split up any networks too big.
Any network larger than $maxSubnet gets split up.
Here the useful code:

Output of script:

 

How to get the intersecting area of two polygons in MySQL

I was playing around with spatial features of MySQL this weekend and stumbled into a problem where I was looking for the area of two rectangles that overlap.  MySQL provides a function to check if they overlap, but no function to extract the region that overlaps.

I’ve never written a stored routine in MySQL before, so I decided it would be a good exercise to try making one. As you can see the function is pretty straightforward and it assumes you are working with rectangles, but other than that it does what it is supposed to.
You pass the function 2 polygons (e.g. Intersection(a.poly,b.poly)), and it returns the intersecting area as a new polygon.

Example comparing some rectangles in 2 tables using the function:

Result:

 

How to find the fingerprints of public keys in authorized_keys

If you use keys for SSH authentication (and you should) then you have probably run into the situation that the auth.log shows that someone logged in, even which local user was used (e.g. root), but you have no idea which of the keys in ~/.ssh/autorized_keys was used. The first step you can do to see what is going on, is increasing the log level of the SSH daemon:

/etc/ssh/sshd_config

That will spit out the fingerprint of the SSH key used to log in. Example log entry for a successful login:

Now that we have the fingerprint of the ssh key used to login, we will need ssh-keygen to spit out the fingerprints of the public keys in ~/.ssh/authorized_keys to be able to compare them. So I wrote a little wrapper called ssh-fingerprint.sh around ssh-keygen to feed it all the public keys from authorized_keys (if you want you can even fit the whole while loop as a oneliner):

How to check if a IP (ipv4) address is valid in pure Bash

Here is a small bash function to check if a IP is valid (4 octets, each octet < 256). I find it somewhat elegant since instead of using a lot of case/if/then constructs or a crazy long regex it splits the IP into each octet (and stores them in an array, and then uses a combination of regex and bit shifting to check each octet.

The function will return 0 if the IP is valid, and 1 or higher if it encountered an error (you can check with the $? variable directly after calling the function)
Example:

silica.dopefish.de – catching data leaks

I was testing a PHP script for security flaws today and needed a way to check if it was possible to “accidently” leak sensitive data to an external server. So I threw together a small script to save the contents of the $_SERVER $_COOKIE $POST and $_GET arrays and dump them in a file. Since it worked so good I decided to leave the site online.

Why did I call it silica? Because silica gel absorbs and stores fluids like this website absorbs information thrown at it. How to use it? Just get your application to connect to silica.dopefish.de instead of where it intended to connect to (by overwriting variables, DNS foo, be creative) and see what happens.

Base Domain: silica.dopefish.de
The webserver will catch any URL (regardless what path or filename) and log the environment. The only exception is the logfile.

Logfile: http://silica.dopefish.de/access.log
The log is automatically emptied every 10 minutes, so save the output if you need it.