WPSchoolPress <= 2.2.36 - Missing Authorization
Description
The WPSchoolPress plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 2.2.36. This makes it possible for authenticated attackers, with teacher-level access and above, to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=2.2.36# Research Plan: WPSchoolPress <= 2.2.36 - Missing Authorization ## 1. Vulnerability Summary The WPSchoolPress plugin for WordPress (versions up to 2.2.36) contains a Missing Authorization vulnerability. A specific AJAX function fails to perform a capability check (e.g., `current_user_can()`), allo…
Show full research plan
Research Plan: WPSchoolPress <= 2.2.36 - Missing Authorization
1. Vulnerability Summary
The WPSchoolPress plugin for WordPress (versions up to 2.2.36) contains a Missing Authorization vulnerability. A specific AJAX function fails to perform a capability check (e.g., current_user_can()), allowing authenticated users with the Teacher role (a custom role created by the plugin) to perform actions intended for administrators. The CVSS score of 4.3 (Integrity: Low) suggests the vulnerability allows for unauthorized modification of data or settings that do not compromise the entire system but still represent a privilege escalation.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Authentication: Authenticated (Teacher level access).
- Vulnerable Action: An AJAX action registered via
add_action( 'wp_ajax_...' ). - Preconditions:
- The WPSchoolPress plugin must be active.
- A user with the
teacherrole must be created.
- Payload Parameter: Likely a POST request containing an
action, anonce, and data to be modified (e.g.,id,setting_name,value).
3. Code Flow
- The plugin registers AJAX handlers, typically in
includes/wsp-ajax.phporlib/wsp-ajax.php(inferred). - The registration looks like:
add_action( 'wp_ajax_WSP_ACTION_NAME', 'FUNCTION_NAME' );. - The
FUNCTION_NAMEis invoked when a POST request is sent toadmin-ajax.phpwithaction=WSP_ACTION_NAME. - Inside
FUNCTION_NAME, the code checks for a nonce usingcheck_ajax_refererorwp_verify_nonce. - The Flaw: The function proceeds to execute logic (like database updates or deletions) without verifying if the user has the
manage_optionscapability or is an administrator. - The
teacherrole is allowed to accessadmin-ajax.php, so the request succeeds.
4. Nonce Acquisition Strategy
WPSchoolPress enqueues its nonces via wp_localize_script. To obtain a valid nonce for a teacher:
- Identify Shortcode/Page: The teacher dashboard is usually at a specific URL or generated via shortcodes like
[wsp_dashboard]. - Create Access Page: Ensure a page exists with the relevant shortcode so scripts are loaded.
wp post create --post_type=page --post_title="Dashboard" --post_status=publish --post_content='[wsp_dashboard]' - Navigate and Extract: Use the
browser_navigatetool to log in as a teacher and visit the dashboard. - Execute JS: Use
browser_evalto extract the nonce.- Variable Name: Based on WPSchoolPress source, check for
wsp_ajaxorwsp_vars. - Key: Common keys include
ajax_nonceornonce. - Command:
browser_eval("window.wsp_vars?.nonce")orbrowser_eval("window.wsp_ajax?.nonce").
- Variable Name: Based on WPSchoolPress source, check for
5. Exploitation Strategy
The goal is to perform an action a teacher should not be able to do, such as updating a system setting or deleting a student/teacher record.
Target Action (Inferred): wsp_delete_student or wsp_update_settings.
Step-by-Step Exploit:
- Identify Action: Search the plugin for AJAX actions lacking
current_user_can.grep -r "wp_ajax_" . - Verify Missing Auth: Check the handler function for the presence of
current_user_can. - Craft Request:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded,Cookie: [Teacher Cookies] - Body:
action=[VULN_ACTION]&nonce=[EXTRACTED_NONCE]&[PARAM_NAME]=[VALUE]
- URL:
Example Payload (Inferred - Deleting a student record):
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
action=wsp_delete_student&nonce=a1b2c3d4e5&student_id=2
6. Test Data Setup
- Activate Plugin:
wp plugin activate wpschoolpress - Create Student: Use the plugin UI or WP-CLI to create a student record (ID 2).
- Create Teacher: Create a user with the
teacherrole.wp user create attacker teacher@example.com --role=teacher --user_pass=password - Create Page: Add the dashboard page as described in Section 4.
7. Expected Results
- The HTTP response should be a
200 OK(or JSON success message like{"success":true}). - The unauthorized action (e.g., student deletion) should be reflected in the database.
- A legitimate security check would have returned a
403 Forbiddenor a JSON error message.
8. Verification Steps
- Check Database: Confirm the record was deleted or the setting was changed.
wp db query "SELECT * FROM wp_wsp_student WHERE student_id=2" - Verify Role: Ensure the
attackeruser still only has theteacherrole and notadministrator.
9. Alternative Approaches
If the wsp_delete_student action is protected, investigate other common WPSchoolPress AJAX actions:
wsp_update_general_settings: Modifying site-wide school settings.wsp_add_mark: Modifying grades without proper permissions.wsp_import_students: If a teacher can trigger a CSV import, they might be able to overwrite existing data.
Search specifically for functions inside lib/wsp-ajax.php that interact with the $wpdb object but don't call current_user_can().
Summary
The WPSchoolPress plugin for WordPress is vulnerable to unauthorized data modification due to a missing capability check in several AJAX functions. Authenticated attackers with teacher-level permissions can exploit this to perform administrative tasks, such as deleting student records or altering settings, because the plugin only validates nonces without verifying the user's authorization level.
Vulnerable Code
// File: lib/wsp-ajax.php (approximate) add_action( 'wp_ajax_wsp_delete_student', 'wsp_delete_student_callback' ); function wsp_delete_student_callback() { // Nonce is checked, but capability check is missing check_ajax_referer('wsp_ajax_nonce', 'nonce'); $student_id = intval($_POST['student_id']); global $wpdb; $table_name = $wpdb->prefix . 'wsp_student'; $wpdb->delete($table_name, array('student_id' => $student_id)); wp_send_json_success(); wp_die(); }
Security Fix
@@ -10,6 +10,10 @@ function wsp_delete_student_callback() { check_ajax_referer('wsp_ajax_nonce', 'nonce'); + if ( ! current_user_can( 'manage_options' ) ) { + wp_send_json_error( array( 'message' => 'You do not have permission to perform this action.' ) ); + } + $student_id = intval($_POST['student_id']); global $wpdb; $table_name = $wpdb->prefix . 'wsp_student';
Exploit Outline
1. Gain access to a WordPress account with the 'teacher' role (a custom role provided by the plugin). 2. Navigate to any page containing the WPSchoolPress dashboard shortcode (e.g., [wsp_dashboard]) to allow the plugin to load its scripts. 3. Extract the security nonce from the page source or browser console by inspecting the 'wsp_vars' or 'wsp_ajax' JavaScript objects (e.g., window.wsp_vars.nonce). 4. Send a POST request to /wp-admin/admin-ajax.php with the following parameters: 'action' set to 'wsp_delete_student', 'nonce' set to the extracted value, and 'student_id' set to the ID of the record to be deleted. 5. Verify the deletion by checking the database or the student list, as the server will process the request without checking if the 'teacher' user has administrative rights.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.