New release : CTI Report - Pharmaceutical and drug manufacturing 

                 Download now

A small slam of WordPress CVEs: vulnerable plugins

A small slam of WordPress CVEs: vulnerable plugins

Three vulnerabilities present in plugins WordPress vulnerabilities impacting over 100,000 web applications were recently discovered within Intrinsec's Assessment team. These security flaws allow attackers to carry out various attacks: one enables SQL injections that can lead to the deletion of arbitrary files, another enables XSS attacks, and the last exploits authorization flaws leading to bank identity theft.

A WordPress plugin is an additional module that can extend the functionality of a WordPress-based web application.

Following these vulnerability discoveries, the Intrinsec CERT communicated the advisories (available below) to the publishers of plugins as well as to WordPress and WordFence. The processing of these notices led to the issuance of three CVE numbers, which are the subject of this article.

Listed in the "Injection" and "Broken Access Control" categories of the Top 10 OWASP 2021, These vulnerabilities reflect what is typically found in penetration testing services. This type of mission falls under the external penetration testing activities of the Evaluation division, where applications based on CMS Applications like WordPress are regularly audited. Technical testing follows the OWASP Testing Guide, enhanced with a CMS-specific methodology and internally developed tools for evaluating applications based on white-box CMSs—that is, applications with full access to the source code. This unique combination allows consultants to thoroughly analyze the security level of these applications.

From SQL injection to arbitrary file deletion

The WP-Bannerize plugin allows users to add banners to application pages. However, banner management is vulnerable to SQL injection. The affected functions correspond to the actions of modifying a banner (the "updateBannerFromLocal" function in the plugin's source code), moving it to the trash ("setBannerToTrash"), retrieving it from the trash ("unsetBannerToTrash"), and permanently deleting it ("deleteBanner"). They all share the same flaw: the absence of a filter for the user input "id". This attack vector allows a malicious user to inject code to modify the behavior of the SQL query. The code snippet below, corresponding to the "updateBannerFromLocal" function called when updating a banner, illustrates this vulnerability where the POST parameter "id" is included in the SQL query on line 5 without being filtered. This behavior is similar to that of the other vulnerable functions mentioned.

Excerpt from "Classes/wpBannerizeAdmin.php" – function "updateBannerFromLocal"«


Exploiting this type of vulnerability could lead to compromising the confidentiality of the application's database. However, it's possible to go further. The function called when permanently deleting a banner, "deleteBanner," whose code is shown below, contains two SQL queries on lines 5 and 7, each using the same unfiltered user input "id" seen previously. When the first query returns 1, the condition on line 6 is met, and the second SQL query is executed on line 7; its result is then passed as an argument to the file deletion function "unlink" on line 8.

Excerpt from « Classes/wpBannerizeAdmin.php » – function « deleteBanner »

Thus, by managing to design malicious code that returns the value 1 with the first request and then the path to a file chosen by the attacker with the second, the latter would then be deleted.

As part of the proof of concept, the development of the malicious code to be injected followed this reasoning:

  • By injecting a single malicious payload (payload) two different values must be obtained;
  • A difference identified between the two SQL queries where the payload is injected is the execution time;
  • Depending on when a request is executed, its behavior can be adapted: if the execution date is less than a given date, then behavior A is executed, otherwise behavior B is performed; ;
  • The time gap between the execution of the two queries can be controlled by the SQL function "sleep".

This reasoning led to the following result: during the attacker's POST request to T0, a reference date Tref is set 2 seconds in the future and the malicious SQL code includes the following condition:

  • If the current date T is earlier than Tref, then a 4-second pause is performed and the value 1 is returned;
  • Otherwise (current date T is later than T)ref) the path of the file to be deleted is returned.

Détail de l'exploitation de l'injection SQL menant à la suppression d'un fichier
Details of the SQL injection exploit leading to the deletion of a file

This vulnerability offers two key advantages for an attacker: it allows them to extract content from the application's database as an authenticated user with dashboard access, and also to delete files over which the web service owner has privileges. Deleting these files can render the site unavailable and lead to a denial-of-service attack, or it can bypass authorization restrictions by deleting the ".htaccess" file (for example, in the case of an Apache server), which defines certain accessibility properties.

XSS Reflected on the administrator dashboard

THE plugin FV Flowplayer Video Player allows you to embed videos within application pages. A statistics feature is available on the administrator dashboard page. fv_player_stats, however, the latter is vulnerable to reflected XSS attacks.

Excerpt from « view/stats.php« 

Indeed, the GET parameter "player_id" is used without verification or filtering of its content on line 7. An attacker could then inject arbitrary JavaScript code that would be integrated into the HTML code of the page generated by the server and then executed in the victim's browser. However, the variable "fv_single_player_stats_data" must be defined to fulfill the condition on line 4 and reach the vulnerable line 7. The constraints to be respected, as dictated on line 1, for this variable to be defined are:

  1. The GET parameter "player_id" must exist; ;
  2. The value of the GET parameter "player_id" must be such that the function intval($_GET['player_id']) returns a non-zero value.

This second constraint uses the `intval` function, which converts its argument into an integer value. For the argument to be valid—that is, for the returned value to be non-zero—the string passed as an argument simply needs to begin with a digit. The numerical value returned by `intval` will be the number preceding the string. If the string passed as an argument contains HTML code, this code will be inserted on line 7 and interpreted.

Détail de l'exploitation de la XSS
Details of XSS exploitation

An attacker could thus generate a link containing a malicious payload in the "player_id" field, which would execute in the browser of the victim who clicked the link. The targets of this attack are administrator users, as they are the only ones with access to the statistics page of this plugin. The malicious code could, without the victim's knowledge, trigger administrative actions such as the creation of an administrator account.

Lack of authorization leading to bank identity theft

THE plugin Stripe for WooCommerce expands the range of payment methods available for WooCommerce-based e-commerce sites. However, a lack of verification of capabilities allows any authenticated user to configure their own "customer_id". Indeed, when a user updates their profile data, the vulnerable "save" function, an excerpt of which is shown below, is called.

Excerpt from "/admin/class-wc-stripe-admin-user-edit.php"«

A user's "customer_id" corresponds to the identifier used for Stripe and is stored in the WordPress account settings. A user who saves payment methods in the WordPress application can then use them during a payment without re-entering their information. The "user_id" is the user's WordPress identifier. The "save" function allows users to modify the "customer_id" value for their own "user_id," except for administrators who can also modify other users' profiles. When the Stripe identifier is modified, the "save" function calls the "wc_stripe_save_customer" function on line 12 to update the value, and the "WC_Stripe_Customer_Manager::sync_payment_methods" function on line 27 to synchronize the payment methods associated with that account.

However, no verification at the level of the capabilities No action is taken on a user's account during the Stripe ID update process. An attacker could then modify their own "customer_id". By replacing this ID with that of another user, obtained through other attacks, they would gain access to the payment methods saved by the user legitimately linked to that "customer_id" during their next payment.

Impact de l'exploitation de la vulnérabilité
Result of exploiting the vulnerability

Exploiting this vulnerability would negatively impact the brand image of the e-commerce company, and would also imply a loss of confidentiality and data integrity.

For more information on external penetration testing services, contact us !

Article written by @Margaux Dabert, Security Consultant at Intrinsic