WordPress Plugins Research

Manual Source Code Review of WordPress Plugins

You can watch the presentation here: Manual Source Code Review on WordPress Plugins


WordPress plugins are packages of code that can be added to a WordPress website to extend its functionality. They are designed to enhance the core features of WordPress.

Manual source code review(SCR) is a process of manually examining the source code of an application or software to identify any security vulnerabilities, bugs, or code quality issues.

This blog focuses on different approaches to manually reviewing WordPress Plugins, some exciting scenarios/vulnerabilities reported, and using PHPCS or semgrep ruleset for streamlining some of the processes.

Setting up the environment



Installing the Plugin and Setting up the Debugger

  • Set up the WordPress and download the WP Plugins from the official WordPress plugin page into the “/wp-content/plugins” directory.

  • You can also download the plugin directly from the plugins page available in the wp-admin section.

  • Activate the installed plugin by navigating to the “Installed plugin” section.

  • Open the installed plugin directory into the VSCode.

  • Install the XDebug for debugging the PHP code.

  • You can also use the XDebug wizard for installing the XDebug to ease the installation or if you are facing any problems.

  • Enable the Xdebug and add the develop and step debugging mode.

  • Below is the configuration file’s content for XDebug

  • Install the PHP Debug Extension in the VSCode, create a “launch.json” file debugging, and start debugging.

  • If the installations are proper, you will see that the debugger has started.

Reviewing the code

Entry Point of the plugin

Every plugin has one main PHP file in which the header fields are mentioned as comments.

This is how WordPress knows it’s a plugin; you will see the same metadata in the “plugin” section on the admin page.

Plugin Name” is a mandatory field, while other fields are optional in the Header Field.

Code Structure

WordPress defines no proper structure to develop a plugin. That’s why you will often see different structures followed for developing different plugins.

Some of the common structures are:

Techniques for looking into the code

Below are some quick ways to look into the plugin for specific vulnerabilities or just to get an idea of the security standards of the plugins.

  • Authentication

    Authentication is handled by the WordPress core itself for all the plugins.

  • Authorization

    wp_ajax_{action} and wp_ajax_nopriv_{action} hooks are used to handle the custom AJAX call from the “wp-admin/admin-ajax.php” page.

    wp_ajax_{action}: Any authorized user can fire this hook.

    wp_ajax_nopriv_{action}: This hook is for an unauthorized user.

    add_action: This function adds the callback function to the hook.

    action: This parameter should be mentioned in the request in order to call the defined hook defined in the plugin.

    Action param◎ /WordPress/wp-admin/admin-ajax.php#L31

    Nonce: This randomly generated string is used to prevent vulnerabilities like CSRF. This can be used more than once and has a default expiry of one day(24 hr).

    This token is tied to the currently logged-in user. That’s why you will often observe this token being used as authorization in different endpoints in the code. However, WordPress mentions that this should not be used as an authorization check.


    wp_create_nonce: This function is used to create the nonce.

    check_ajax_referer: This function is used to verify the nonce in the AJAX request. Observe the last argument($die) of this function. By default, it’s set to True. If it’s set to False, it will not cause the script to die, making the check useless.

    Explore different endpoints and examine the implementation of authorization in the code.

    If the developer is using nonce for authorization, examine where precisely the nonce is getting created using wp_create_nonce and any possibility of leaking the nonce.

    You can refer to Nonce leak+ Any authorized user calling the endpoints finding for one such scenario.

    WordPress Rest API

    rest_api_init hook is used for adding the API endpoints.

    register_rest_route function is used for registering the custom routes. Look into the permission_callback function if implemented to check for the authorization part.

    The defined endpoint is public if the permission callback is not defined or returns true.

  • SQL Injection (SQLi)

    Examine different methods of wpdb class, which is used for interacting with the databases.

    Some of the methods like $wpdb->prepare() are safe if used correctly, and other methods like $wpdb->query() are unsafe.

    All the unsafe methods are found in the WP Plugin SQLi semgrep rule.

    WordPress core, by default, adds the magic quotes in the request. This behavior prevents SQLi in some of the plugins.

    Magic Quotes


    I have seen some of the plugins vulnerable to SQLi, but I could not exploit it due to this behavior.

    Developers usually use wp_unslash to remove the extra slash(escaping) added by WordPress.

    Another way is to turn on the logging of the MySQL database.

    Include the below system variables in the MySQL configuration file.



    By default, mysql.conf file is located in the /etc/mysql directory in Linux OS.

    MySQL Conf

    Monitor the log file for some unique string like “uniqueString”

    Now explore the plugin’s functionality, and in the input fields, enter some unique String like “uniqueString.”

    Observe the SQL queries and your payload “uniqueString” in the logs.

    Sql logs

    You can try to break the formed SQL queries shown in the logs depending on the queries using chars like single quotes(’), double quotes(”), etc., or directly appending the keywords like “union.”

    Observe whether the payload like “ uniqueString’ ”, “ unqiueString” ” is getting properly escaped or not for detecting and exploiting the SQLi.

    Sql logs

  • Cross-Site Scripting (XSS)

    By default, users with admin or Editor roles are allowed to add unfiltered HTML.

    When testing for XSS, make sure that you test with other roles like contributor, author, etc.

    You can also disable the default behavior for Admin and Editor by placing the below content in the wp-config.php file

    define( 'DISALLOW_UNFILTERED_HTML', true );

  • Functionality Wise

    You can start exploring the plugin functionality and see if something looks interesting, like Updating any value, importing or exporting the files, Adding custom snippets, etc.

    Observe the endpoint responsible for the same and start looking into the source code.

    Set up some breakpoints in the code for interacting with the code if some of the code/logic implemented is not easy to understand.

  • PHPCS Filters

    Most of the plugins use PHPCS to maintain the coding standard.

    You can look for strings like “phpcs:ignore”, “phpcs:ignoreFile”, “phpcs:disable”, etc. in the plugin code. If the developer uses PHPCS and the ruleset has found some violations, the above filters ignore the violations.

    This can be helpful in cases where the PHPCS has reported any possible security-related issues, and the developer has used the filters to ignore the issue.

    All the supported filters can be found here

  • Additional Information

    Below are some more functions which are frequently used in the WP plugin development.









