Picture of Jürgen Kreileder

Archive for the ‘Security’ Category

Chrooting Recent MySQL Versions on Debian and Ubuntu

I’ve posted a recipe for chrooting MySQL on Debian sarge a while ago. These instructions no longer work out of the box for newer MySQL packages from Debian and Ubuntu. The main problem is that the startup script added a few extra checks and script invocations that don’t understand the chroot environment. So here’s an updated plan:

  • Prepare the chroot directory. It’s recommended to use an extra partition/filesystem for it. I will use /srv/mysql (which is an LVM2 partition with an ext3 filesystem on my system) for the rest of the text.
  • Stop MySQL:
    /etc/init.d/mysql stop
  • Copy the databases to new location:
    mkdir -p /srv/mysql/var/lib
    cp -a /var/lib/mysql /srv/mysql/var/lib
  • Copy this script to /etc/default/mysql-chroot
  • Edit /etc/init.d/mysql:
    • Source the mysql-chroot script somewhere at the top:
      …
      test -x /usr/sbin/mysqld || exit 0
      
      . /etc/default/mysql-chroot
      
      SELF=$(cd $(dirname $0); pwd -P)/$(basename $0)
      …
    • Fix the disk space check:
      …
      # check for diskspace shortage
      datadir=`mysqld_get_param datadir`
      if LC_ALL=C BLOCKSIZE= df --portability $CHROOT_DIR$datadir/. | tail -n 1 | awk '{ exit ($4>4096) }'; then
        log_failure_msg "$0: ERROR: The partition with $datadir is too full!"
      …
    • Run setup_chroot right in the start section:
      …
      if mysqld_status check_alive nowarn; then
        echo "...already running."
      else
        setup_chroot
        /usr/bin/mysqld_safe > /dev/null 2>&1 &
      …
    • Somehow /var/run/mysqld/mysqld.pid disappears after each start. We have to create it each time, otherwise the stop command won’t work properly:
      …
      if mysqld_status check_alive warn; then
        log_end_msg 0
        ln -sf $CHROOT_DIR/var/run/mysqld/mysqld.pid \
                       /var/run/mysqld
        # Now start mysqlcheck or whatever the admin wants.
        output=$(/etc/mysql/debian-start)
      …
  • In /etc/mysql/debian.cnf, change the two socket lines to:
    socket = /srv/mysql/var/run/mysqld/mysqld.sock
  • In /etc/mysql/my.cnf:
    • Change the socket line in the [client] section to:
      socket = /srv/mysql/var/run/mysqld/mysqld.sock

      Don’t change the socket lines in the other sections!

    • Add
      chroot = /srv/mysql

      to the [mysqld] section.

  • Prepend /srv/mysql to the log files listed in /etc/logrotate.d/mysql-server
  • Make /usr/bin/mysql_upgrade_shell use the chrooted socket. Note: Currently these changes must be made each time mysql gets upgraded because upgrades override this file!
    …
    --password=*) password=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
    --socket=*) socket=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
    --ldata=*|--data=*|--datadir=*) DATADIR=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
    …
    fi
    $bindir/mysql_fix_privilege_tables --silent --user=$user --password=$password --socket=$socket $args
    exit 0
    …
    check_args="--check-upgrade --all-databases --auto-repair --user=$user --password=$password --socket=$socket"
    …
    $bindir/mysql_fix_privilege_tables --silent --user=$user --password=$password --socket=$socket $args
    …
  • Start MySQL:
    /etc/init.d/mysql start
  • Check /var/log/syslog for errors ;-)

Securing WordPress 2 Admin Access With SSL

A few people have asked for an updated version of my Securing WordPress Admin Access With SSL guide. So here is an updated version for 2!

The situation has not changed much since WordPress 1.5: WordPress 2.0 still does not support HTTPS access to the admin area when the rest of the blog is served via normal HTTP and I still do not like logging in to my server over unencrypted connections, especially not when using public WLANs. Getting around this WordPress limitation requires quite a few steps:

The Goal

All communication involving passwords or authentication cookies should be done over HTTPS connections. wp-login.php and the wp-admin directory should only be accessible over HTTPS.
Normal reading access, as well as comments, tracebacks, and pingbacks still should go over ordinary HTTP.

The Plan

  • Add an HTTPS virtual host that forwards requests to the HTTP virtual host
  • Modify WordPress to send secure authentication cookies, so cookies never get sent over insecure connections accidentally
  • Require a valid certificate on HTTPS clients. That means to log in to WordPress you need both a valid certificate and a valid password. If someone manages to get your password, he still can not login because he does not have a valid certificate.

The Implementation

