RIPSTech presents
PHP Security Calendar 2018
Day 1 - WooCommerce #1
Stored XSS in 4 million eCommerce shops
WooCommerce
is an eCommerce plugin for WordPress with over
4 million active installations. It's privilege design was flawed, which lead to attackers
in control of a user account with
Shop manager
privileges on the target server being able to inject
malicious JavaScript code into the index page of the target WordPress site. The next time
an administrator visits the frontpage of the
target store, the evil JavaScript code executes in his browser and compromises the store and all customer data.
Proof of concept video
The vulnerability has to do with user roles and capabilities in WordPress.
There are 5 user roles by default
in a default WordPress installation: Subscribers
,
Contributors
,
Authors
, Editors
and
Administrators
. When WooCommerce is installed,
the user role Shop manager
is added. Subscribers are
just readers of the blog
and can't do anything besides updating their profile. Contributors and Authors can
create articles and can use very limited
HTML code in them, such as <table>
and
<img>
tags. For security
reasons, they are limited to harmless HTML tags and are prohibited from using JavaScript code in
their articles.
Editors and Administrators have the capability to use any HTML tags when creating and editing
posts and pages, even <script>
tags and
therefor have the ability to plant Stored XSS payloads into the target WordPress site.
Although Shop managers
do not have the ability to use unfiltered
HTML and are also proibited from using JavaScript code, they had the ability to
edit Customer
accounts of the store and were able to upgrade
their role to Editor
privileges. Evil Shop managers can simply
update a random Customer account, set their user role to Editor, update their password
and log into their account, which then has Editor privileges.
This means they can simply circumvent the HTML restriction
and inject arbitrary JavaScript code into the front page.
The vulnerability was fixed in version 3.4.6
.
Timeline
Date | What |
---|---|
30/08/2018 | Reported the vulnerability to Automattic on Hackerone |
11/09/2018 | Automattic verifies the vulnerability |
11/10/2018 | Automattic releases a patch in version 3.4.6 |
Day 2 - Multiple Popular Plugins
Stored XSS in 4 million WordPress sites
Three plugins, Contact Forms by WP Forms (1 Million active installations), Google Analytics by Monster Insights (2 Million active installations) and WP Mail SMTP by WP Forms (1 Million active installations) all suffered from a critical Stored XSS vulnerability. This is because they all shared vulnerable code that is responsible for displaying notifications in the admin area of WordPress.
The vulnerabilities occurred because lower privileged users were able to create new notifications
for other user accounts on the site and inject <script>
tags
into the rendered HTML markup of the notification. The malicious notifications are then displayed
on the index site of the admin dashboard of WordPress. The next
time an administrator logs into the admin dashboard, evil JavaScript code executes which
compromises the entire server.
Responsible lines of code
Unsanitized post meta is embedded into HTML markup
|
|
WordPress and WordPress plugin developers commonly store things such as internal
notifications and messages
as posts in the database. Although the database columns of the wp_posts
table are static,
fields such as post_content
can be used as notification or message content.
The three plugins use this pattern to implement their notification functionality.
Every time an administrator logs into his WordPress site, a request to the WP Forms API is made.
The request asks if
there are any new notifications that should be displayed, such as critical updates or special offers.
When the API returns new notifications, a new post with the internal type
amn_wpforms
is created with the contents of the notification.
When an administrator then logs into his site, the display_notifications()
function is called, which
pulls all posts from the database with the post type amn_wpforms
and displays the markup.
Lower privileged users, such as Contributors, can create new posts and simply set the post type of them to
amn_wpforms
. The call to
get_posts()
will return all posts with this type and thus
include the post created by the Contributor. The function then iterates over
all returned posts and outputs their post_content
and some post meta information. Although contributors are restricted in the usage of
HTML tags in the post_content, which is sanitized, the post meta information is not
sanitized. Contributors can simply update the post meta information of their
own posts. Since the $type
post meta value is embedded
into the HTML markup, setting it to
'><script>evilCode();</script>
would
result in arbitrary JavaScript code execution.
The vulnerabilities were fixed in WP Forms in version 1.4.8
and in Google Analytics by Monster Insights in version
7.2.0
Timeline
Date | What |
---|---|
25/08/2018 | Reported the vulnerability to the vendor via their support email address |
27/08/2018 | The vendor confirms the vulnerability |
28/08/2018 | The vendor releases a patch for Contact Forms by WP Forms in version 1.4.8 |
19/09/2018 | The vendor releases a patch for Google Analytics by Monser Insights with verion 7.2.0 |
Day 3 - WooCommerce #2
Phar Deserialization to RCE in 4 million eCommerce sites
The popular eCommerce plugin WooCommerce
suffered from a Phar Deserialization vulnerability
that allows attackers in control of a user account with Shop manager
privileges
on the target website to execute arbitrary code remotely on the underlying server. We have written a
blog post explaining
Phar Deserializations, a new exploitation technique in PHP. You can
read about it here.
The vulnerability occurred in the CSV import functionality
of WooCommerce.
$_POST['file'] is passed unsanitized to is_file()
Responsible lines of code
|
|
Phar deserializations occur if unsanitized user input is passed to functions such as
file_exists()
or is_file()
. The vulnerability occurred in WooCommerce's
CSV product import functionality. Shop managers
can upload a CSV file, containing information about products and import them into the shop.
In the first step, the CSV file is uploaded. In the second
step, the shop manager has to confirm that he really wants to perform the import. When
he does confirm, an AJAX request
is sent to the server. One of the POST
parameters sent wth the
AJAX request is that of the path of the CSV file to import (which is the one uploaded in
the first step). That POST parameter
($_POST['file']
) is then passed to
the vulnerable PHP function is_file()
.
Since the attacker has control over the POST parameter, he can simply change it from
/uploads/to-import.csv
to
phar:///uploads/evil.phar
, deserialize the malicious
object and then take over the server. WooCommerce contains classes that allow building POP Gadgets that
finally lead to arbitrary remote code execution.
The vulnerability was fixed in version 3.4.6
Timeline
Date | What |
---|---|
30/08/2018 | Reported the vulnerability to Automattic on Hackerone |
20/09/2018 | Automattic verifies the vulnerability |
11/10/2018 | Automattic releases a patch in version 3.4.6 |
16/10/2018 | Automattic says the patch was too restrictive, proposes another patch |
16/10/2018 | We verify the new patch |
18/10/2018 | Automattic releases the new patch in version 3.4.7 |
Day 4 - All in One SEO Pack
Stored XSS in 2 million WordPress sites
All in One SEO pack
has over 2 million active installations and suffered from a Stored XSS vulnerability. The vulnerability
can be exploited by attackers who gained control over a user account with at least
Contributor
privileges
on the target WordPress site. An attacker is able to inject arbitrary JavaScript code
into blog posts he creates and publishes. If an administrator opens a
malicious blog post, evil JavaScript code executes which compromises the target server.
Unsanitized post meta values are embedded into HTML markup
Responsible lines of Code
|
|
All in one SEO Pack stores meta information about each article of a WordPress site.
This meta information is displayed each time a post is edited. Plugin developers can add post meta to a post
with the function add_post_meta()
and retrieve them with
get_post_meta()
. Post meta information are
stored in the database as key, value pairs. in this example, the meta value with the key
_aioseop_opengraph
is retrieved.
In this case, the meta value is an associative array that stores options. Depending on the type
of the meta entry (e.g. HTML or date), it will be rendered differently.
In WordPress, post meta entries should not be trusted as any user can set them to arbitrary values.
In this case, nothing stops an attacker from overwriting the post meta
entry with the key _aioseop_opengraph
with an option of the
type html and set the value to <script>evilCode();</script>
.
The value would then be
outputted unsanitized.
Timeline
Date | What |
---|---|
25/10/2018 | Reported the vulnerability to the vendor via their support email address. |
25/10/2018 | The vendor replies and says they will investigate. |
22/11/2018 | Asked the vendor for progress on the patch. Replies with a patch proposition. |
06/12/2018 | The vendor releases a patch. |
Day 5 - Redirection
CSRF to RCE in 1 million WP sites
Redirection is one of the
most popular WordPress plugins and has over 1 million active installations. It allows site owners
to easily create redirections. For example, a site owner may use the plugin to redirect all users that visit
the URL example.com/someurl
to example.com/anotherurl
.
The plugin suffered
from a critical CSRF vulnerability that allows remote attackers to create a
shell.php
on
the target server and execute arbitrary code. The only requirement for successful exploitation is
that an administrator
of the target site visits a malicious website set up by the attacker. The victim does not have to
click anything on the
malicious website in order to trigger the exploit.
Our leading SAST solution RIPS was able to find the file creation vulnerability automatically within 2 minutes.
Proof of concept video
Each WordPress installation has it's own REST API that can be used by plugin developers. Redirection
also uses this REST API and adds it's own REST endpoint URLs. To update a redirection, for example
the one with the ID 1, a POST request is sent to the
URL example.com/wordpress/wp-json/redirection/v1/redirect/1
.
The WordPress
core securely performs a CSRF validation check when calls to the REST API are made.
However, the Redirection plugin also registers an ajax callback that serves as a proxy. Instead of calling the REST API directly, the ajax callback is executed and parses some POST parameter and then calls the same methods that would have been called by the REST API. The purpose of this callback is to make sure that the plugin works even if administrators disabled the REST API on their server. This ajax callback is not CSRF protected.
|
|
This means an attacker can perform any actions the REST API of Redirection offers. This
allows him to update any setting of the plugin with arbitrary values.
Redirection can use .htaccess
files for Redirections.
Administrators can specify the path and filename of the .htaccess file Redirection
should use. An evil administrator could simply set the filename of the .htaccess file to
shell.php
. He then sets up
a new redirection with the url example.com/<?php evilCode(); ?>
,
which then gets written to shell.php
. When he then makes a
request to shell.php, the evil code will be
executed, resulting in arbitrary code execution.
The vulnerability was fixed in version 3.6.4
Timeline
Date | What |
---|---|
14/11/2018 | Reported the vulnerability to plugins@wordpress.org because no reply was received from the plugin author |
14/11/2018 | A WordPress security team member replies and says he forwarded the vulnerability report to the author |
14/11/2018 | The author releases a patch in version 3.6.4 on the same day. |
Day 6 - WooCommerce #3
Privilege Escalation in 4 million eCommerce sites
WooCommerce, the most popular
eCommerce plattform on the internet with over 4 million active installations
suffered from an arbitrary file deletion vulnerability that allowed attackers in control of a user account
with Shop manager
privileges on the target online shop to delete any
file on the remote server. This allows an attacker to delete certain files containing security checks. Without
these security checks in place, the evil shop manager can then take over any administrator account.
Once access to the administrator account is gained, the
attacker can execute arbitrary code on the target server, leading to a full compromise of the target store.
Our leading SAST solution RIPS was able to find the vulnerability automatically within 2 minutes.
Proof of Concept video:
The vulnerability was fixed in version 3.4.6
.
Timeline
Date | What |
---|---|
30/08/2018 | Reported the vulnerability to Automattic on Hackerone |
11/09/2018 | Automattic verifies the vulnerability |
11/10/2018 | Automattic releases a patch in version 3.4.6 |
Day 7 - Toolset Types
Privilege escalation from Subscriber to Admin in 200.000 WordPress Sites
Toolset Types is a plugin that allows site owners to customize their sites functionality by adding new, custom post types and meta fields. It has over 200.000 active installations. Due to a misuse of the WordPress filter API, it was possible for attackers to escalate their privileges from any type of account on the website to administrator privileges with a single request. If the plugin was used in combination with a plugin such as WooCommerce or BuddyPress, unprivileged attackers are able to perform a full site takeover.
The following paragraphs will explain how returning the wrong value from a filter function can lead to severe security issues in WordPress.
Responsible lines of code
|
|
The function set_screen_options()
is a function that gets
called when users update screen settings. Screen settings define for example how many
posts a user wants to see on each page or how many search results he wants to see on a
search result page. This information is stored in the database as user meta information.
User meta information is updated with update_user_meta()
.
The function takes 3 parameters: The user ID of the user who's meta information should be
updated, the key of the meta information (e.g. twitter_url
,
number_of_logins
or posts_per_page
).
The third parameter is the new and desired value of the meta key.
The function works by taking two POST parameters: the meta key that should be updated and the
value of it. This is a dangerous thing to do for the following reason:
The user's role and privileges are also stored as user meta information. The user meta entry with the key
wp_capabilities
defines which
capabilities the user has. In order to prevent users from simply setting
$_POST['wp_screen_options']['option']
, which is the meta key that will
be updated, to wp_capabilities
, and giving themselves admin permissions,
a switch statement on the meta key (stored in $option
) is put in place.
The meta information will only be updated if the meta key matches one of the WordPress core screen
options, such as posts_per_page
. If it matches
none of the core options, the default case is reached. Here, the function
apply_filters()
is called and the meta information will only be updated
if the return value of that call is not false
.
Filters in WordPress allow plugins to modify the behavior of WordPress. If a plugin developer
wants to create new screen option, he adds a filter function to the
set-screen-option
filter. Plugins can add filter functions to a
filter by using the add_filter($filter_name, $function_name);
.
The first argument to that function is the name of the filter, for example
set-screen-option
. The second parameter is the name of a function
that should be called when the filter is applied via apply_filters()
.
The following is an example of the correct usage of the set-screen-options
filter. If the $option
should be allowed, because
the plugin wants to use it, it will return the new value. Otherwise, the filter function
returns false, which tells the set_screen_options()
function
to return and not update the user meta.
|
|
If no filter function is added to the set-screen-option
filter,
false
will be returned, thus set_screen_options()
will return and
the call to update_user_meta()
is never reached. This means a plugin that adds a
filter to set-screen-option
and returns
the value unmodified has to be installed in order for this to be exploitable. An example for such a plugin
is Toolset Types.
The following code snippets shows the vulnerable filter added by Toolset Types
|
|
The filter is vulnerable because it simply returns the value unmodified. This allows an attacker to set
the target user meta key to wp_capabalities
and give himself administrator privileges.
The vulnerability was fixed in version 2.3.4
Timeline
Date | What |
---|---|
09/10/2018 | Reported the vulnerability to OnTheGoSystems via the contact form for vulnerabilities on their website |
09/10/2018 | OnTheGoSystems verifies the vulnerability |
11/10/2018 | OnTheGoSystems releases a patch in version 2.3.4 |
Day 8 - WP Smush
XSS to Object Injection in 1 million sites
Smush Image Compression and Optimization
is a plugin for WordPress that compresses uploaded images. It suffers from a Phar deserialization
vulnerability that can be exploited by attackers who have control
over a user account with at least Author
privileges on the target site.
Such access could be gained via means of XSS vulnerabilities. RIPS has detected
a reflected XSS vulnerability in the same version of WP Smush. The plugin is used in over more than
1 million WordPress sites.
When the two vulnerabilities are combined, an attacker can trick a user of a target WordPress site
into clicking a malicious link, which then executes evil JavaScript code that finally exploits the Phar
Deserialization.
Our leading SAST solution RIPS was able to find the vulnerability automatically within 2 minutes.
Unsanitized post meta is passed to file_exists()
Responsible lines of code
|
|
We have written a detailed blog post on how Phar Deserializations work in this article.
Whenever an image is uploaded to a WordPress site, the file is moved to the uploads directory (by default
wp-content/uploads
) and a post with the post type
attachment
is created internally to store a reference
to the uploaded image. The path to the file on the server is stored as post
meta information. Post meta information can be retrieved by calling
get_post_meta($post->ID, 'whatever_meta_key');
.
When this plugin
wants to know the path to images that should be smushed upfront, it will
pull the meta information with the key upfront_used_image_sizes
from the database.
This meta information can be set to arbitrary values by the owner of the image file.
This means the meta information that stores the path to the local file should under no circumstances
be trusted.
Phar deserializations occur if unsanitized user input is passed to functions such as
file_exists()
or is_file()
. Here, user input is received on the second line
via get_post_meta()
and is then
passed to file_exists()
. This then triggers the Phar Deserialization.
Date | What |
---|---|
21/08/2018 | Reported the reflected XSS vulnerability and Phar Deserialization via the support contact form of the vendor, along with PoC video. |
22/08/2018 | The vendor says both vulnerabilities require admin access. |
23/08/2018 | We send another email explaining what a reflected XSS vulnerability is and explain that the Phar deserialization does not require admin access. The vendor does not reply. |
22/11/2018 | We notify the vendor about upcoming disclosure |
10/12/2018 | The vendor releases a patch. |
Day 9 - Contact Form by WP Forms
Reflected XSS in 1 million WordPress Sites
Contact Forms by WP Forms is a plugin that allows WordPress site owners to easily create contact forms for their site. It has over 1 million active installations. The commercial version of the plugin suffered from a reflected XSS vulnerability. If an attacker can lure a victim administrator to click on a malicious link, a full site takeover can be performed.
Our leading SAST solution RIPS was able to find the vulnerability automatically within 2 minutes.
$_GET['date'] is embedded into JavaScript code without sanitization
Responsible lines of code
|
|
This is a JavaScript context based XSS attack. The user supplied parameter
date
is embedded into the JavaScript
code without any escaping. First of all, it is exploded. In this case,
-
is the delimeter. The values are then concatenated in a way
that they result in valid JavaScript code. However, this allows an attacker to simply supply
the input
1 - </script><script>evilCode();</script>
.
This allows him to execute his own, arbitrary JavaScript code and finally perform a full site takeover.
Timeline
The vulnerability was fixed in version 1.4.8
.
Timeline
Date | What |
---|---|
25/08/2018 | Reported the vulnerability to the vendor via their support email address |
27/08/2018 | The vendor confirms the vulnerability |
28/08/2018 | The vendor releases a patch for Contact Forms by WP Forms in version 1.4.8 |
Day 10 - WooCommerce #4
Arbitrary File Read in 4 million eCommerce sites
WooCommerce, an eCommerce plugin for WordPress used by over 4 million stores on the web suffered from a vulnerability that allowed attackers to read arbitrary files on the target server, allowing them to compromise the database of the server and take over the target store.
Attackers who gained control over a user account with the Shop manager
role on the target server can read
arbitrary files on the target server, including the wp-config.php
configuration file of WordPress. This file contains the database credentials of the target WordPress installation.
Once an attacker gains control over the database, he can
steal all data of the target shop and execute arbitrary code on
the target server by inserting malicious serialized strings into the database.
Proof of concept video
The vulnerability occurs because Shop managers can abuse a feature of WooCommerce. WooCommerce
allows vendors to sell downloadable products (e.g. sell a PDF download). Vendors don't
have to do anything besides creating such a new product and specifying the path and filename of the file to be
downloaded, for example /uploads/ebook-to-sell.pdf
. When a customer
then buys the product, the backend of the store will read the file specified by the vendor and make it available
to the customer to download.
The evil
Shop manager can create such a new downloadable product. However, instead of specifying a
harmless file such as /uploads/ebooks-to-sell.pdf
he can specify the absolute
path to the configuration file, e.g. //var/www/html/wordpress/wp-config.php
.
The vulnerability was fixed in version 3.4.6
Timeline
Date | What |
---|---|
30/08/2018 | Reported the vulnerability to Automattic on Hackerone |
11/09/2018 | Automattic verifies the vulnerability |
11/10/2018 | Automattic releases a patch in version 3.4.6 |
Day 11 - Jetpack
Stored XSS in 5 million WordPress sites
Jetpack is the fourth most used
plugin in the WordPress community and has over 5 million active installations.
RIPS detected a Stored XSS vulnerability that affects a module available to premium and professional users of
Jetpack. Attackers who gained control over an account on the target site with at least
Contributor
privileges were
able to inject arbitrary JavaScript code into the HTML markup of a blog post. Once the administrator
of the target site views the malicious blog post, evil JavaScript code is executed
which compromises the target server.
Our leading SAST solution RIPS was able to find the vulnerability automatically within 2 minutes.
Unsanitized post meta is embedded into HTML
Responsible lines of Code
|
|
Jetpack offers it's users to create products for their WordPress site. The products are stored
in the database as a post of the type jp_spay_product
. When any user then inserts the shortcode
[spay_product id="1"]
into a page or post, the function parse_shortcode will generate the HTML
markup of the product and replace the shortcode with it. The id attribute of the shortcode is the ID or number of the product.
Jetpack will store the price of the product as post meta information with the key
spay_formatted_price
in the database.
When the shortcode is parsed, Jetpack pulls the post meta information of the product with the corresponding ID with
get_post_meta($id, 'spay_formatted_price');
from the database.
Post meta values are not sanitized and contributors can use it to inject arbitrary HTML markup
and JavaScript code into the page.
The vulnerability was fixed in version 6.5
.
Timeline
Date | What |
---|---|
30/08/2018 | Reported the vulnerability to Automattic on Hackerone |
01/09/2018 | Automattic asks for more information on the vulnerability |
03/10/2018 | We provide more information |
04/09/2018 | Automattic proposes a patch |
04/09/2018 | We verify the patch |
05/09/2018 | Automattic releases a patch in version 6.5 |
Day 12 - Mailchimp
Reflected XSS in 1 million WordPress sites
Mailchimp is a popular service that companies can use to build email lists and launch fully automated email marketing campaigns. They also offer a a plugin called Mailchimp for WordPress which has over 1 million active installations. It suffered from a reflected Cross Site Scripting vulnerability. If an administrator of a target WordPress site running a vulnerable version of Mailchimp triggers the XSS payload, a full site takeover can be achieved.
The vulnerability occurs because Mailchimp used the dangerous WordPress functionadd_query_arg()
without sanitization.
Our leading SAST solution RIPS was able to find the vulnerability automatically within 2 minutes.
add_query_arg() returns user input without sanitization
Responsible lines of code
|
|
add_query_arg()
takes the current request URI (e.g
example.com/?arg=true
and adds arguments to it. For example,
the call add_query_arg( array('anotherArg' => 'someText') );
would return the URL example.com/?arg=true&anotherArg=someText
.
The security issue lies in the fact that the WordPress function takes the user controlled
$_SERVER['REQUEST_URI']
, adds the specified parameters and then returns
the resulting URI unsanitized. The WordPress documentation states that the return value should be
sanitized with the WordPress function esc_url()
.
The simple payload for exploitation would be:
example.com/?arg=true&"<script>alert(/PoC/)</script>
The vulnerability was fixed in version 4.1.7
.
Timeline
Date | What |
---|---|
07/09/2017 | Reported the vulnerability to the vendor |
08/09/2017 | The vendor acknowledges the vulnerability |
11/09/2017 | The vendor releases a patch in version 4.1.7 |
Day 13 - WooCommerce #5
Privilege escalation in 4 million eCommerce sites
WooCommerce is the most
popular eCommerce plattform on the internet with
over 4 million active installations. It suffered from a privilege escalation vulnerability that allows
attackers who are in control over an account with Shop manager
privileges
on the target site to change the password and email of the admin account.
The vulnerability occurs because WooCommerce can be managed in two ways: Via the admin dashboard and
REST API. Shop managers
are not able to update the user accounts of administrators in the admin dashboard because security
checks are in place. However, these checks were not made
in the REST API of WooCommerce.
Once an admin account of a WordPress site is compromised, a full site takeover and in most cases arbitrary remote code execution can be achieved.
Proof of concept video
The vulnerability was fixed in version 3.5.1
.
Timeline
Date | What |
---|---|
12/10/2018 | Reported the vulnerability to Automattic on Hackerone |
18/10/2018 | Automattic verifies the vulnerability |
31/10/2018 | Automattic releases a patch in 3.5.1 |
Day 14 - All in One WP Security & Firewall
Phar Deserialization in 700.000 sites
The WordPress security plugin All in One WP Security & Firewall is vulnerable to a Phar Deserialization. Although only administrators can trigger the vulnerability, the Phar deserialization might serve as a bypass for hardened WordPress installations. By default, administrators of a WordPress site can edit plugin files directly and download plugins from the WordPress plugin repository. If an attacker gains control over the admin account of the target site, he can abuse these features and write arbitrary PHP code to the server. It is recommended that administrators disable this functionality to ensure that even if their account gets compromised attackers can't just execute arbitrary PHP code on the server. The Object Injection resulting from the Phar Deserialization might allow attackers to bypass the hardening and still take over the site. Affected are over 700.00 sites.
Our leading SAST solution RIPS was able to find the vulnerability automatically within 2 minutes.
Responsible lines of code
|
|
We have written a blog post that explains
Phar Deserializations, a new exploitation technique in PHP. You can
read it here.
In this case the sink is
file_get_contents()
. The vulnerable functionality allows administrators to restore the .htaccess
file of the server from a local file. The filename of the local file to be restored
from is the vulnerable parameter and is under full control of the attacker. This can, under certain circumstances, also
be leveraged to arbitrary remote code execution. The evil administrator
could simply upload a malicious .htaccess file to the server as a htaccess.txt
and restore it. This way he can use arbitrary apache2 directives.
Timeline
Date | What |
---|---|
25/10/2018 | Reported the vulnerability to the support email address of the vendor. No reply |
22/11/2018 | Asked for progress and notified the vendor of another vulnerability. |
Day 15 - W3 Total Cache
Reflected XSS in 1 Million WordPress sites
The caching plugin W3 Total Cache suffered from a reflected XSS vulnerability. The plugin has over 1 million active installation. For the vulnerability to be exploitable, the administrator of the target site must have the Google Analytics functionality of W3 Total Cache enabled. Once an administrator of a WordPress site triggers a XSS payload, arbitrary remote code execution can be achieved in most cases.
Our leading SAST solution RIPS was able to find the vulnerability automatically within 2 minutes.
$_GET['extension'] is embedded into JavaScript code without sanitization
Resonsible lines of code
|
|
$_GET['extension']
is embedded into JavaScript code.
By simply escaping the function call, a user can execute arbitrary JavaScript code.
By setting $_GET['extension']
to
')}; evilCode(); //
.
Timeline
Date | What |
---|---|
26/02/2018 | Contacted the author through the contact form on their website. No reply. |
Day 16 - WooCommerce #6
Unpatched Privilege Escalation in WooCommerce and WordPress Importer
WooCommerce is the most
popular eCommerce plattform on the web and has over 4 million active installations. It suffers from an unpatched
Object Injection vulnerability that can be exploited by attackers who are in control of a user account with
Shop manager
privileges on the target site.
The issue occurs because Shop managers have the import
capability,
which means they can use the native WordPress importer to upload XML files and import
posts and pages. The WordPress Importer
is a plugin by wordpress.org and has over 4 million active installations. If it is installed, evil Shop
managers can simply upload a malicious XML file and import it. The
WordPress importer allows users to have serialized PHP strings in the
import files and will unserialize them, which leads to PHP Object Injections.
This is in itself not a high security risk because only administrators
should be allowed to use the importer. However, WooCommerce also allows
Shop managers
to use the import functionality. Since WooCommerce contains classes that
allow building a POP chain that leads to arbitrary code execution, a privilege escalation and full
site takeover is possible. Automattic, the company behind WooCommerce did not remove
the Shopmanager's capability to use the importer when we reported it.
Timeline
Date | What |
---|---|
14/09/2018 | Reported the vulnerability to Automattic on Hackerone |
20/09/2018 | Automattic says the deserialization happens in a third party software and closes the report. |
Day 17 - WordPress Core
WordPress Core Post Type privilege escalation
Our security researchers have identified a logic flaw in the way WordPress handles posts that allows for privilege escalation exploits in hundreds of plugins and the WordPress core itself.
Day 18 - Contact Form 7
Arbitrary File Read in 5 million WordPress sites
Contact Form 7
is the most popular WordPress plugin and is used by over 5 million WordPress sites.
The plugin suffered from a vulnerability that allowed attackers
in control of a user account with at least Contributor
privileges to
read arbitrary files on the server, including the WordPress configuration file wp-config.php
, which
stores the database credentials of the WordPress installation of the target site. With this information, an attacker can
perform a full site takeover and in most cases execute arbitrary code on the target machine.
Proof of concept video
Contact Form 7 is a plugin that allows site owners to create contact forms for their WordPress sites
and define what information
visitors of the page should enter into the Contact Form. If the site owner wants to have a contact
form that asks for the full name, the email address of the visitors and what their issue is
(for example if the contact form serves as a form
to ask questions to developers on a support site). When a visitor then fills in his information and clicks
on Submit
,
Contact Form 7 will process the user input and sends the site owner an email with the information the user entered.
Another feature of Contact Form 7 are Local attachments
. Local attachments allow
a site owner to specify files on the server running the WordPress installation to be sent as an email attachment with each email that
was generated by a visitor filling out the contact form.
However, this feature could be abused by attackers. An evil attacker was able to create a new contact form,
set the email to which the information should be sent to, to his own and specify that the local attachment
should be the wp-config.php
file. The attacker would then simply submit the new
Contact Form and receive the wp-config.php
file as an email attachment.
The vulnerability was patched in version 5.0.4
.
Timeline
Date | What |
---|---|
31/08/2018 | Reported the vulnerability to the plugin author |
04/09/2018 | A patch is released in version 5.0.4 |
Day 19 - Regenerate Thumbnails
File Delete to RCE in 1 million WordPress sites
Regenerate Thumbnails is a
WordPress plugin with over 1 million active installations. It allows site owners to regenerate the thumbnail
sizes of already uploaded images.
Attackers in the user role of at least an Author
on the target site can delete arbitrary
files on the underlying server. We have demonstrated
in a blog post
how an arbitrary file deletion vulnerability in WordPress can lead to Remote Code Execution.
By deleting the main configuration file wp-config.php
of the target WordPress site,
WordPress will be unable to connect to the database and
prompts the next user with the installation prompt. This is because WordPress acts as if it hadn't been
installed if the wp-config.php
is missing. The
attacker could then simply re-install WordPress and then execute arbitrary code on the machine.
Our leading SAST solution RIPS was able to find the vulnerability automatically within 2 minutes.
User controlled get_post_meta is passed to wp_delete_file()
Responsible lines of code
|
|
Whenever an image is uploaded to a WordPress site, the file is moved to the uploads directory (by default
wp-content/uploads
) and a post with the post type
attachment
is created internally to store a reference to
the uploaded image. The path to the file on the server is stored as post
meta information. Post meta information can be retrieved by calling
get_post_meta($post->ID, 'whatever_meta_key');
.
This meta information can be set to arbitrary values. This means the meta information
that stores the path to the local file should under no circumstances
be trusted.
When Regenerate Thumbnails wants to regenerate a specific image or
attachment
, it will pull post meta information
from the database on line 2.
The post meta information requested has the key _wp_attachment_metadata
,
which stores data such as the path to modified versions of the image on the target server.
wp_delete_file()
. This means an attacker could simply update
the post meta information
and set the filepath to ../wp-config.php
, which would result in the
main configuration file being deleted.
Timeline
Date | What |
---|---|
25/10/2018 | Reported the vulnerability to the plugin author via the Contact Form on their website |
30/10/2018 | The plugin author replies and says his going to patch. |
13/12/2018 | The vulnerability becomes no longer exploitable with WordPress 5.0.1. |
Day 20 - WooCommerce #7
RCE in 4 million eCommerce sites
This is a bypass for the patch for the Phar Deserialization described on day 3. As a reminder,
Phar Deserializations occur if unsanitized user input
is passed to functions such as is_file()
or
file_exists()
.
You can read up on how exactly this vulnerability type works here.
WooCommerce suffered from a
Phar deserialization
in the CSV import function. When a CSV file should be used to import products, attackers were able to set
the path of
the CSV file to be imported. Instead of telling the server to use for example
uploads/import.csv
, an attacker was able to tell the server
to import the file phar://malicious.phar
. This would then
trigger the Object Injection of the Phar Deserialization.
To prevent this, WooCommerce added the function is_file_valid_csv()
.
|
|
This function will check if the target file is an absolute path and only then returns true.
ABSPATH
is the absolute path of the target WordPress installation (e.g.
/var/www/html/wordpress/
).
However, this check is only performed if the call to apply_filters()
returns true.
apply_filters()
works by calling all functions that were added to this filter with
add_filter()
. An example of this is given below
|
|
apply_filters()
takes two parameters: The filter name and a default value.
It will then call all functions that have been added with add_filter()
and return their return value.
If no filters are added, the default value is returned. In the example of WooCommerce, this would be
true and the check will be performed by default. The only way to bypass the check is to add a filter
function to the filter woocommerce_product_csv_importer_check_import_file_path
that returns false.
Filters are a part of the WordPress Core and allow modification of data by plugins. If a developer wants
to write a plugin for WooCommerce and wants to modify the behavior of the
import function, he would first have to add a filter to
woocommerce_product_csv_importer_check_import_file_path
which
returns false, so that no check
is performed. If such a plugin was installed, the Phar deserializtion would still work
because no check would be performed. However, the following bypass allows to add a filter function
that returns false without installing another plugin.
WooCommerce offers users a feature called Webhooks. The purpose of Webhooks are to send
the administrator of the shop running WooCommerce email notifications when selected events happen.
For example, a Shop manager might specify that he recieves an email every time a customer buys
a product with a specific product ID. This is implemented internally by adding a filter function to the event.
When for example the site should send an email notification each time the product with the ID 5 is
bought, it will add a filter function to the filter purchase-product-5
, which
is executed every time that specific product is bought. Within the filter function all the email processing
happens.
Shop managers can specify the filter name they want to hook in. This allows evil Shop managers to add a
filter function to the woocommerce_product_csv_importer_check_import_file_path
filter.
This means that the return value of the Webhook filter function is used instead of the default value
true
. The Webhook function returns NULL
, which is
casted to false
so the call to
apply_filters()
returns false
and therefor the check
is never executed.
The vulnerability was fixed in version 3.5.1
.
Timeline
Date | What |
---|---|
12/10/2018 | Reported the vulnerability to Automattic on Hackerone |
18/10/2018 | Automattic verifies the vulnerability |
31/10/2018 | Automattic releases a patch in 3.5.1 |
Day 21 - WP Fastest Cache
SQL Injection in 700.000 WordPress sites
WP Fastest Cache is a
caching plugin for WordPress with over 700.000 active installations. It was vulnerable to a SQL Injection.
The vulnerability was exploitable by attackers who had any type of account on the target website
running WP Fastest Cache, including customers of a store or forum users.
By exploiting the vulnerability, an attacker could steal all data of the target WordPress site
and take over the administrator account, which would then lead to a
full site takeover.
Our leading SAST solution RIPS was able to find the vulnerability automatically within 2 minutes.
User input is embedded into a SQL query and is sanitized with the wrong function
Responsible lines of code
|
|
The SQL Injection occurred because esc_sql()
only works when the user input
is wrapped around single quotes. esc_sql()
will escape single quotes (turns '
into
\'
) so that the user input won't break the string.
However, in this context the value in the
SQL query is an integer and is not wrapped around single quotes. The attacker
can simply supply the string 1 AND 1=0...
and execute
SQL queries. The correct way to have handled
this user input would have been to cast it to an integer.
The vulnerability was fixed in version 0.8.7.5
Timeline
Date | What |
---|---|
17/11/2017 | Reported the vulnerability to the vendor |
17/11/2017 | The vendor asks for more information. We send more details. |
20/11/2017 | The vendor releases a patch in version 0.8.7.5 |
Day 22 - WP Job Manager
Unprivileged Phar Deserialization in 100.000 WordPress Sites
WP Job Manager is a plugin by Automattic with over 100.000 active installations. It allows site owners to easily create job listings on their WordPress site. Attackers were able to sign up and upload a company logo for their listing. This upload functionality was vulnerable to a Phar Deserialization, which left over 100.000 sites vulnerable to a PHP Object Injection that results from Phar Deserializations. If other plugins are installed that make the Object Injection exploitable, a full takeover by unauthenticated remote attackers was possible.
Our leading SAST solution RIPS was able to find the vulnerability automatically within 2 minutes.
The user controlled $attachment_url is passed to the vulnerable function wp_generate_attachment_metadata()
Responsible lines of code
|
|
We have written a blog post that explains
Phar Deserializations, a new exploitation technique in PHP. You can read it here. In this case the sink is
within the wp_generate_attachment_metadata()
function. This WordPress function will internally call getimagesize()
, which is
vulnerable to Phar deserializations. This is only possible because attackers are in full control of the $attachment_url
parameter.
The vulnerability was fixed in version 1.31.3
Timeline
Date | What |
---|---|
21/08/2018 | Reported the vulnerability to Automattic on Hackerone |
23/08/2018 | A patch is released in version 1.31.3 |
Day 23 - WooCommerce #8
Stored XSS in 4 million WordPress sites
WooCommerce suffered from a
Stored XSS vulnerability that allows attackers who took control over
an accout with Shop manager
privileges on the target site to hijack
the session of the admin user and perform a full site takeover.
The vulnerability occurs because of a common design flaw in application security. When data is stored in the database, it is sanitized correctly and secure. The application then trusts the data, since it was sanitized when it was initially stored, and then uses it without any further security checks when pulling it from the database. However, sometimes data can be modified that is already stored in the database. This happened in WooCommerce. When an evil Shop manager wants to create a new Order from within the Admin dashboard, all input is sanitized and stored safely. If the Shopmanager creates the order via the REST API of WordPress, the data will not be sanitized. Since WooCommerce trusts all data in the database, the Stored XSS occurs.
Timeline
Date | What |
---|---|
12/10/2018 | Reported the vulnerability to Automattic on Hackerone |
18/10/2018 | Automattic verifies the vulnerability |
31/10/2018 | Automattic releases a patch in 3.5.1 |
Day 24 - WordPress.org
Wormable Stored XSS on WordPress.org website
Our security researchers have identified a critical stored XSS vulnerability on the plugin repository on WordPress.org. In wrong hands, the vulnerability could have been exploited to infect all WordPress plugins with malicious code.