2010-10-18

OpenBSD 4.8 is almost here! Chroot Apache, MySQL and Suhosin Hardened PHP


OpenBSD 4.8 is going to be released on November 1st, and that means it's time to revisit the setup of a highly-secure AMP stack on OpenBSD for hosting your web apps, blogs, and projects!

I actually cheated a bit to make this article, if you can call busting my ass performing a "make package" for hundreds ports in OpenBSD-current and doing a bunch of Virtual Machine snapshot reversions "cheating." It was a major pain in the butt to do, but I won't have much free time when OpenBSD 4.8 actually ships, so here you have it.

My Chroot OAMP series of articles is pretty popular, especially since attacks against PHP web applications are on the rise and people are looking for ways to get a little extra security for their web hosting environments.

By default, OpenBSD ships with a specially patched and code-audited derivative of Apache web server. It has been engineered specifically to run in a chroot environment, which is to say that even if someone or something could make Apache run arbitrary code, it can only impact what's in the web directory. It can't readily harm or disrupt the rest of the system.

The version of PHP in OpenBSD's package repository has also been tweaked with the Suhosin Hardened-PHP patch, which can defend vulnerable PHP applications from certain kinds of malicious attacks.

A relatively current version of MySQL is also in the package repository. The configuration provided isn't too bad.

Getting the software installed is easy, but turning it into a functional and secure AMP environment can be a chore if you haven't done it before.

Preparation:
During the installation of OpenBSD, you are prompted to create a non-root user. This feature was introduced last year with OpenBSD 4.6, and is primarily to discourage the improper use of the root account. The user you create during installation will be automatically added to the wheel group, which grants permission to use the su command. I generally add the wheel group to sudo as well, by adding this line to /etc/sudoers (with the root user):
%wheel   ALL=(ALL) SETENV: ALL
If you are currently logged in with your user-level account, you will need to log off and log in again in order to use sudo.

Package management used to be one of the more annoying aspects of OpenBSD. In 2004, I even wrote my own scripts to wrangle the packages. They've gotten consistently better over the years, and with OpenBSD 4.8, they introduced yet another great feature: /etc/pkg.conf (manual page .) There are only a few options available for this file right now, but it allows you to set global options for the package tools instead of setting up and relying on the PKG_PATH environment variable. If you perform an FTP install, the installer should automatically add the FTP mirror you used to this file. If you installed from CD but would like to use an ftp mirror for pkg_add, you need to add an "installpath" line to /etc/pkg.conf, which may not exist yet.
installpath=ftp://ftp5.usa.openbsd.org/pub/OpenBSD/4.8/packages/i386
Of course, you can pick whichever mirror you like. The OpenBSD project maintainers frown upon pointing direct downloads at the main ftp site. You can easily add local package repositories to this path.

Installing Packages
Installing php5-mysql and mysql-server will fetch all of the dependencies for OAMP. This process may take a while depending on your connection speed. There are several dependencies that will be installed, including php5-core and some perl modules.
sudo pkg_add php5-mysql mysql-server
Next, copy the PHP + MySQL sample files into place
sudo cp /var/www/conf/modules.sample/php5.conf \
/var/www/conf/modules/

sudo cp /var/www/conf/php5.sample/mysql.ini \
/var/www/conf/php5/
Run the script to get the default MySQL database installed, start MySQL and set a MySQL root password.
sudo /usr/local/bin/mysql_install_db

sudo /usr/local/share/mysql/mysql.server start

sudo /usr/local/bin/mysqladmin \
-u root password 'your-password'
At this point, both MySQL and PHP are installed and set up with a default configuration that will probably work fine for most applications.

