Cross-Site Request Forgery vulnerability in the Merge + Minify + Refresh plugin


An attacker can create a URL that, if followed by a low-privilege WordPress user, would delete chosen files on the website.

We discovered that this plugin allows any logged-in user to perform actions that are susceptible to path traversal attacks. Additionally, the plugin does not use cryptographic nonce checks. Therefore, if an attacker were able to cause a logged-in user's browser to make requests (such as by following a URL or loading an image) they could submit webserver requests as if they were that user. This is known as a CSRF attack.

For example, an attacker could cause a user's browser to delete the WordPress configuration file by making an Ajax purge request to the path ../../../wp-config.php. Once this file is deleted, any unauthenticated user connecting to the site can complete the installation process and point the WordPress site to a database of their choosing. The attacker could then log into WordPress as an administrator and modify the PHP code of the theme to create a backdoor to execute shell commands, thus gaining complete control over the webserver. It would be possible to automate the process of taking over a WordPress instance once the user visits the malicious page, and if crafted carefully the user would not be aware they had been compromised.

Note that the Merge + Minify + Refresh plugin allows any authenticated user to perform these actions, regardless of their level of privilege, so all users are susceptible to this attack.


WARNING: This replication process is destructive, and is included for information purposes only. Do not follow these steps on a production system: set up a local copy (hostname temporarycopy.local in this example).

Create an HTML file containing the following code, and save it on your local drive:

    <form id="form" action="https://temporarycopy.local/wp-admin/admin-ajax.php" method="post">
    <input type="hidden" name="action" value="mmr_files"/>
    <input type="hidden" name="purge" value="../../wp-config.php"/>

Log into WordPress, and then visit the HTML file you have just created.

Then open an incognito browser window and visit https://temporarycopy.local/. A WordPress configuration page is displayed.

Create a MySQL database, then visit the following URL: https://temporarycopy.local/wp-admin/setup-config.php

Fill in the set-up forms, and provide the details of the AWS database.

Log into the new WordPress installation. Modify the WordPress theme code to allow arbitrary commands to be run.

Mitigation/further actions

Upgrade to version 1.10.8 or later.

Advisory timeline

  1. 2020-01-28 – Reported to plugin author
  2. 2020-01-29 – Issue reported fixed
  3. 2020-01-31 – Fix verified by Tradecraft
  4. 2020-02-05 – Advisory published


Base score 8.2
Attack vector Network
Attack complexity High
Privileges required None
User interaction Required
Scope Changed
Confidentiality Low
Integrity High
Availability High


  • Severity
    High (base score 8.2)
  • Discovered by
    Glyn Wintle
  • Severity
  • Advisory ID
  • CVE
    (CVE not assigned)
  • Component/package
    Merge + Minify + Refresh
  • Version
    1.10.7 and older versions
  • Published