Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save andriyun/5322c4cef0a7fcc62e988afd5748fc51 to your computer and use it in GitHub Desktop.
Save andriyun/5322c4cef0a7fcc62e988afd5748fc51 to your computer and use it in GitHub Desktop.

How to patch your Drupal 7 regarding SA-CORE-2018-004

Check if your site doesn't have SA-CORE-2018-002 security update

If not please follow this manual How to patch your Drupal 7 regarding SA-CORE-2018-002

Add changes to your drupal core files

All changes in here is based on original patch for Drupal.7.58

You can add changes 2,3,4 from list below using partial patch using command:

cd /drupal/root/folder/
curl https://gist.githubusercontent.com/andriyun/1b5a210952045f65e0a965e98de4bee8/raw/801a06109446d5c0ea37cdb88f41569297a4cdce/SA-CORE-2018-004-D7-partial.patch | patch -p1

After that please add changes from 1 section manually.

If you have Media contrib module version > 7.x-2.0-alpha4 (after 02-05-2014), you should fix remote code execution SA-CONTRIB-2018-020. See section 5

1. Sanitize destination query argument in includes/bootstrap.inc file

  • Open includes/bootstrap.inc
  • Find code snippet lines ~ 2000 - 2500
      unset($_GET['destination']);
      unset($_REQUEST['destination']);
    }
  • Add following 4 lines after snippet above ^^^
    // Use the DrupalRequestSanitizer to ensure that the destination's query
    // parameters are not dangerous.
    if (isset($_GET['destination'])) {
      DrupalRequestSanitizer::cleanDestination();
    }

For earlier versions it's possible that you will need add all the sanitize block. Find snippet:

  require_once DRUPAL_ROOT . '/includes/module.inc';
  module_load_all(TRUE);

And add following block:

  // Sanitize the destination parameter (which is often used for redirects) to
  // prevent open redirect attacks leading to other domains. Sanitize both
  // $_GET['destination'] and $_REQUEST['destination'] to protect code that
  // relies on either, but do not sanitize $_POST to avoid interfering with
  // unrelated form submissions. The sanitization happens here because
  // url_is_external() requires the variable system to be available.
  if (isset($_GET['destination']) || isset($_REQUEST['destination'])) {
    require_once DRUPAL_ROOT . '/includes/common.inc';
    // If the destination is an external URL, remove it.
    if (isset($_GET['destination']) && url_is_external($_GET['destination'])) {
      unset($_GET['destination']);
      unset($_REQUEST['destination']);
    }
    // Use the DrupalRequestSanitizer to ensure that the destination's query
    // parameters are not dangerous.
    if (isset($_GET['destination'])) {
      DrupalRequestSanitizer::cleanDestination();
    }
    // If there's still something in $_REQUEST['destination'] that didn't come
    // from $_GET, check it too.
    if (isset($_REQUEST['destination']) && (!isset($_GET['destination']) || $_REQUEST['destination'] != $_GET['destination']) && url_is_external($_REQUEST['destination'])) {
      unset($_REQUEST['destination']);
    }
  }

2. Improve DrupalRequestSanitizer object with new method.

  • Open includes/request-sanitizer.inc
  • Find code snippet lines ~ 45 - 50
      $request_sanitized_keys = array();
      $_REQUEST = self::stripDangerousValues($_REQUEST, $whitelist, $request_sanitized_keys);

      self::$sanitized = TRUE;
    }
  }
  • Add following lines. You should put the new method between two existing methods.

  /**
   * Removes the destination if it is dangerous.
   *
   * Note this can only be called after common.inc has been included.
   *
   * @return bool
   *   TRUE if the destination has been removed from $_GET, FALSE if not.
   */
  public static function cleanDestination() {
    $dangerous_keys = array();
    $log_sanitized_keys = variable_get('sanitize_input_logging', FALSE);

    $parts = drupal_parse_url($_GET['destination']);
    // If there is a query string, check its query parameters.
    if (!empty($parts['query'])) {
      $whitelist = variable_get('sanitize_input_whitelist', array());

      self::stripDangerousValues($parts['query'], $whitelist, $dangerous_keys);
      if (!empty($dangerous_keys)) {
        // The destination is removed rather than sanitized to mirror the
        // handling of external destinations.
        unset($_GET['destination']);
        unset($_REQUEST['destination']);
        if ($log_sanitized_keys) {
          trigger_error(format_string('Potentially unsafe destination removed from query string parameters (GET) because it contained the following keys: @keys', array('@keys' => implode(', ', $dangerous_keys))));
        }
        return TRUE;
      }
    }
    return FALSE;
  }

3. Protect q argument in path in includes/common.inc file

  • Open includes/common.inc
  • Find code snippet lines ~ 600 - 620
  // URLs are enabled, due to how Apache rewriting rules work.
  if (isset($options['query']['q'])) {
  • Replace 2 lines from snippet above ^^^ with following 3 lines.
  // URLs are enabled, due to how Apache rewriting rules work. The path
  // parameter must be a string.
  if (isset($options['query']['q']) && is_string($options['query']['q'])) {

4. Protect file core module

  • Open modules/file/file.module
  • Find code snippet lines ~ 235 - 245

  $form_parents = func_get_args();
  $form_build_id = (string) array_pop($form_parents);
  • Add following 3 lines after snippet above ^^^. Better with last blank line :)
  // Sanitize form parents before using them.
  $form_parents = array_filter($form_parents, 'element_child');

5. Media contrib module fix remote Code Execution (only for version ~ 7.x-2.x)

  • Open Media module folder. It should be something like sites/all/media.module
  • Find code snippet lines
  $form_parents = func_get_args();
  $form_build_id = (string) array_pop($form_parents);
  • Add following 3 lines after snippet above ^^^. Better with last blank line :)
  // Sanitize form parents before using them.
  $form_parents = array_filter($form_parents, 'element_child');

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment