Merged 7.96.
commit
e11e3f4f7f
|
@ -1,6 +1,11 @@
|
|||
Drupal 7.xx, xxxx-xx-xx (development version)
|
||||
-----------------------
|
||||
|
||||
Drupal 7.96, 2023-04-19
|
||||
-----------------------
|
||||
- Fixed security issues:
|
||||
- SA-CORE-2023-005
|
||||
|
||||
Drupal 7.95, 2023-03-15
|
||||
-----------------------
|
||||
- Fixed security issues:
|
||||
|
|
|
@ -2073,6 +2073,7 @@ function file_download() {
|
|||
$scheme = array_shift($args);
|
||||
$target = implode('/', $args);
|
||||
$uri = $scheme . '://' . $target;
|
||||
$uri = file_uri_normalize_dot_segments($uri);
|
||||
if (file_stream_wrapper_valid_scheme($scheme) && file_exists($uri)) {
|
||||
$headers = file_download_headers($uri);
|
||||
if (count($headers)) {
|
||||
|
@ -2730,6 +2731,58 @@ function file_get_content_headers($file) {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize dot segments in a URI.
|
||||
*
|
||||
* @param $uri
|
||||
* A stream, referenced as "scheme://target".
|
||||
*
|
||||
* @return string
|
||||
* The URI with dot segments removed and slashes as directory separator.
|
||||
*/
|
||||
function file_uri_normalize_dot_segments($uri) {
|
||||
$scheme = file_uri_scheme($uri);
|
||||
|
||||
if (file_stream_wrapper_valid_scheme($scheme)) {
|
||||
$target = file_uri_target($uri);
|
||||
|
||||
if ($target !== FALSE) {
|
||||
if (!in_array($scheme, variable_get('file_sa_core_2023_005_schemes', array()))) {
|
||||
$class = file_stream_wrapper_get_class($scheme);
|
||||
$is_local = is_subclass_of($class, DrupalLocalStreamWrapper::class);
|
||||
if ($is_local) {
|
||||
$target = str_replace(DIRECTORY_SEPARATOR, '/', $target);
|
||||
}
|
||||
|
||||
$parts = explode('/', $target);
|
||||
$normalized_parts = array();
|
||||
while ($parts) {
|
||||
$part = array_shift($parts);
|
||||
if ($part === '' || $part === '.') {
|
||||
continue;
|
||||
}
|
||||
elseif ($part === '..' && $is_local && $normalized_parts === array()) {
|
||||
$normalized_parts[] = $part;
|
||||
break;
|
||||
}
|
||||
elseif ($part === '..') {
|
||||
array_pop($normalized_parts);
|
||||
}
|
||||
else {
|
||||
$normalized_parts[] = $part;
|
||||
}
|
||||
}
|
||||
|
||||
$target = implode('/', array_merge($normalized_parts, $parts));
|
||||
}
|
||||
|
||||
$uri = $scheme . '://' . $target;
|
||||
}
|
||||
}
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "defgroup file".
|
||||
*/
|
||||
|
|
|
@ -819,6 +819,20 @@ function image_style_deliver($style, $scheme = NULL) {
|
|||
array_shift($args);
|
||||
array_shift($args);
|
||||
$target = implode('/', $args);
|
||||
$image_uri = $scheme . '://' . $target;
|
||||
$image_uri = file_uri_normalize_dot_segments($image_uri);
|
||||
|
||||
if (file_stream_wrapper_valid_scheme($scheme)) {
|
||||
$normalized_target = file_uri_target($image_uri);
|
||||
if ($normalized_target !== FALSE) {
|
||||
if (!in_array($scheme, variable_get('file_sa_core_2023_005_schemes', array()))) {
|
||||
$parts = explode('/', $normalized_target);
|
||||
if (array_intersect($parts, array('.', '..'))) {
|
||||
return MENU_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the style is defined, the scheme is valid.
|
||||
$valid = !empty($style) && !empty($scheme) && file_stream_wrapper_valid_scheme($scheme);
|
||||
|
@ -830,7 +844,9 @@ function image_style_deliver($style, $scheme = NULL) {
|
|||
// variable from leaving the site vulnerable to the most serious attacks, a
|
||||
// token is always required when a derivative of a derivative is requested.)
|
||||
$token = isset($_GET[IMAGE_DERIVATIVE_TOKEN]) ? $_GET[IMAGE_DERIVATIVE_TOKEN] : '';
|
||||
$token_is_valid = $token === image_style_path_token($style['name'], $scheme . '://' . $target);
|
||||
$token_is_valid =
|
||||
$token === image_style_path_token($style['name'], $image_uri)
|
||||
|| $token === image_style_path_token($style['name'], $scheme . '://' . $target);
|
||||
if (!variable_get('image_allow_insecure_derivatives', FALSE) || strpos(ltrim($target, '\/'), 'styles/') === 0) {
|
||||
$valid = $valid && $token_is_valid;
|
||||
}
|
||||
|
@ -838,7 +854,6 @@ function image_style_deliver($style, $scheme = NULL) {
|
|||
return MENU_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
$image_uri = $scheme . '://' . $target;
|
||||
$derivative_uri = image_style_path($style['name'], $image_uri);
|
||||
$derivative_scheme = file_uri_scheme($derivative_uri);
|
||||
|
||||
|
@ -1084,9 +1099,11 @@ function image_style_flush($style) {
|
|||
*/
|
||||
function image_style_url($style_name, $path) {
|
||||
$uri = image_style_path($style_name, $path);
|
||||
$uri = file_uri_normalize_dot_segments($uri);
|
||||
|
||||
// The passed-in $path variable can be either a relative path or a full URI.
|
||||
$original_uri = file_uri_scheme($path) ? file_stream_wrapper_uri_normalize($path) : file_build_uri($path);
|
||||
$original_uri = file_uri_normalize_dot_segments($original_uri);
|
||||
|
||||
// The token query is added even if the 'image_allow_insecure_derivatives'
|
||||
// variable is TRUE, so that the emitted links remain valid if it is changed
|
||||
|
|
|
@ -4093,6 +4093,25 @@ function system_admin_paths() {
|
|||
* Implements hook_file_download().
|
||||
*/
|
||||
function system_file_download($uri) {
|
||||
$scheme = file_uri_scheme($uri);
|
||||
if (file_stream_wrapper_valid_scheme($scheme)) {
|
||||
$target = file_uri_target($uri);
|
||||
if ($target !== FALSE) {
|
||||
if (!in_array($scheme, variable_get('file_sa_core_2023_005_schemes', array()))) {
|
||||
if (DIRECTORY_SEPARATOR !== '/') {
|
||||
$class = file_stream_wrapper_get_class($scheme);
|
||||
if (is_subclass_of($class, DrupalLocalStreamWrapper::class)) {
|
||||
$target = str_replace(DIRECTORY_SEPARATOR, '/', $target);
|
||||
}
|
||||
}
|
||||
$parts = explode('/', $target);
|
||||
if (array_intersect($parts, array('.', '..'))) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$core_schemes = array('public', 'private', 'temporary');
|
||||
$additional_public_schemes = array_diff(variable_get('file_additional_public_schemes', array()), $core_schemes);
|
||||
if ($additional_public_schemes) {
|
||||
|
|
|
@ -818,3 +818,22 @@ $conf['mail_display_name_site_name'] = TRUE;
|
|||
* Use this variable to set a custom cron lock expiration timeout (float).
|
||||
*/
|
||||
# $conf['cron_lock_expiration_timeout'] = 900.0;
|
||||
|
||||
/**
|
||||
* File schemes whose paths should not be normalized:
|
||||
*
|
||||
* Normally, Drupal normalizes '/./' and '/../' segments in file URIs in order
|
||||
* to prevent unintended file access. For example, 'private://css/../image.png'
|
||||
* is normalized to 'private://image.png' before checking access to the file.
|
||||
*
|
||||
* On Windows, Drupal also replaces '\' with '/' in URIs for the local
|
||||
* filesystem.
|
||||
*
|
||||
* If file URIs with one or more scheme should not be normalized like this, then
|
||||
* list the schemes here. For example, if 'porcelain://china/./plate.png' should
|
||||
* not be normalized to 'porcelain://china/plate.png', then add 'porcelain' to
|
||||
* this array. In this case, make sure that the module providing the 'porcelain'
|
||||
* scheme does not allow unintended file access when using '/../' to move up the
|
||||
* directory tree.
|
||||
*/
|
||||
# $conf['file_sa_core_2023_005_schemes'] = array('porcelain');
|
||||
|
|
Loading…
Reference in New Issue