From 0a9feec5af9c0e6e4dfd0175a9ef69bd92651213 Mon Sep 17 00:00:00 2001 From: Camwyn Date: Fri, 25 Apr 2025 11:10:27 -0400 Subject: [PATCH 1/6] Check user permissions for subscriber actions. --- .../Exit_Interview_Subscriber.php | 19 ++++++++++++------- src/Telemetry/Opt_In/Opt_In_Subscriber.php | 4 ++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php b/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php index 7f58ad3..55eee46 100644 --- a/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php +++ b/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php @@ -80,6 +80,18 @@ public function render_exit_interview() { * @return void */ public function ajax_exit_interview() { + $nonce = filter_input( INPUT_POST, 'nonce', FILTER_SANITIZE_SPECIAL_CHARS ); + $nonce = ! empty( $nonce ) ? $nonce : ''; + + if ( ! wp_verify_nonce( $nonce, self::AJAX_ACTION ) ) { + wp_send_json_error( 'Invalid nonce' ); + } + + // Check if the user has the necessary permissions. + if ( ! current_user_can( 'manage_options' ) ) { + wp_send_json_error( 'User does not have proper permissions plugins' ); + } + $uninstall_reason_id = filter_input( INPUT_POST, 'uninstall_reason_id', FILTER_SANITIZE_SPECIAL_CHARS ); $uninstall_reason_id = ! empty( $uninstall_reason_id ) ? $uninstall_reason_id : false; if ( ! $uninstall_reason_id ) { @@ -97,13 +109,6 @@ public function ajax_exit_interview() { $comment = filter_input( INPUT_POST, 'comment', FILTER_SANITIZE_SPECIAL_CHARS ); $comment = ! empty( $comment ) ? $comment : ''; - $nonce = filter_input( INPUT_POST, 'nonce', FILTER_SANITIZE_SPECIAL_CHARS ); - $nonce = ! empty( $nonce ) ? $nonce : ''; - - if ( ! wp_verify_nonce( $nonce, self::AJAX_ACTION ) ) { - wp_send_json_error( 'Invalid nonce' ); - } - $telemetry = $this->container->get( Telemetry::class ); $telemetry->send_uninstall( $plugin_slug, $uninstall_reason_id, $uninstall_reason, $comment ); diff --git a/src/Telemetry/Opt_In/Opt_In_Subscriber.php b/src/Telemetry/Opt_In/Opt_In_Subscriber.php index ba6baec..557f30c 100644 --- a/src/Telemetry/Opt_In/Opt_In_Subscriber.php +++ b/src/Telemetry/Opt_In/Opt_In_Subscriber.php @@ -61,6 +61,10 @@ public function set_optin_status() { return; } + if ( ! current_user_can( 'manage_options' ) ) { + return; + } + // We're not attempting a telemetry action. if ( isset( $_POST['action'] ) && 'stellarwp-telemetry' !== $_POST['action'] ) { return; From 7407e8d6809a9a40a12663c4aea1c85987c860f7 Mon Sep 17 00:00:00 2001 From: Stephen Page Date: Fri, 25 Apr 2025 13:09:19 -0400 Subject: [PATCH 2/6] Update src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php Co-authored-by: Tanner Record --- src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php b/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php index 67606cf..d3acb76 100644 --- a/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php +++ b/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php @@ -88,7 +88,7 @@ public function ajax_exit_interview() { // Check if the user has the necessary permissions. if ( ! current_user_can( 'manage_options' ) ) { - wp_send_json_error( 'User does not have proper permissions plugins' ); + wp_send_json_error( 'User does not have proper permissions to modify plugins' ); } $uninstall_reason_id = filter_input( INPUT_POST, 'uninstall_reason_id', FILTER_SANITIZE_SPECIAL_CHARS ); From da05a71daf3066aee22f9235277e6d32f5abea42 Mon Sep 17 00:00:00 2001 From: Camwyn Date: Fri, 25 Apr 2025 13:21:43 -0400 Subject: [PATCH 3/6] Move current_user_can to last check as it requires a database hit. --- .../Exit_Interview/Exit_Interview_Subscriber.php | 12 +++++++----- src/Telemetry/Opt_In/Opt_In_Subscriber.php | 10 ++++++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php b/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php index d3acb76..cfed466 100644 --- a/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php +++ b/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php @@ -79,6 +79,7 @@ public function render_exit_interview() { * @return void */ public function ajax_exit_interview() { + // Validate nonce. $nonce = filter_input( INPUT_POST, 'nonce', FILTER_SANITIZE_SPECIAL_CHARS ); $nonce = ! empty( $nonce ) ? $nonce : ''; @@ -86,11 +87,7 @@ public function ajax_exit_interview() { wp_send_json_error( 'Invalid nonce' ); } - // Check if the user has the necessary permissions. - if ( ! current_user_can( 'manage_options' ) ) { - wp_send_json_error( 'User does not have proper permissions to modify plugins' ); - } - + // Check sent data before we do any database checks for faster failures. $uninstall_reason_id = filter_input( INPUT_POST, 'uninstall_reason_id', FILTER_SANITIZE_SPECIAL_CHARS ); $uninstall_reason_id = ! empty( $uninstall_reason_id ) ? $uninstall_reason_id : false; if ( ! $uninstall_reason_id ) { @@ -108,6 +105,11 @@ public function ajax_exit_interview() { $comment = filter_input( INPUT_POST, 'comment', FILTER_SANITIZE_SPECIAL_CHARS ); $comment = ! empty( $comment ) ? $comment : ''; + // Sent data validated, check if the user has the necessary permissions. + if ( ! current_user_can( 'manage_options' ) ) { + wp_send_json_error( 'User does not have proper permissions to modify plugins' ); + } + $telemetry = $this->container->get( Telemetry::class ); $telemetry->send_uninstall( $plugin_slug, $uninstall_reason_id, $uninstall_reason, $comment ); diff --git a/src/Telemetry/Opt_In/Opt_In_Subscriber.php b/src/Telemetry/Opt_In/Opt_In_Subscriber.php index 557f30c..96d9285 100644 --- a/src/Telemetry/Opt_In/Opt_In_Subscriber.php +++ b/src/Telemetry/Opt_In/Opt_In_Subscriber.php @@ -61,10 +61,7 @@ public function set_optin_status() { return; } - if ( ! current_user_can( 'manage_options' ) ) { - return; - } - + // Check sent data before we do any database checks for faster failures. // We're not attempting a telemetry action. if ( isset( $_POST['action'] ) && 'stellarwp-telemetry' !== $_POST['action'] ) { return; @@ -75,6 +72,11 @@ public function set_optin_status() { return; } + // Sent data validated, check if the user has the necessary permissions. + if ( ! current_user_can( 'manage_options' ) ) { + return; + } + $stellar_slug = Config::get_stellar_slug(); if ( isset( $_POST['stellar_slug'] ) ) { From 9b23218fdd9d86260d813f221c1b8d93d9ff7bb0 Mon Sep 17 00:00:00 2001 From: Camwyn Date: Fri, 25 Apr 2025 13:42:18 -0400 Subject: [PATCH 4/6] Proposed additional security tweaks. --- .../plugins/library-testing/src/Settings_Page.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dev/public/wp-content/plugins/library-testing/src/Settings_Page.php b/dev/public/wp-content/plugins/library-testing/src/Settings_Page.php index d6f1aed..88417a8 100644 --- a/dev/public/wp-content/plugins/library-testing/src/Settings_Page.php +++ b/dev/public/wp-content/plugins/library-testing/src/Settings_Page.php @@ -79,6 +79,11 @@ public function send_event(): void { return; } + // Check if the user has the necessary permissions. + if ( ! current_user_can( 'manage_options' ) ) { + return; + } + $number = filter_input( INPUT_POST, 'number', FILTER_VALIDATE_INT ) ?: 1; // Set up basic event data for each valid event. @@ -114,6 +119,11 @@ public function clear_all_database_options() { return; } + // Check if the user has the necessary permissions. + if ( ! current_user_can( 'manage_options' ) ) { + return; + } + global $wpdb; $query = $wpdb->prepare( "DELETE FROM {$wpdb->prefix}options WHERE `option_name` LIKE 'stellarwp_telemetry%%';" ); From c7be0cf24bead814d7223769e802548b80295385 Mon Sep 17 00:00:00 2001 From: Tanner Record Date: Fri, 25 Apr 2025 14:29:33 -0400 Subject: [PATCH 5/6] Minimizing changes --- .../Exit_Interview/Exit_Interview_Subscriber.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php b/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php index cfed466..3ddff55 100644 --- a/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php +++ b/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php @@ -79,13 +79,6 @@ public function render_exit_interview() { * @return void */ public function ajax_exit_interview() { - // Validate nonce. - $nonce = filter_input( INPUT_POST, 'nonce', FILTER_SANITIZE_SPECIAL_CHARS ); - $nonce = ! empty( $nonce ) ? $nonce : ''; - - if ( ! wp_verify_nonce( $nonce, self::AJAX_ACTION ) ) { - wp_send_json_error( 'Invalid nonce' ); - } // Check sent data before we do any database checks for faster failures. $uninstall_reason_id = filter_input( INPUT_POST, 'uninstall_reason_id', FILTER_SANITIZE_SPECIAL_CHARS ); @@ -105,6 +98,14 @@ public function ajax_exit_interview() { $comment = filter_input( INPUT_POST, 'comment', FILTER_SANITIZE_SPECIAL_CHARS ); $comment = ! empty( $comment ) ? $comment : ''; + // Validate nonce. + $nonce = filter_input( INPUT_POST, 'nonce', FILTER_SANITIZE_SPECIAL_CHARS ); + $nonce = ! empty( $nonce ) ? $nonce : ''; + + if ( ! wp_verify_nonce( $nonce, self::AJAX_ACTION ) ) { + wp_send_json_error( 'Invalid nonce' ); + } + // Sent data validated, check if the user has the necessary permissions. if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( 'User does not have proper permissions to modify plugins' ); From 67b8d7478880b7581b2bf07e9d87e0a643f60db6 Mon Sep 17 00:00:00 2001 From: Tanner Record Date: Fri, 25 Apr 2025 14:40:09 -0400 Subject: [PATCH 6/6] Add new since tags to document changes --- src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php | 1 + src/Telemetry/Opt_In/Opt_In_Subscriber.php | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php b/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php index 3ddff55..54d03ad 100644 --- a/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php +++ b/src/Telemetry/Exit_Interview/Exit_Interview_Subscriber.php @@ -75,6 +75,7 @@ public function render_exit_interview() { * Handles the ajax request for submitting "Exit Interivew" form data. * * @since 1.0.0 + * @since 2.3.4 - Added user capability check. * * @return void */ diff --git a/src/Telemetry/Opt_In/Opt_In_Subscriber.php b/src/Telemetry/Opt_In/Opt_In_Subscriber.php index 96d9285..dc18afd 100644 --- a/src/Telemetry/Opt_In/Opt_In_Subscriber.php +++ b/src/Telemetry/Opt_In/Opt_In_Subscriber.php @@ -45,6 +45,7 @@ public function register(): void { * Sets the opt-in status for the site. * * @since 1.0.0 + * @since 2.3.4 - Added user capability check. * * @return void */