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
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
- 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']);
}
}
- 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;
}
- 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'])) {
- 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');
- 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');