6,000 WordPress Sites Affected by Unauthenticated Critical Vulnerability in WP Job Portal WordPress Plugin


📢 Did you know Wordfence runs a Bug Bounty Program for all WordPress plugin and themes at no cost to vendors? Through October 14th, researchers can earn up to $31,200, for all in-scope vulnerabilities submitted to our Bug Bounty Program! Find a vulnerability, submit the details directly to us, and we handle all the rest. 


On August 7th, 2024, we received a submission for an unauthenticated Local File Inclusion, Arbitrary Settings Update, and User Creation vulnerability in WP Job Portal, a WordPress plugin with more than 6,000 active installations. This vulnerability can be leveraged to create malicious administrator users, and also can be leveraged to include and execute arbitrary files on the server, allowing for the execution of any PHP code in those files.

Props to Connor Billings who discovered and responsibly reported this vulnerability through the Wordfence Bug Bounty Program. This researcher earned a bounty of $813.00 for this discovery. Our mission is to Secure the Web, which is why we are investing in quality vulnerability research and collaborating with researchers of this caliber through our Bug Bounty Program. We are committed to making the WordPress ecosystem more secure, which ultimately makes the entire web more secure.

Wordfence Premium, Wordfence Care, and Wordfence Response users received a firewall rule to protect against any exploits targeting this vulnerability on August 19, 2024. Sites using the free version of Wordfence will receive the same protection 30 days later on September 18, 2024.

We contacted the WP Job Portal team on August 19, 2024, and received a response on the next day. After providing full disclosure details, the developer released the patch on August 21. We would like to commend the WP Job Portal team for their prompt response and timely patch.

We urge users to update their sites with the latest patched version of WP Job Portal, version 2.1.7 at the time of this writing, as soon as possible.

Vulnerability Summary from Wordfence Intelligence

Description: WP Job Portal <= 2.1.6 - Missing Authorization to Unauthenticated Local File Inclusion, Arbitrary Settings Update, and User Creation
Affected Plugin: WP Job Portal – A Complete Recruitment System for Company or Job Board website
Plugin Slug: wp-job-portal
Affected Versions: <= 2.1.6
CVE ID: CVE-2024-7950
CVSS Score: 9.8 (Critical)
CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Researcher/s: Connor Billings
Fully Patched Version: 2.1.7
Bounty Award: $813.00

The WP Job Portal – A Complete Recruitment System for Company or Job Board website plugin for WordPress is vulnerable to Local File Inclusion, Arbitrary Settings Update, and User Creation in all versions up to, and including, 2.1.6 via several functions called by the ‘checkFormRequest’ function. This makes it possible for unauthenticated attackers to include and execute arbitrary files on the server, allowing the execution of any PHP code in those files. This can be used to bypass access controls, obtain sensitive data, or achieve code execution in cases where images and other “safe” file types can be uploaded and included. Attackers can also update arbitrary settings and create user accounts even when registration is disabled, leading to user creation with a default role of Administrator.

Technical Analysis #1: Arbitrary Function Call in Controller Classes

Examining the code reveals that the plugin uses the checkFormRequest() function in the WPJOBPORTALformhandler class to handle form requests, which can call any function of the WPJOBPORTAL-prefixed controller class.

function checkFormRequest() {
    $formrequest = WPJOBPORTALrequest::getVar('form_request', 'post');
    if ($formrequest == 'wpjobportal') {
        //handle the request
        $modulename = (is_admin()) ? 'page' : 'wpjobportalme';
        $module = WPJOBPORTALrequest::getVar($modulename);
        $module = wpjobportalphplib::wpJP_str_replace('wpjobportal_', '', $module);
        wpjobportal::$_data['sanitized_args']['wpjobportal_nonce'] = esc_html(wp_create_nonce('wpjobportal_nonce'));
        WPJOBPORTALincluder::include_file($module);
        $class = 'WPJOBPORTAL' . $module . "Controller";
        $task = WPJOBPORTALrequest::getVar('task');
        $obj = new $class;
        $obj->$task();
    }
}

This function serves as the core and start of what creates many vulnerabilities.

Technical Analysis #2: Local File Inclusion

The arbitrary function call in controller classes can be used to load the WPJOBPORTALUserController, whose constructor invokes the handleRequest() function, which contains the following code snippets:

