Welcome

This is my poky little corner of the Internet. Originally started in 1999 (my website that is, not the Internet) it took on many forms – until 2005, when I lost enthusiasm for my own Internet presence and simply stopped updating it.

This is my (not quite as successful as I’d hoped) attempt at getting some of that enthusiasm back. Enjoy!

1

WordPress Plugin Security Alert

Earlier this week, a friend (who, for the purposes of this post is named Stephen) relayed a story to me of an email that one of his friends had received recently.

This friend – let’s call him John – runs a local business that requires advance bookings from customers. He runs his entire booking calendar through his website, and as well as customers being able to register an account and book through the website, he can also create bookings on behalf of customers from the administration panel.

It’s this latter scenario that gave rise to the situation I’m about to delve into. John had booked this customer in to his calendar through the admin panel of his WordPress-powered website, and the customer received a confirmation email containing a “Manage Account” link.

The customer clicked this link to view his booking details, and was surprised to find that he could see a lot more bookings than just his own! He, very responsibly, emailed John to let him know, who then in turn got in touch with Stephen (who had built the website) and Stephen then relayed this whole story to me.

Immediately my ears pricked up – that’s not a great situation for a customer to find, as it suggests deep-seated problems with the website’s security, so I volunteered to take a look. The following is what I found…

Is this a WordPress problem?

Firstly, let’s get this out of the way. This is a security issue with a specific WordPress plugin – NOT WordPress itself.

What is the plugin affected by this security alert?

The plugin in question is Salon Booking System (link to the WordPress repository)

The original report from Stephen and John related to version 3.30.7 of the Premium version of this plugin, but I have confirmed that the problem exists in version 3.32.2 of the free plugin found on the WordPress repository.

What is the problem?

In short, in situations where the administrator of a website is creating a booking for a customer in the back-end of WordPress – if the admin chooses NOT to create an account for the customer, the confirmation emails (and any subsequent emails relating to that booking) that are sent to the customer’s email address include a link that, when followed, logs them into the WordPress user account that created the booking.

When the link is clicked, the customer is taken to a page that lists all bookings created by the user that created the booking – and, if the customer then goes to the /wp-admin URL (or uses the Dashboard link in the admin bar if it is present at the top) they have access to whatever the original creator of that booking does.

Essentially, this is a privilege escalation vulnerability that may result in personal data being leaked or unauthorised actions being carried out in the WordPress dashboard.

So, how is this happening?

With permission from John, I’ve collated some screenshots of the process – with certain details redacted to protect the anonymity of him, his website and any customers affected.

First, the booking needs to be created by an administrator user:

Note: The “Create a new user” tickbox has not been ticked.

This creates the booking (which is a custom post type) and sets the post_author ID to the currently logged in user, as is pretty much standard with WordPress.

An email confirmation is then sent to the email address specified, in this case my Gmail account. This email confirmation looks like this:

Any identifying marks have been redacted/pixellated to preserve anonymity.

The Manage Account button is what we’re interested in here. That button links through to this URL: https://[redacted]/?sln_customer_login=b2a96dc6

This is what we see at that URL:

Note: Booking 11330 was also created by the same administrator user, but for another customer.

