Picture of Jürgen Kreileder

Securing WordPress Admin Access With SSL

January 22nd, 2006: There’s an updated version of this guide for WordPress 2 now: Securing WordPress 2 Admin Access With SSL

As one can guess from the look of this site, I’m using as my blog engine. At this time WordPress does not support HTTPS access to the admin area when the rest of the blog is served via normal HTTP. This is a bit unfortunate. I 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() working with HTTPS URLs
    • Disable login over XML-RPC
  • 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.

    • 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-example.org
  • Now setup the HTTPS virtual server: 20-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!

This article Jürgen Kreileder is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

20 Comments

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post. Both comments and pings are currently closed.

Cody said

I like the config that you have here, but I am not able to install the plug in. When I put the file into the “wp-content/plugins” folder I don’t see it come up. Any ideas?

You mean wp-ssl.patch? That’s a patch, not a plugin. To apply it to the WordPress source code do this:

$ cd /path/to/wordpress
$ patch -p1 < /path/to/wp-ssl.patch
kb said

I’m trying to set up WordPress on a intranet site that’s 100% SSL and I don’t know where to turn. It’s served from Windows IIS.

I tried running your patch from the DOS prompt but I get this error:

patch: **** strip count ‘l’ is not a number

any ideas?

It’s -p1, not -pl. In other words: there’s a ONE at the end, not an L.

The setup described here is for a mixed HTTP/HTTPS environment: Readers still use HTTP, only admin access is done via HTTPS.

If you put the whole blog on an HTTPS server, WordPress should work pretty much out of the box. If it doesn’t, just look through the source code if there’s some hardcoded “http://”.
Also, for an intranet site you don’t need certificates, so setup should be pretty straightforward. I can’t tell you how to do it, though, because I’m not familiar with IIS.

[…] Ein schönes Howto um das Kontrollzentrum bei WordPress mit Hilfe von SSL zu sichern. […]

Ju said

hello… thx for trying to solve that problem. But I wish my entire blog (both admin and client-side) could work on my ssl/https server. Changing the “http://” to “https://” in the install file doesn’t give access to the page… so far I’m stuck. Any help ?

AFAIK the forthcoming WordPress 2.0 should work out-of-box when running everything on https.

As for the mixed http/https setup, I’ll update this guide when 2.0-final is released.

[…] I finally found a way around this using mod_proxy. This page was a major help in getting that working. […]

[…] after completing the installation i noticed that the admin area can not be configured to be accessible via ssl. googling for solutions i came across a very useful blog entry which provides a patch and instructions on how to configure the apache proxy module to enable ssl access to the admin interface. […]

s.b said

Hi there! Now the 2.0-version is out, but I think there is still no good solution for https-support …

Yeah, I’ll post an updated guide for the mixed HTTP/HTTPS setup this weekend.

As for pure HTTPS configurations: The current svn version of WP still has some issues, e.g. triggering of asynchronous pings doesn’t work.

[…] Still with me? Fear not; we’re almost there. If you – like we – happen to use WordPress on some of your pages, you still have to set the WordPress URL (under Options) to https://yoursite.com, leaving the Blog URL at http://yoursite.com. Since WordPress uses these URLs to actually hardlink everything on its admin pages, this must be done. Still, as some guys pointed out, cookies can be sent in cleartext, so watch out in hostile surroundings (you don’t save cookies or even passwords on your machines, do you? Then start with a fresh browser session). This is being worked on: the WordPress 2.1alpha brings secure logins already, so things are changing for the better. If you want real WordPress security now, visit Jürgen Kreileder’s pages and follow that setup – here an own server (at least vserver) is a must – you won’t be able to do this on shared webhosting. […]

Larry said

Hi,

I’m currently modifying wordpress 2.0 for my company to allow ldap authentication. Since the windows passwords will be used to log into wordpress, I’m going to run the whole blog on ssl. I haven’t given it a try yet. But hopefully it will work out of box.

There is one thing about wordpress that I don’t quite get. Why does word press use cookies to store all the user authentication info, why not sessions? It seems that using session is a much better/cleaner/safer way to handle user authentication while on the client side, there is only a session id that needs to be stored inside cookies.

Can someone give me some hints.

Thanks

[…] Securing WordPress Admin Access With SSL […]

Jen Farmer said

Nice examples, don’t forget to secure HTTPS only connections for submitting passwords to prevent sniffers.

http://www.askapache.com/2006/htaccess/apache-ssl-in-htaccess-examples.html

[…] Wie man den WordPress-Adminbereich mit SSL sichert […]

[…] Kreileder over at blog.blackdown.de has a really nice step by step howto on how to enable SSL (HTTPS) for a WordPress […]

umesh said

hi,

I am using WORDPRESS 2.7.1 with CAS authentication.
Now I am trying to publish a document on WordPress using XML-RPC but it shows error.
javax.faces.el.EvaluationException: Exception while invoking expression #{org_alfresco_module_blogIntegration_BlogActionListener.executeScript}
caused by:
org.alfresco.module.blogIntegration.BlogIntegrationRuntimeException: Failed to execute blog action ‘metaWeblog.editPost’ @ url ‘http:///wordpress/xmlrpc.php’
caused by:
marquee.xmlrpc.XmlRpcException: The XML-RPC response could not be parsed: org.xml.sax.SAXParseException: The element type “address” must be terminated by the matching end-tag “”.

I want to know whether XMl-RPC request on wordpress is allowed after applying CAS authentication on WORDPRESS?

Please help.

metron replied

Nice Howto but it stops to ask me what file I use to patch? What I have to choose to?

regards

[…] I finally found a way around this using mod_proxy. This page was a major help in getting that working. […]