12 Apr 2016

When A False Vulnerability Report Leads To a Real Security Vulnerability

Today a report claiming that there was remote code execution vulnerability in version 2.0.14 of the Robo Gallery plugin was released. With such a serious vulnerability and one that was claimed to be in the most recent version of the plugin, we quickly started checking on the report to include the vulnerability in our service’s data. What we quickly noticed was the claimed vulnerability didn’t actually exist, but that that a less serious vulnerability in code mentioned in the false report does exist in the plugin. We have notified the developer that there apparent attempt to fix that vulnerability in the subsequently released version 2.0.15 was not successful. All of this highlights the importance the kind of the testing we do before adding vulnerabilities to our service’s data (and highlights the limited value of other services that don’t do that testing).

The threat of the claimed vulnerability is describe as

A remote php code execution vulnerability has been discovered in the official Robo Gallery v2.0.14 WordPress Plugin web-application. The vulnerability allows remote attackers to execute own malicious php commands to compromise the web-application or connected dbms.

and

The security risk of the code execution vulnerability is estimated as high with a cvss (common vulnerability scoring system) count of 8.9. Exploitation of the php code execution vulnerability requires no privileged web-application user account and low or medium user interaction. Successful exploitation of the vulnerability results in computer system, web-server or database management system -compromise.

The report looks rather professional, but once you look at the details of the claimed vulnerability in becomes clear that that the person that put it together didn’t understand what they were talking about at all.

The proof of concept provided for exploiting the vulnerability is:

http://localhost:8080/wp-content/plugins/robo-gallery/includes/rbs_gallery_ajax.php?function=phpinfo();[CODE EXECUTION VULNERABILITY!]

Right after the code for the file the request is supposed to be sent to, /includes/rbs_gallery_ajax.php, is included:

<?php
if ( ! defined( 'WPINC' ) )  die;

if(!function_exists('rbs_gallery_ajax_callback')){
    add_action( 'wp_ajax_rbs_gallery', 'rbs_gallery_ajax_callback' );
    function rbs_gallery_ajax_callback(){
        if(isset($_POST['function']) && $_POST['function']){
            $functionName = 'rbs_ajax_'.$_POST['function'];
            if( function_exists( $functionName ) ) $functionName();
        }
        wp_die();
    }
}

The first obvious problem is that the code in the file will not run directly, as the proof of concept requires. The second line of the file, “if ( ! defined( ‘WPINC’ ) ) die;”, checks if the file is being loaded directly and then stops it from running if it has. The rest of the code only runs if the file is loaded through WordPress.

The next problem is that the proof of concept shows passing the value of input named “function” via a URL parameter. That would be accessible via PHP using $_GET[‘function’], but the code only access the “function” input through a POST, $_POST[‘function’].

So based on that clearly the proof of concept is wrong, but that doesn’t necessarily mean that there isn’t an issue, which meant we still had to dig deeper to fully check this out.

Next we saw that only some one logged into to WordPress is allowed to access the function included in the file due to this line:

add_action( 'wp_ajax_rbs_gallery', 'rbs_gallery_ajax_callback' );

So the claim that this “requires no privileged web-application user account” is also false.

The portion of the code where the code execution is supposed to happen is here:

$functionName = 'rbs_ajax_'.$_POST['function'];
if( function_exists( $functionName ) ) $functionName();

The code first takes the  value of “function” input and appends it to the string “rbs_ajax”. That means that only a function that starts “rbs_ajax” can possibly run.

Unless another plugin was installed that had functions that started”rbs_ajax”, then all of the functions that would meet that requirement are stored in the file /includes/extensions/rbs_create_post_ajax.php. Based on what the functions do it didn’t look like these were meant to be accessible to all levels of users, which would indicate that there is actually a privilege escalation vulnerability in the plugin.

While we were looking into this, version 2.0.15 of the plugin was released, in which the developer tried to restrict access to the function rbs_gallery_ajax_callback in the file /includes/rbs_gallery_ajax.php to admins. We say tried, because they used the function is_admin(), which doesn’t actually doesn’t check if a user is an administrator. Instead it checks if “if the Dashboard or the administration panel is attempting to be displayed”. Since it “will return true when trying to make an ajax request (both front-end and back-end requests)”, this had no impact in this situation since it involves an ajax request. The attempt to restrict access to the functions seems to confirm that a privilege escalation vulnerability exists in the plugin.

We have informed the developer of the problem with using is_admin() and hopefully a fix will be released soon.

Leave a Reply

Your email address will not be published.