Vulnerabilities Reported(8 CVEs)

I reported 12 vulnerabilities after manually reviewing different plugins, and 8 of them were triaged by the WPScan team. Other reported vulnerabilities were intended features in the plugin or required another vulnerability for the impact.

You can have a look at the reported vulnerabilities with the detailed report and the vulnerable code snippets available at the below GitHub link.


Interesting scenarios

Below are some exciting scenarios I came across, which I think are hard to find without the manual SCR.


PHP Code Sniffer

It’s a tool that detects violations of the rules defined in the ruleset.

WordPress-Coding-Standards has some security relates PHPCS rulesets that can be used for detecting possible security-related issues.

./vendor/bin/phpcs --standard=WordPress --sniffs=WordPress.CSRF.NonceVerification,WordPress.DB.PreparedSQL,WordPress.DB.PreparedSQLPlaceholders,WordPress.DB.RestrictedClasses,WordPress.DB.RestrictedFunctions,WordPress.Security.NonceVerification,WordPress.Security.PluginMenuSlug,WordPress.Security.SafeRedirect,WordPress.Security.ValidatedSanitizedInput,WordPress.WP.PreparedSQL,WordPress.XSS.EscapeOutput /path/to/plugin/

Semgrep Rules

I contributed to the WordPress plugin semgrep rules based on the WPScan-Cheat-Sheet-Wiki

You can find all the rules in a single ruleset WordPress

Run the semgrep rules on any plugins for reviewing the plugins for possible security-related vulnerabilities.

Semgrep result will give you an idea of the code standard of the plugin and possible vulnerable locations where you can directly look for the vulnerability.

You can run all the WP Plugins semgrep rules after setting up the semgrep by running

semgrep --config p/wordpress

Observe the path of all the WP Plugins rules. This is done to limit the rules to WordPress plugins only.

Semgrep Paths

Run the semgrep from the one directory before the wp-content directory to follow the path structure.

If there are multiple plugins inside the plugins directory and you want to run the rules for one of them, you can add the other plugin directory in the “.semgrepignore” file to ignore the other plugins.

Reporting the Vulnerabilities

You can directly contact the developer or report the vulnerability to the WPScan team.

You can read more about the WPScan submission terms here.

About the Author

Sanjay Das(p3n7a90n)

Security Consultant @payatu

Website: https://p3n7a90n.github.io/

Load Comments?