Luckily, on this website at least, there doesn’t appear to be any way of seeing any other customers’ details (although the Update Your Profile link visible in that screenshot does allow the customer to see the administrator’s full name, email address, mobile phone (if present) and postal address (again, if present)

More problematic however, is that if the customer then goes to /wp-admin then they have access to the WordPress dashboard as the user that originally created the booking:

In this case, full administrator access. If another role had been used to create the booking, that role’s privileges would be available instead.

Not good at all – in this case, this would allow the personal details of any registered user or any previously booked customer to be viewed. It also obviously allows the user to edit whatever they want to on the site, if the original user has administrator privileges.

The problem code

This issue stems from the “one click login” facility that is present on the “Manage Account” button. Let’s delve into the code! I’m using version 3.32.2 of the free plugin for this analysis.

The Manage Account button can be found in views/mail/_customer_manage_buttons.php:

Line 37 appends the offending sln_customer_login parameter to the button link, with a value taken from $customer->getHash() – this can be found in src/SLN/Wrapper/Customer.php:

This code attempts to retrieve a meta field from the customer’s user, and if it is not found, generates a new one (using the generateHash() method underneath)

The hash is the first 8 characters of the MD5 hash of the concatenated string of the user’s ID, a colon (:) and the current time as a Unix timestamp (i.e. the number of seconds since Jan 1, 1970) – importantly, this hash does not change unless the existing hash is removed at any point.

When the button is clicked, some code in src/SLN/Action/Init.php takes over if the sln_customer_login parameter is detected:

As can be seen on line 206, the code fetches the Customer record by the hash described above, and if it finds a matching user ID it fetches the WP_User object, sets the authorisation cookie (using wp_set_auth_cookie) for that user and then runs any actions hooked into wp_login. It then redirects the user to the My Account page.

At this point, it’s essentially game over as the user is now logged in as the user that created the booking.

Critically, because the hash for the administrator users are constant once generated (unless they are removed through some other means) every email sent that relates to a booking created by that administrator from that point on will contain the vulnerable URL.

What can I do to prevent my site being exploited for now?

The plugin author has already published a patch to the WordPress plugin repository (v3.32.4) which fixes one element of the problem – namely the post_author being set to the administrator user in the scenario described. The fix sets the post_author to zero, meaning the Manage Account button is not added to the outgoing emails.

So, to begin with, we recommend updating your plugin to the latest version – I assume that a similar patch has been released for the Premium version of the plugin (Salon Booking System Pro)

UPDATE – 28 December 2019: A post on the WordPress Support Forum for this plugin suggests that this patch was not rolled into the Premium version of the plugin.

However, this fix does not yet prevent emails that have already been sent from potentially being exploited.

A number of possible courses of action exist:

  1. The easiest solution is most likely to create a new user in the WordPress dashboard that effectively replaces any accounts previously used to create bookings, and to then change the Role of the old accounts to Subscriber or another role that has no admin privileges.
  2. The best course of action, if you are familiar with database queries, would be to remove the generated hashes of any non-customer users.

Either way, until the vendor fixes this issue in a satisfactory manner, I would strongly advise against creating new customer bookings without ticking the “Create a new user” box – i.e. make sure that you create a new user for every customer!

Disclosure Timeline (all times are GMT+1)

  • 3rd October 2019
    • 10:59 – contacted the plugin vendor asking for a contact to send further details to
    • 11:12 – vendor responded asking for further details
    • 11:23 – sent detailed description of issue to vendor
    • 11:40 – vendor confirmed receipt, and advised that they would investigate
    • 12:49 – as per responsible disclosure guidelines, advised vendor that I would be preparing a disclosure report that would be made public after 60 days, or when a fix is published
    • 13:17 – vendor advised that they are already working on a fix
  • 4th October 2019
    • 12:23 – vendor advised that they have released a fix on the WordPress plugin repository (v3.32.4) that does not display the button on the emails – the fix sets the post_author to zero on bookings created without an attached user
    • 13:03 – suggested to vendor that code should be added to invalidate existing hashes to prevent emails that had already been sent from being exploited.
    • 13:51 – vendor replied to state that they would attempt to find a solution for the existing hashes.
  • 2nd December 2019
    • 60 day window expires, disclosure report is made public (err… except, I forgot to unprotect the article, so this didn’t happen until the 28th December)
4

WooCommerce: getAddress.io Postcode Lookup

Update: Version 1.4 released on 12th June 2020, on the plugin repository. See changelog on the plugin repository for more information.

This, my third WordPress plugin (and also my third WooCommerce plugin, apparently I really like doing stuff with WooCommerce!) adds a postcode lookup tool to the checkout in WooCommerce 3.x that lets your UK-based customers quickly fill in their billing/shipping addresses based on their postcode.

It utilises the great getAddress.io API for the postcode lookup, and as such requires an API key for their service. I’d always recommend the £10 per month pricing plan, simply because it offers the best value, but they have a number of others available.

Plugin Features

  • Adds postcode lookup for both billing and shipping addresses
  • Administrators can turn off the lookup for either address, if needed
  • (v1.1) Uses an internal cache for each customer to prevent repeated calls for the same postcode eating up API usage limits
  • Correctly uses the WooCommerce “locale” system to show and hide the lookup button when appropriate
  • Has full internationalisation (i18n) and localisation (l10n) support – so if you want to translate the plugin into your own language, please get in touch!

Screenshots

The plugin adds a Find Address button next to the postcode field, and moves the Postcode field so that it is the first field filled in after selecting United Kingdom as the country.

When the Find Address button is clicked, the user is presented with a menu of available addresses:

In the WordPress back-end, administrators have the following settings available:

Installation

As with all WordPress plugins, you just need to drop the plugin folder into your wp-content/plugins folder and then activate the “GazChap’s WooCommerce getAddress.io Postcode Lookup” plugin.

Requirements

I’m using WordPress 5.1 and WooCommerce 3.5.5 – please let me know in the comments if it doesn’t work on other versions. I believe it requires at least WooCommerce 3.0.0.

Download

Download the plugin from the WordPress Plugin Repository (8.3KiB Zip)

Source

This plugin is open-source – view the source code on the GitHub repository.

1

How to enable checkbox lists for non-hierarchical taxonomies in WordPress

WordPress’ taxonomy features are one of the most powerful aspects of the platform, giving you the capabilities to group posts (including custom post types) in pretty much as many ways as you can think of. There are two types of WordPress taxonomy – hierarchical and non-hierarchical. In case it’s not obvious from the name, a hierarchical taxonomy […]

Read full post >

0

Site upgrade

I’ve spent the last couple of days converting my site to the WordPress platform, rather than using my own bespoke content management platform. It’s taken me far too long to start espousing the benefits of WordPress over other systems, but having done an increasing amount of work with it in the last year I’m now […]

Read full post >