Chroot Setup
In this version of OpenBSD, a chroot /tmp directory already exists with the proper permissions in /var/www, which simplifies setup of the chroot environment. All we're left to do is to reproduce the directory structure for the MySQL socket under /var/www.
sudo mkdir -p /var/www/var/run/mysql  # -p creates subdirs as needed
Start Apache and MySQL at boot
Set apache to start on boot by editing /etc/rc.conf. Find the httpd_flags line in the file, change NO to "" -- literally, two double quotes as shown below.
sudo vi /etc/rc.conf
# use -u to disable chroot, see httpd(8)
httpd_flags=""
Then, make sure that MySQL starts at boot and that the real mysql.sock file gets hard linked into the new directory by editing /etc/rc.local. I also added a line to remove the old hard link before starting MySQL. The end of my /etc/rc.local looks like this:
rm /var/www/var/run/mysql/mysql.sock
/usr/local/share/mysql/mysql.server starr
sleep 5

ln /var/run/mysql/mysql.sock /var/www/var/run/mysql/mysql.sock

After getting all of the services set up to start automatically, I usually reboot to make sure everything starts up as expected.
sudo reboot

Testing
Once the system comes back online, the most basic test of Apache and PHP is to create a phpinfo script. This can be done with one line of shell-fu, which will launch "tee" with root permissions to write the phpinfo.php file.

echo "<?php phpinfo(); ?>" | sudo tee /var/www/htdocs/phpinfo.php

Then, navigate to http://your.openbsd.ip.address/phpinfo.php in your web browser. It should load a nice-looking document containing details about PHP's configuration. In particular, check for MySQL.



To wrap up, I performed the usual "5 minute install" of Wordpress 3.0.1 (current as of writing) to see what happens. The end result was a totally painless and fully functional setup that's ready to go.

Wordpress on OAMP

The ultimate simple guide to Internet privacy

