Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/geodirectory/geodirectory.php
+++ b/geodirectory/geodirectory.php
@@ -11,7 +11,7 @@
* Plugin Name: GeoDirectory
* Plugin URI: https://wpgeodirectory.com/
* Description: GeoDirectory - Business Directory Plugin for WordPress.
- * Version: 2.8.169
+ * Version: 2.8.170
* Author: AyeCode - WP Business Directory Plugins
* Author URI: https://wpgeodirectory.com
* Text Domain: geodirectory
@@ -34,7 +34,7 @@
*
* @var string
*/
- public $version = '2.8.169';
+ public $version = '2.8.170';
/**
* GeoDirectory instance.
--- a/geodirectory/includes/class-geodir-api.php
+++ b/geodirectory/includes/class-geodir-api.php
@@ -578,20 +578,48 @@
*
*/
public static function rest_cookie_check_errors( $errors ) {
- if ( is_wp_error( $errors ) && ! empty( $_REQUEST['_wpnonce'] ) && ! empty( $_SERVER['REQUEST_URI'] ) && strpos( $_SERVER['REQUEST_URI'], '/wp-json/geodir/' ) !== false && strpos( $_SERVER['REQUEST_URI'], '/markers/' ) !== false && is_wp_error( $errors ) && $errors->get_error_code() == 'rest_cookie_invalid_nonce' ) {
- if ( is_user_logged_in() ) { // Logged in user
- return true;
- } elseif ( geodir_create_nonce( 'wp_rest' ) == sanitize_text_field( $_REQUEST['_wpnonce'] ) ) {
+ // Check basic validation.
+ if ( empty( $_REQUEST['_wpnonce'] ) || empty( $_SERVER['REQUEST_URI'] ) || strpos( $_SERVER['REQUEST_URI'], '/markers/' ) === false || strpos( $_SERVER['REQUEST_URI'], '/geodir/' ) === false || ! is_wp_error( $errors ) ) {
+ return $errors;
+ }
+
+ // Only check for rest_cookie_invalid_nonce error.
+ if ( $errors->get_error_code() !== 'rest_cookie_invalid_nonce' ) {
+ return $errors;
+ }
+
+ // Match against the PATH only, never the raw REQUEST_URI.
+ $request_path = wp_parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
+
+ if ( empty( $request_path ) ) {
+ return $errors;
+ }
+
+ $rest_prefix = trailingslashit( rest_get_url_prefix() ); // Usually 'wp-json/'.
+ $namespace = GEODIR_REST_SLUG . '/v' . GEODIR_REST_API_VERSION; // Usually 'geodir/v2'.
+ $is_markers_route = (bool) preg_match( '#/' . preg_quote( $rest_prefix, '#' ) . $namespace. '/markers/#', $request_path );
+
+ // Return if not a markers route.
+ if ( ! $is_markers_route ) {
+ return $errors;
+ }
+
+ if ( is_user_logged_in() ) {
+ // Logged in user.
+ return true;
+ } elseif ( geodir_create_nonce( 'wp_rest' ) == sanitize_text_field( $_REQUEST['_wpnonce'] ) ) {
+ // Nonce validated.
+ return true;
+ } else {
+ $parse_referer = wp_parse_url( wp_get_referer() ); // Http referer
+ $parse_home = wp_parse_url( home_url( '/' ) ); // Home url
+
+ // Check request from same host.
+ if ( ! empty( $parse_referer['host'] ) && ! empty( $parse_home['host'] ) && strtolower( $parse_referer['host'] ) == strtolower( $parse_home['host'] ) ) {
return true;
- } else {
- $parse_referer = wp_parse_url( wp_get_referer() ); // Http referer
- $parse_home = wp_parse_url( home_url( '/' ) ); // Home url
-
- if ( ! empty( $parse_referer['host'] ) && ! empty( $parse_home['host'] ) && strtolower( $parse_referer['host'] ) == strtolower( $parse_home['host'] ) ) {
- return true;
- }
}
}
+
return $errors;
}
}
--- a/geodirectory/includes/class-geodir-post-data.php
+++ b/geodirectory/includes/class-geodir-post-data.php
@@ -422,12 +422,20 @@
* }
*/
public static function save_auto_draft( $post_info ) {
-
- // check if we already have an auto draft
+ // Check if we already have an auto draft
if ( isset( $post_info['ID'] ) && $post_info['ID'] ) {
+ }
+
+ // Validate pos type
+ if ( ! empty( $post_info['post_type'] ) ) {
+ $_post_type = sanitize_key( $post_info['post_type'] );
+ if ( $_post_type != 'revision' && ! geodir_is_gd_post_type( $_post_type ) ) {
+ return new WP_Error( 'save_post', __( "Invalid post!", "geodirectory" ) );
+ }
}
- $result = wp_insert_post( $post_info, true ); // we hook into the save_post hook
+
+ $result = wp_insert_post( $post_info, true ); // We hook into the save_post hook
}
/**
@@ -773,6 +781,10 @@
return $data;
}
+ if ( ! empty( $_REQUEST['post_type'] ) && $_REQUEST['post_type'] != 'revision' && ! geodir_is_gd_post_type( $_REQUEST['post_type'] ) ) {
+ return $data;
+ }
+
// Check its a GD CPT first
if (
( isset( $data['post_type'] ) && in_array( $data['post_type'], geodir_get_posttypes() ) )
@@ -1323,7 +1335,22 @@
return new WP_Error( 'gd-not-owner', __( "You do not own this post", "geodirectory" ) );
}
+ $post_type = get_post_type( (int) $post_data['ID'] );
+
+ if ( ! ( $post_type == 'revision' && geodir_is_gd_post_type( $post_type ) ) ) {
+ return new WP_Error( 'gd-invalid-post', __( "Invalid post!", "geodirectory" ) );
+ }
+
+ if ( ! empty( $post_data['post_parent'] ) ) {
+ $post_type = get_post_type( (int) $post_data['post_parent'] );
+
+ if ( ! ( $post_type == 'revision' && geodir_is_gd_post_type( $post_type ) ) ) {
+ return new WP_Error( 'gd-invalid-post', __( "Invalid post!", "geodirectory" ) );
+ }
+ }
+
$result = wp_delete_post( $post_data['ID'], true );
+
if ( ! empty( $post_data['post_parent'] ) ) {
delete_post_meta( (int) $post_data['post_parent'], "__" . (int) $post_data['ID'] ); // Delete any temp stored media values from auto saves.
}
@@ -1413,15 +1440,14 @@
* @return int|WP_Error
*/
public static function auto_save_post( $post_data, $doing_autosave = true ) {
-
- // check if user has privileges to edit the post
+ // Check if user has privileges to edit the post
$post_id = isset( $post_data['ID'] ) ? absint( $post_data['ID'] ) : '';
$parent_id = isset( $post_data['post_parent'] ) ? absint( $post_data['post_parent'] ) : '';
if ( ! self::can_edit( $post_id, get_current_user_id(), $parent_id ) ) {
return new WP_Error( 'save_post', __( "You do not have the privileges to perform this action.", "geodirectory" ) );
}
- // set that we are doing an auto save
+ // Set that we are doing an auto save
if ( ! defined( 'DOING_AUTOSAVE' ) ) {
if ( $doing_autosave ) {
define( 'DOING_AUTOSAVE', true );
@@ -1430,20 +1456,20 @@
}
}
- // its a post revision
+ // Its a post revision
if ( isset( $post_data['post_parent'] ) && $post_data['post_parent'] ) {
$post_data['post_type'] = 'revision'; // post type is not sent but we know if it has a parent then its a revision.
$post_data['post_name'] = $post_data['post_parent'] . "-autosave-v1";
-
- // save file temp info
+ // Save file temp info
$file_meta = array();
- // set post images
+
+ // Set post images
if ( isset( $post_data['post_images'] ) ) {
$file_meta['post_images'] = $post_data['post_images'];
}
-// // process attachments
+ // Process attachments
$post_type = get_post_type( $post_data['post_parent'] );
$file_fields = GeoDir_Media::get_file_fields( $post_type );
@@ -1458,7 +1484,6 @@
if ( ! empty( $file_meta ) ) {
update_post_meta( $post_data['post_parent'], '__' . $post_data['ID'], $file_meta );
}
-
} // its a new auto draft
else {
/*
@@ -1477,10 +1502,28 @@
return $validate;
}
+ // Validate pos type
+ if ( ! empty( $post_data['post_type'] ) ) {
+ $_post_type = sanitize_key( $post_data['post_type'] );
+
+ if ( $_post_type != 'revision' && ! geodir_is_gd_post_type( $_post_type ) ) {
+ return new WP_Error( 'save_post', __( "Invalid post!", "geodirectory" ) );
+ }
+ }
+
+ // Strip reserved fields.
+ if ( isset( $post_data['meta_input'] ) ) {
+ unset( $post_data['meta_input'] );
+ }
+
+ if ( isset( $post_data['guid'] ) ) {
+ unset( $post_data['guid'] );
+ }
+
// Save the post.
$result = wp_update_post( $post_data, true );
- // get the message response.
+ // Get the message response.
if ( ! is_wp_error( $result ) ) {
do_action( 'geodir_ajax_post_auto_saved', $post_data, ! empty( $post_data['post_parent'] ) );
}
@@ -1534,6 +1577,8 @@
// if a post_type is being posted check that matches
if ( ! empty( $_POST['post_type'] ) && $post_type != $_POST['post_type'] ) {
return false;
+ } elseif ( ! empty( $_REQUEST['post_type'] ) && $post_type != $_REQUEST['post_type'] ) {
+ return false;
}
if ( $author_id == $user_id ) {
@@ -1656,28 +1701,29 @@
* @return int|WP_Error $result
*/
public static function ajax_save_post( $post_data ) {
-
// Check if user has privileges to edit the post
$post_id = isset( $post_data['ID'] ) ? absint( $post_data['ID'] ) : '';
$parent_id = isset( $post_data['post_parent'] ) ? absint( $post_data['post_parent'] ) : '';
+
if ( ! self::can_edit( $post_id, get_current_user_id(), $parent_id ) ) {
return new WP_Error( 'save_post', __( "You do not have the privileges to perform this action.", "geodirectory" ) );
}
// Check if address is required
- $post_type = isset( $post_data['post_type'] ) ? esc_attr( $post_data['post_type'] ) : '';
+ $post_type = isset( $post_data['post_type'] ) ? esc_attr( $post_data['post_type'] ) : '';
$address_required = geodir_cpt_requires_address( $post_type );
// Pre validation
$has_error = false;
+
if ( isset( $post_data['post_title'] ) && sanitize_text_field( $post_data['post_title'] ) == '' ) {
- $has_error = true;
+ $has_error = true;
$field_title = __( 'Title', 'geodirectory' );
} elseif ( $address_required && isset( $post_data['street'] ) && sanitize_text_field( $post_data['street'] ) == '' && isset( $post_data['post_type'] ) && GeoDir_Post_types::supports( sanitize_text_field( $post_data['post_type'] ), 'location' ) ) {
- $has_error = true;
+ $has_error = true;
$field_title = __( 'Address', 'geodirectory' );
} elseif ( isset( $post_data['cat_limit'] ) && isset( $post_data['post_type'] ) && isset( $post_data['tax_input'] ) && empty( $post_data['tax_input'][ $post_data['post_type'] . 'category' ][0] ) ) {
- $has_error = true;
+ $has_error = true;
$field_title = __( 'Category', 'geodirectory' );
}
@@ -1733,6 +1779,24 @@
*/
$post_data = apply_filters( 'geodir_ajax_update_post_data', $post_data, ! empty( $post_data['post_parent'] ) );
+ // Validate pos type.
+ if ( ! empty( $post_data['post_type'] ) ) {
+ $_post_type = sanitize_key( $post_data['post_type'] );
+
+ if ( $_post_type != 'revision' && ! geodir_is_gd_post_type( $_post_type ) ) {
+ return new WP_Error( 'save_post', __( "Invalid post!", "geodirectory" ) );
+ }
+ }
+
+ // Strip reserved fields.
+ if ( isset( $post_data['meta_input'] ) ) {
+ unset( $post_data['meta_input'] );
+ }
+
+ if ( isset( $post_data['guid'] ) ) {
+ unset( $post_data['guid'] );
+ }
+
// Save the post.
$result = wp_update_post( $post_data, true );