function handleRequest() {
    $layout = WPJOBPORTALrequest::getLayout('wpjobportallt', null, 'users');
    WPJOBPORTALincluder::include_file($layout, $module);

This sets the layout based on the wpjobportal request parameter and calls the include_file() function in the WPJOBPORTALincluder class, which includes the file using the following code snippet:

$file_path = self::getPluginPath($filename,'file');
if($wp_filesystem->exists($file_path)){
    include_once $file_path; //

The file inclusion is limited to PHP files in the vulnerability. This means that threat actors cannot exploit one of the most popular remote code execution methods via a log file poisoning attack. In addition, since the plugin also uses the file_exists() function for file checking, the other popular remote code execution method using wrappers is also not possible.

Nevertheless, an attacker has several options to include and exploit a malicious PHP file and execute it on the server. This can be achieved by chaining the attack and exploiting vulnerabilities in other plugins. However, it’s worth mentioning that the attack possibilities are limited. This vulnerability would likely be leveraged in a scenario where an attacker has access to upload a PHP file, but does not have direct access to the file to execute it. Additionally, there is a notable exploit possibility involving pearcmd.php, which is a common method for remote code execution in local file inclusion vulnerabilities.

Technical Analysis #3: Administrator User Creation

The arbitrary function call in controller classes can be used to invoke the saveconfiguration() function in the WPJOBPORTALConfigurationController controller class. Although this function is nonce protected, the nonce can unfortunately be obtained by unauthenticated attackers in the vulnerable version.

function saveconfiguration() {
    $nonce = WPJOBPORTALrequest::getVar('_wpnonce');
    if (! wp_verify_nonce( $nonce, 'wpjobportal_configuration_nonce') ) {
         die( 'Security check Failed' );
    }
    $data = WPJOBPORTALrequest::get('post');
    $layout = WPJOBPORTALrequest::getVar('wpjobportallt');
    $result = WPJOBPORTALincluder::getJSModel('configuration')->storeConfig($data);

This makes it possible for unauthenticated attackers to update the employer_defaultgroup and jobseeker_defaultgroup plugin settings, which are the roles associated with the “Employer” and “Job Seeker” job roles used in the user registration form handled by the wpjobportal_add_new_member() function, which contains the following code snippet:

$role = wpjobportal::wpjobportal_sanitizeData(WPJOBPORTALrequest::getVar('jobs_role') );

if (is_numeric($role)) {
    if ($role == 1) {
        update_user_meta($new_user_id, 'jobs_role', 'employer');
        $employer_defaultgroup = wpjobportal::$_config->getConfigurationByConfigName('employer_defaultgroup');
        wp_update_user(array('ID' => $new_user_id, 'role' => $employer_defaultgroup));
    } elseif ($role == 2) {
        update_user_meta($new_user_id, 'jobs_role', 'jobseeker');
        $jobseeker_defaultgroup = wpjobportal::$_config->getConfigurationByConfigName('jobseeker_defaultgroup');
        wp_update_user(array('ID' => $new_user_id, 'role' => $jobseeker_defaultgroup));
    }
}

When the default group is set to administrator, an attacker can register a new user with administrator privileges.

It’s worth noting that chaining the Local File Inclusion vulnerability allows the attacker to obtain the nonce, which is needed for registration.

As with any Privilege Escalation vulnerability, this can be used for complete site compromise. Once an attacker has gained administrative user access to a WordPress site they can then manipulate anything on the targeted site as a normal administrator would. This includes the ability to upload plugin and theme files, which can be malicious zip files containing backdoors, and modify posts and pages which can be leveraged to redirect site users to other malicious sites or inject spam content.

These series of vulnerabilities are similar to the ones we recently covered in the JS Help Desk plugin.

Disclosure Timeline

August 7, 2024 – We received the submission for the Local File Inclusion, Arbitrary Settings Update, and User Creation vulnerability in WP Job Portal via the Wordfence Bug Bounty Program.
August 16, 2024 – We validated the report and confirmed the proof-of-concept exploit.
August 19, 2024Wordfence Premium, Care, and Response users received a firewall rule to provide protection against any exploits that may target this vulnerability.
August 19, 2024 – We initiated contact with the plugin vendor asking that they confirm the inbox for handling the discussion.
August 20, 2024 – The vendor confirmed the inbox for handling the discussion.
August 20, 2024 – We sent over the full disclosure details. The vendor acknowledged the report and began working on a fix.
August 21, 2024 – The fully patched version of the plugin, 2.1.7, is released.
September 18, 2024 – Wordfence Free users will receive the same protection.

Conclusion

In this blog post, we detailed a Local File Inclusion, Arbitrary Settings Update, and User Creation vulnerability within the WP Job Portal plugin affecting versions 2.1.6 and earlier. This vulnerability allows unauthenticated threat actors to include and execute PHP files on the server, allowing the execution of any PHP code in those files, which can be used for complete site compromise, and makes it possible for an unauthenticated attacker to update the default group plugin settings, which can be used to create administrator accounts. The vulnerability has been addressed in version 2.1.7 of the plugin.

We encourage WordPress users to verify that their sites are updated to the latest patched version of WP Job Portal as soon as possible considering the critical nature of this vulnerability.

Wordfence Premium, Wordfence Care, and Wordfence Response users received a firewall rule to protect against any exploits targeting this vulnerability on August 19, 2024. Sites using the free version of Wordfence will receive the same protection 30 days later on September 18, 2024.

If you know someone who uses this plugin on their site, we recommend sharing this advisory with them to ensure their site remains secure, as this vulnerability poses a significant risk.

Did you enjoy this post? Share it!

Comments

No Comments

All comments are moderated before being published. Inappropriate or off-topic comments may not be approved.