People are making a big fuss about privacy and how companies are invading it. Without further delay, here is my all-encompassing guide to Internet privacy.

  1. Think about what you're going to post.
  2. If you can concoct any situation in your mind where it would be bad for any one specific person to see it (e.g., your boss, your parents or even the person you're making fun of,) either now or for the foreseeable future, then do not post it on the Internet.
Your mother probably said something along the lines of "If you don't want it on the front page of the newspaper, then don't do it!" She was on to something, you know.

Also, if you're using someone else's bandwidth, server resources and infrastructure for free, then the service they provide to you is not their product. Their product is the data you willingly give them, which they're more than happy to monetize in any number of ways.

2010-10-15

Shibboleet!

In today's xckd, we see the magic passphrase "shibboleet."




I'd never heard of this word before, but when I saw mention of the 1990s, I figured it had to be a portmanteau of "shibboleth" and "leet" (or 1337 as it were), where leet is a shortened form of "elite" - a (now tongue-in-cheek) catchphrase for a hacker, programmer or engineer who is among the best of the best at a given skill.

The word shibboleth comes from a Hebrew word that was difficult for non-Hebrew-speakers to pronounce properly. At one point in history, Hebrews used this word to weed out Ephraimite impostors. This day and age, a shibboleth is any defining trait or practice that's inherent to a given culture, but particularly one that is used as a cultural indicator. We naturally use shibboleths frequently in the form of inside jokes, lexical idiosyncrasies and even our fashion.

That makes today's xkcd particularly meta.

2010-10-11

Nessus XML parsing with awk

At the office, I use Nessus for automated network scanning and patch auditing. With credentials and proper tuning of the scan policy, Nessus is a very powerful tool for more than skript kiddie network scanning. This leaves me with a whole bunch of data to wade through on a weekly basis.

Usually, I only concern myself with the high-severity issues for weekly reports, then as I have time, I dig deeper into the more trivial problems. Still, this required me to manually open the scan files, filter them by severity, and export the data. I got tired of that and made a quick and really dirty XML parser (.nessus files are XML) with shell and grep. It was horrendously slow.

Andy, a fellow KC2600-er helped me wrap my brain around some of the finer points of awk to make it more efficient. This is slightly modified from the one I use at work, which is part of a bigger script that does other things. I figure it's useful for others who use Nessus regularly. The script is here.

Basically, it stores the HostName tag when it encounters it, then iterates through the lines, storing them temporarily until it runs into a line indicating a high-severity plugin has been triggered (severity level 3), then it spits out the host name and the plugin that was triggered. I probably could write the whole thing in awk, but I wrapped it in a little bit of plain old shell script.

Output looks something like this:


Windows
----------------------------------------------------
x.x.x.19:MS10-062: Vulnerability in MPEG-4 Codec Could Allow Remote Code Execution (975558)
x.x.x.19:Adobe Reader <= 9.3.4 / 8.2.4 CoolType.dll SING Font 'uniqueName' Field Parsing Overflow (APSA10-02)
x.x.x.20:MS10-066: Vulnerability in Remote Procedure Call Could Allow Remote Code Execution (982802)

Mac
----------------------------------------------------
x.x.x.8:Mac OS X AFP Shared Folders Unauthenticated Access (Security Update 2010-006) (uncredentialed check)

Linux
----------------------------------------------------
x.x.x.40:PHP 5.2 < 5.2.14 Multiple Vulnerabilities

2010-10-07

It only happens once every 823 years!

- OR -
Shell Scripting for Pedantry's Sake.


Today's "That can't be true!" moment hit me when I started seeing this making the rounds (in various different paraphrased versions) on Teh Intarwebs:

"This month has 5 Fridays, 5 Saturdays and 5 sundays-Only happens every 823 years!"

Truth be known, I don't really care about how many weekends are in a month except for the fact that I get three paychecks this month. That happens about twice per year, and that's always welcome! Once in a while, though, I just can't help it. I have to disprove something. I figured the easiest way to disprove this particular claim would be to write a shell script that used the "cal" tool, found in every unix variant known to mankind.

For there to be 5 Fridays, Saturdays and Sundays in a single month, there is a basic requirement for a 31-day month that begins on a Friday, and only then will the 31st fall on a Sunday to complete 5 "whole weekends" in one month.

Initially, I was thinking of ways to see what months started on a Friday. That would get me close. It would give me months such as February 2013, which have only 28 days. Then it hit me: Look for any month with a 31st day that falls on Sunday. Using "cal," I can simply roll through the calendar year looking for a line that begins with "31" and guarantee that the month will satisfy the requirements of having five Fridays, Saturdays and Sundays.

So here we go!

#!/bin/sh
ye=2010
mo=1
while true
do
until [ $mo -gt 12 ]
do
cal=`cal $mo $ye | grep ^31`
if [ -z "$cal" ]
then
echo -n ""
else
echo
cal $mo $ye
fi
mo=`expr $mo + 1`
done
mo=1
ye=`expr $ye + 1`
done


Output:

January 2010
Su Mo Tu We Th Fr Sa
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

October 2010
Su Mo Tu We Th Fr Sa
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

July 2011
Su Mo Tu We Th Fr Sa
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

March 2013
Su Mo Tu We Th Fr Sa
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

August 2014
Su Mo Tu We Th Fr Sa
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

May 2015
Su Mo Tu We Th Fr Sa
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31


I don't know. It looks like these things happen more than every 823 years. You can rest easy knowing that it will actually happen a total of 825 times in the next 823 years. Yep, I counted them.

One of the derivatives mentioned October specifically, though. Perhaps this only happens once every 823 Octobers?

Slightly modified, we make the script check Octobers...

#!/bin/sh
ye=2010
mo=10
while true
do
cal=`cal $mo $ye | grep ^31`
if [ -z "$cal" ]
then
echo -n ""
else
echo
cal $mo $ye
fi
ye=`expr $ye + 1`
done

Output:

October 2010
Su Mo Tu We Th Fr Sa
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

October 2021
Su Mo Tu We Th Fr Sa
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

October 2027
Su Mo Tu We Th Fr Sa
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

October 2032
Su Mo Tu We Th Fr Sa
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31



Nope. More than a decade at times, but not 823 years.