Home » Archives for James Golovich

Author: James Golovich

WordPress shortcode injection as an attack vector

Summary

This is not about a specific vulnerability but an intrusion vector often overlooked by WordPress plugin and theme developers. Frequently code is used that allows attackers to execute arbitrary shortcodes or shortcodes are added that do not provide sufficient validation or check authorization. After all, shortcodes are intended to be used by site editors who are expected to have high credentials, though an attacker doesn’t play by the rules.

What is a shortcode?

Shortcodes were introduced in WordPress version 2.5 back in 2008 as a way for editors to include dynamically generated content in WordPress posts. Initially the available shortcodes were rather limited but plugin and theme developers quickly embraced the API. Shortcodes allow passing attributes and content data to custom functions that return textual data to be included with the post.

Default shortcodes available in WordPress 4.7.2

The default shortcodes are relatively safe but many third party developers have added functionality that makes it easier for WordPress site administrators to extend their site without doing custom PHP coding. Generally the shortcodes added are benign and allow building feature rich WordPress websites, though sometimes the shortcodes provide features that can be leveraged for nefarious purposes.

Shortcode functionality I have seen in various third party plugins

  • Include arbitrary files from the file system
  • Execute arbitrary PHP code
  • Retrieve arbitrary data from WordPress custom post type fields
  • Generate HTML forms that allow editing WordPress posts or users
  • View content that is supposed to be protected by password or other specific protections
  • Provide list of discount codes for an E-Commerce plugin

Who does this affect?

If you are using stock WordPress without any third party plugins or themes you should be safe from any known attack. I’ve posted in the past about specific vulnerabilities but there are some issues I’ve uncovered during research that have not been resolved yet so I will not disclose them until they are fixed.

Depending on the site setup, a user with a Contributor, Author, or Editor role could potentially use shortcodes to escalate their privileges to that of an administrator. With the default roles and capabilities a user with the Contributor role can create posts but they must be approved before being published, but a Contributor can preview their own posts which will cause any included shortcodes to be executed.

How can a developer help prevent these types of an attack?

There are 2 major aspects developers need to be concerned with.

Allowing shortcode injection

Anytime a developer feels the need to call do_shortcode() they should ensure that user input is not passed into the function or be properly sanitized, just like with any other user input.

Keeping shortcodes secure

Any shortcode added with add_shortcode() should check that the logged in user has proper credentials to execute the action. All attributes passed should be properly validated as if the input comes from an untrusted attacker.

Securing shortcodes going forward

I wish there was a holy grail to solve this issue with a couple lines of code, but it’s not a trivial issue to tackle. If a developer could specify capabilities required to insert a specific shortcode then post editors could filter out shortcodes that an author should not have access to, for instance administrator only shortcodes.

I use some simple custom code that adds a filter on ‘pre_do_shortcode_tag’ to restrict shortcodes I explicitly want to allow, security plugins could add some whitelisting/blacklisting of shortcodes but this would likely cause a significant amount of support issues when features suddenly stop working.

Following is a code example to show how to restrict the shortcodes allowed to only the ones that come with stock WordPress.

add_filter( 'pre_do_shortcode_tag', 'pritect_whitelist_shortcodes', 10, 4 );
function pritect_whitelist_shortcodes( $return, $tag, $attr = array(), $m = array() ) {
    if ( in_array( $tag, array( 'audio', 'caption', 'embed', 'gallery', 'playlist', 'video' ) ) ) {
        return $return;
    }
    return '';
}

I hope one day WordPress has a security permission system setup that requires plugins and themes to specify capabilities they use and allow the site administrator to authorize or revoke specific permissions, but that is a large moving target that I wouldn’t expect to be implemented for years (if ever).

Ultimate Member < 1.3.84 allows executing arbitrary WordPress shortcodes

Shortcode Injection Vulnerability

Ultimate Member versions older than 1.3.84 allow unauthenticated users to execute arbitrary WordPress shortcodes via AJAX. The vulnerable code exists as far back as version 1.0.0 when the plugin was first published. If you are using any version of this plugin, update immediately. At this time, the plugin revision notes do not address this vulnerability nor has the developer released any information related to this issue.

The default WordPress shortcodes are relatively secure but other installed plugins often include insecure shortcodes, including the Ultimate Member plugin. Some of the Ultimate Member shortcodes are documented at http://docs.ultimatemember.com/article/210-ultimate-member-shortcodes.

Executing arbitrary shortcodes

Ultimate Member adds the ‘ultimatemember_frontend_modal’ AJAX action which is accessible to anyone whether they are logged in or not. This allows passing arbitrary arguments to the do_shortcode() function and returns the results.

 

Include arbitrary PHP files

Using directory traversal and the ‘ultimatemember_account’ shortcode PHP files accessible on the host can be included. The following function is what is called when the ‘ultimatemember_account’ shortcode is executed.

 

Adding a template argument to the shortcode allows the PHP file to be included.

For example the following shortcode call allows viewing some user stats from the dashboard:

[ultimatemember_account template=../admin/templates/dashboard/users]

If a method could be discovered that allows uploading arbitrary PHP code, this could be used to execute that code.

Timeline

NinjaForms < 3.0.32 allows injecting arbitrary WordPress shortcodes

Back in March 2016 Ninja Forms version 3.0 started to roll out, there was an unknown vulnerability at the time that allowed unauthenticated end users to inject arbitrary WordPress shortcodes via form field submissions. The issue was resolved in version 3.0.31.

The default WordPress shortcodes do not provide much further access and accessing the [ninja-forms] shortcode would only allow an attacker to preview un-published forms. While these shortcodes could allow leverage for further attacks by default this is a very minor issue, though if a site has additional plugins installed that provide shortcodes then this vulnerability could be leveraged to execute those.

Timeline

  • 10/27/2016 First contact to vendor regarding issue
  • 10/27/2016 Received vendor support reply saying they will forward on the issue
  • 11/9/2016 Version 3.0.15 released
  • 11/10/2016 Second contact regarding issue
  • 11/21/2016 Version 3.0.16 released
  • 11/22/2016 Third contact regarding issue
  • 12/6/2016 Version 3.0.18 released
  • 2/28/2016 Version 3.0.30 released
  • 3/2/2017 Fourth attempt regarding issue
  • 3/3/2017 Reply from developer saying they see the issue and will be resolved
  • 3/7/2017 Version 3.0.31 released