[wp-trac] [WordPress Trac] #62449: Bypassable Sanitization in the restfulAPI, which lead to the

WordPress Trac noreply at wordpress.org
Fri Nov 15 19:52:36 UTC 2024


#62449: Bypassable Sanitization in the restfulAPI, which lead to the
--------------------------+-------------------------------
 Reporter:  samjhuseclab  |      Owner:  (none)
     Type:  defect (bug)  |     Status:  new
 Priority:  normal        |  Milestone:  Awaiting Review
Component:  REST API      |    Version:  trunk
 Severity:  normal        |   Keywords:  changes-requested
  Focuses:  rest-api      |
--------------------------+-------------------------------
 = WordPress Core Potential Issue: JSONP Sanitization Bypass in `wp_die` =

 == Overview ==
 This document describes a potential sanitization bug in WordPress Core,
 specifically in the `_jsonp_wp_die_handler` function. The issue arises
 when a plugin uses the `rest_jsonp_enabled` filter to modify the `_jsonp`
 field after it has passed the `wp_check_jsonp_callback` validation. While
 this issue is not a direct security vulnerability, it reveals a
 sanitization flaw that can result in unexpected behavior.

 == Details ==

 === Affected Function: `_jsonp_wp_die_handler` ===
 The `_jsonp_wp_die_handler` function uses the `$_GET['_jsonp']` parameter
 to generate the JSONP callback name. The callback is directly output in
 the response without further validation after initial checks.

 '''Key Code:'''
 {{{
 $jsonp_callback = $_GET['_jsonp'];
 echo '/**/' . $jsonp_callback . '(' . $result . ');';
 }}}

 If the `$_GET['_jsonp']` contains malicious or invalid characters, it may
 lead to unintended outputs.

 === Validation Process and the Problem ===

 1. '''Validation via `wp_is_jsonp_request`:'''
    - The function `wp_is_jsonp_request` validates `$_GET['_jsonp']` using
 `wp_check_jsonp_callback`, ensuring the callback name only contains safe
 characters (alphanumeric, underscores, and dots).
    - '''Code:'''
 {{{
 preg_replace('/[^\w\.]/', '', $callback, -1, $illegal_char_count);
 if ($illegal_char_count > 0) {
     return false;
 }
 }}}

 2. '''The Problem:'''
    - After validation, the `rest_jsonp_enabled` filter is called:
 {{{
 $jsonp_enabled = apply_filters('rest_jsonp_enabled', true);
 }}}
    - At this stage, an attacker or a malicious plugin can modify
 `$_GET['_jsonp']`, bypassing the sanitization performed by
 `wp_check_jsonp_callback`.

 3. '''Potential Outcome:'''
    - The callback function name used in the response could contain
 unsanitized or unexpected values.
    - '''Example Output:'''
 {{{
 /**/maliciousCallback({...});
 }}}

 == Reproduction Steps ==

 1. '''Create a Plugin to Exploit the Issue:'''
 {{{
 add_filter('rest_jsonp_enabled', function($enabled) {
     $_GET['_jsonp'] = 'maliciousCallback';
     return $enabled;
 });
 }}}

 2. '''Trigger the Issue:'''
    - Send a request to any endpoint that invokes `_jsonp_wp_die_handler`:
 {{{
 GET /wp-json?_jsonp=legitCallback
 }}}

 3. '''Observe the Response:'''
    - Despite the original `legitCallback` passing validation, the plugin
 modifies it to:
 {{{
 /**/maliciousCallback({...});
 }}}

 == Impact ==

 === Risk Assessment ===
 - '''Threat Level:''' Low
 - '''Requirements for Exploitation:'''
   - A specific plugin must actively modify `$_GET['_jsonp']` after
 validation.
 - '''Actual Output:''' A standard HTTP JSON response, albeit with a
 potentially unsanitized callback function.

 === Potential Implications ===
 - '''Data Integrity:''' The final output does not match the originally
 validated input.
 - '''Third-Party Plugin Behavior:''' Malicious plugins could abuse this to
 inject unexpected callback names.

 == Example Fix Code ==
 Below is the updated version of the `wp_is_jsonp_request` function:

 {{{
 function wp_is_jsonp_request() {
     if (!isset($_GET['_jsonp'])) {
         return false;
     }

     $jsonp_callback = $_GET['_jsonp'];

     // Initial validation
     if (!wp_check_jsonp_callback($jsonp_callback)) {
         return false;
     }

     // Call filter
     $jsonp_enabled = apply_filters('rest_jsonp_enabled', true);

     // Revalidate after filter execution
     if ($jsonp_enabled) {
         $jsonp_callback_after_filter = $_GET['_jsonp'];
         if (!wp_check_jsonp_callback($jsonp_callback_after_filter)) {
             return false;
         }
     }

     return $jsonp_enabled;
 }
 }}}

 == Conclusion ==
 This issue highlights a sanitization bug rather than a direct
 vulnerability. While the risk is low, fixing this behavior ensures that
 WordPress maintains robust input validation and output integrity, even in
 edge cases involving plugins and filters.

 If JSONP functionality is no longer required, it is recommended to disable
 it entirely to mitigate any future risks.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/62449>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list