Skip to content

Instantly share code, notes, and snippets.

@ldionmarcil
Last active Dec 31, 2016
Embed
What would you like to do?
Authenticated directory listing in XCloner WP plugin <3.5.1, leads to full backups disclosure

Description

Authenticated users are able to perform directory listings at any location available to the Wordpress user, leaking filenames of previous backups. This was found in XCloner - Backup and Restore version 3.1.5, but may have been introduced in earlier versions. Attackers can leverage directory listings to leak otherwise secret filepaths to previous backups, allowing them to acquire full backup contents, since the backup download is not authenticated.

POC

Logged in as a regular, unprivileged user (subscriber)

  1. Visit http://wordpress/wp-admin/admin-ajax.php?action=files_xml. This is a XML file-listing of the root Wordpress installation, and its fullpath
  2. Add a dir GET argument to the URL to browse to a specific directory. The length of this path has to be longer than the length of the backup_path configuration variable on the server, but this is bypassable by adding leading slashes to your path. ie: /foo/bar → /////////foo/bar, or until the length of your path exceeds the configuration one, using trial and error. In this case, we want to leak previous backups, so navigate to http://wordpress/wp-admin/admin-ajax.php?action=files_xml&dir=///////var/www/html/administrator/backups
  3. Backups will be enumerated here, you can then browse to their location Depending on previous steps, the URL would be something like this: http://wordpress/administrator/backups/{BACKUP_FILENAME}

Notes

This bug is caused by a missing access control in files_xml():xcloner.php. This function is missing a check to only allow admins to call this method, something like the check in json_return():xcloner.php.

The reason why the dir parameter has to exceed in length the one of the backup_path variable is because of a check in files_xml.php:24:

if((strlen($_REQUEST['dir']) < strlen($_CONFIG['backup_path']))&&($_REQUEST[dir]! = ''))

I am not sure why this check is there, but as seen in the POC, you can bypass it by adding leading slashes. One would have the reflex to test with directory traversal tricks such as ../ but they might trigger IDS warnings/WAF rules, but trailing slashes rarely do.

Timeline

12-30-2016 Vulnerability found
12-30-2016 Contacted maintainer via email
12-31-2016 Maintainer issues patch
12-31-2016 Report made public
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment