I discovered that the WordPress Download Manager contains some very serious security vulnerabilities. The free version available on wordpress.org claims to have 80,000+ active installs (as of 1/19/2016), the company also sells a pro version that has an unknown number of installs.
There are multiple different vulnerabilities in the plugin, I do not have access to the pro version so I can not verify if all of the vulnerabilities are resolved or if there are additional similar vulnerabilities.
Unauthenticated Directory listings
The wpdm_dir_tree() function is called during the ‘init’ action and without any authorization checks preventing it from working. A user can pass the HTTP GET variable ‘task=wpdm_dir_tree’ and the HTTP POST variable ‘dir’ containing a directory and the server will return a listing of the files in that directory.
Unauthenticated post updating
The savePackage() function gets called by the ‘wp’ action, there are lots of fun things you can do with this function and none of it requires any type of authorization. I won’t spell out exactly what you need to do but it’s quite simple to use this to associate any file on the filesystem with a post.
Later in the function it takes arbitrary user data and updates the post meta for a specific post.
Then someone can use the WPDM builtin capabilities to download a file associated with a specific post. I was able to use this mechanism to download arbitrary files from the host.
Privilege Escalation
This last piece requires you have a valid account on the WordPress host, though if registration is enabled on the host the WPDM plugin makes it even easier to create an account. Through the magic of the extract($_POST) function a user can pass in any of the parameters that get sent to the wp_update_user() WordPress function. Many of these options the user can usually change via their profile settings, but the ‘role’ is usually one that should only be adjusted by the Administrator.
The extract function needs to be used very carefully (if at all), especially when passing in an array of user supplied data (like $_POST, $_GET, $_REQUEST, etc.).
Timeline
- 1/10/2016 Initial contact via webform to determine contact information
- 1/11/2016 11:51am Contact address received
- 1/11/2016 1:38pm Initial full disclosure
- 1/11/2016 2:45pm Additional information discovered and disclosed
- 1/11/2016 10:15pm Updated version released that did not completely resolve issue
- 1/12/2016 Vendor released new versions and posted blog