Note: This documentation assumes a Debian sarge installation with 2. Some things, in particular Apache module related ones, will be different on other systems.
The server used throughout the instructions is example.org/192.0.34.166. The server’s DocumentRoot is /blog and WordPress resides in /blog/wp. The value of WordPress’ home option is ‘http://example.org’ and the value of its site_url option is ‘http://example.org/wp’.

  • Prepare the SSL certificates:
    • Generate your own certificate authority (CA) if you don’t have one already (I’m using the makefile from OpenSSL Certificate Authority Setup for managing mine) and import it into your browser.
    • Generate a certificate for the SSL server and certify it with your private CA.
    • Generate a certificate for your browser and certify it with your private CA. Most browsers expect a PKCS#12 file, so generate one with
      $ openssl pkcs12 -export -clcerts \
          -in blogclient.cert \
          -inkey blogclient.key \
          -out blogclient.p12

      Then import blogclient.p12 into your browser.

  • Make WordPress SSL-ready:
    Apply this patch to the WordPress code. It makes the following changes:

    • Use secure authentication cookies in wp_setcookie()
    • Make check_admin_referer() work with HTTPS URLs
    • Use HTTPS URLs for notification mails
    • Use HTTPS URLS for redirects to wp-login.php
    • Only allow XML-RPC logins from the local host (ie. the HTTPS proxy)
    • Add the Mark-as-Spam feature from trunk

    The patch is against svn version 3825 of WordPress (ie. WordPress 2.0.3), when you apply it to a newer version, you will likely get some harmless ‘Hunk succeeded’ message. If you are getting ‘Hunk FAILED’ message, just send me note and I’ll update the patch.

  • Enable the necessary Apache modules:
    • Install mod_proxy_html. It will be used to replace absolute ‘http://example.org’ HTTP URLs in the WordPress output with ‘https://example.org’ HTTPS URLs:
      $ aptitude install libapache2-mod-proxy-html

      The module gets enabled automatically after installation.

    • Enable mod_proxy and mod_ssl
      $ a2enmod proxy
      $ a2enmod ssl

      Debian provides sane default configurations for both modules. You might want to take a look at the configuration files (ssl.conf and proxy.conf) nevertheless.
      I have changed SSLCipherSuite to

      TLSv1:SSLv3:!SSLv2:!aNULL:!eNULL:!NULL:!EXP:!DES:!MEDIUM:!LOW:@STRENGTH

      in ssl.conf in order to just allow TLS v1 and SSL v3 ciphers which provide strong encryption and authentication (see ciphers(1)).

    • If you are compressing WordPress output (that is if you enabled the ‘WordPress should compress articles (gzip) if browsers ask for them’ option) then also enable mod_headers:
      $ a2enmod headers
  • Configure Apache to listen on the HTTPS port
    $ cat > /etc/apache2/conf.d/ssl.conf << EOF
    <IfModule mod_ssl.c>
    	Listen 443
    </IfModule>
    EOF
  • Modify the blog virtual host to limit access to wp-login.php and wp-admin to the local host. Also completely deny access to files which should never be accessed directly. Here is an example: 10-wp2-example.org
  • Now setup the HTTPS virtual server: 20-wp2-example.org-ssl
    If you are compressing WordPress output you have to enable the RequestHeader line.
  • Enable the site and restart Apache
    $ a2ensite 20-blog-ssl
    $ /etc/init.d/apache2 restart
  • Remove the old WP cookies from your browser
  • Test the new setup!

February 1st, 2006: wp2-ssl.patch updated for WordPress 2.0.1

March 11st, 2006: WordPress 2.0.2 has been released, fixing some security issues. The HTTPS patch still applies fine to that version.

March 19th, 2006: Updated wp2-ssl.patch. Changes: Fix bug in list-manipulation.php, use HTTPS for ‘Login’ and ‘Register’ links, backport ‘Mark-as-Spam’ feature from trunk

May 1st, 2006: WordPress 2.0.3 has been released. Here is the updated wp2-ssl.patch.

July 29th, 2006: WordPress 2.0.4 has been released, fixing some security issues. Here is an updated version of the wp2-ssl.patch.

January 12st, 2007: wp2-ssl.patch updated for 2.0.6 and 2.0.7-RC1

January 15st, 2007: WordPress 2.0.7 has been released. The patch still applies fine to that version.

Blackdown J2SE 1.4.2-03

I’ve released Blackdown’s J2SE 1.4.2-03 for Linux on x86 and AMD64/EM64T yesterday. The release fixes three security issues with the Reflection API (JRE May Allow Untrusted Applet to Elevate Privileges), so make sure you upgrade.

The issue isn’t Blackdown-specific. Sun released an advisory too.

Thanks to Matthias Klose, Debian packages for 1.4.2-03 are available too. Just add something like

deb ftp://ftp.tux.org/java/debian/ sarge non-free

to your /etc/apt/sources.list.

The Release files are signed with the Blackdown Java-Linux Package Signing Key. If you have recent apt version you can use this key to authenticate our Debian packages. Just import the key with apt-key:

$ wget http://www.blackdown.org/java-linux/java2-status/gpg.asc
$ apt-key add gpg.asc

Debian Testing Gets Security Support

The Debian Testing Security Team just announced the beginning of full security support for Debian’s “testing” distribution!

The lack of security support was one of the main problems with “testing”. You had to pull security fixes from “unstable” or even build your own packages to keep it secure.

I hope they have the manpower to keep up with security issues. Debian’s main security team, which only provides updates for the “stable” distribution, had some problems over the last months.

WordPress Security Annoyances

As if the unprofessional handling of security announcements (see Another WordPress Security Update and More on Security Announcements) wouldn’t be bad enough, the WordPress developers also seem to have problems with organizing releases.

Stefan Esser reports that there are two WordPress 1.5.2 versions. The first one, which didn’t fix the problem it was supposed to fix, was available for download for several hours before it silently was replaced by the fixed second version.

It’s hard to understand why the version number wasn’t bumped for the second release and why the WordPress developers didn’t inform users about the mistake.

The comments from the WordPress crowd are a bit weak in my opinion. If there’s FUD about WordPress’ security it’s the sole fault of the WordPress developers!