summaryrefslogtreecommitdiff
path: root/modules/image
diff options
context:
space:
mode:
authorDavid Rothstein <drothstein@gmail.com>2013-03-06 18:58:12 -0500
committerDavid Rothstein <drothstein@gmail.com>2013-03-06 18:58:12 -0500
commit33d91c459dad4dfd26b07c9bfcf754d48e279fbd (patch)
treee94bfdae3f7010eb7a298f5b56e54451868f2928 /modules/image
parent3a24da1b40f5e05876ad7775044500b61eb2ed94 (diff)
downloadbrdo-33d91c459dad4dfd26b07c9bfcf754d48e279fbd.tar.gz
brdo-33d91c459dad4dfd26b07c9bfcf754d48e279fbd.tar.bz2
Issue #1934568 by David_Rothstein, pwolanin: Allow sites using the 'image_allow_insecure_derivatives' variable to have partial protection from the security issues fixed in Drupal 7.20.
Diffstat (limited to 'modules/image')
-rw-r--r--modules/image/image.module15
-rw-r--r--modules/image/image.test45
2 files changed, 54 insertions, 6 deletions
diff --git a/modules/image/image.module b/modules/image/image.module
index d7178ad7d..a9cc1a545 100644
--- a/modules/image/image.module
+++ b/modules/image/image.module
@@ -780,9 +780,11 @@ function image_style_deliver($style, $scheme) {
// derivative token is valid. (Sites which require image derivatives to be
// generated without a token can set the 'image_allow_insecure_derivatives'
// variable to TRUE to bypass the latter check, but this will increase the
- // site's vulnerability to denial-of-service attacks.)
+ // site's vulnerability to denial-of-service attacks. To prevent this
+ // variable from leaving the site vulnerable to the most serious attacks, a
+ // token is always required when a derivative of a derivative is requested.)
$valid = !empty($style) && file_stream_wrapper_valid_scheme($scheme);
- if (!variable_get('image_allow_insecure_derivatives', FALSE)) {
+ if (!variable_get('image_allow_insecure_derivatives', FALSE) || strpos(ltrim($target, '\/'), 'styles/') === 0) {
$valid = $valid && isset($_GET[IMAGE_DERIVATIVE_TOKEN]) && $_GET[IMAGE_DERIVATIVE_TOKEN] === image_style_path_token($style['name'], $scheme . '://' . $target);
}
if (!$valid) {
@@ -867,6 +869,11 @@ function image_style_deliver($style, $scheme) {
* @see image_style_load()
*/
function image_style_create_derivative($style, $source, $destination) {
+ // If the source file doesn't exist, return FALSE without creating folders.
+ if (!$image = image_load($source)) {
+ return FALSE;
+ }
+
// Get the folder for the final location of this style.
$directory = drupal_dirname($destination);
@@ -876,10 +883,6 @@ function image_style_create_derivative($style, $source, $destination) {
return FALSE;
}
- if (!$image = image_load($source)) {
- return FALSE;
- }
-
foreach ($style['effects'] as $effect) {
image_effect_apply($image, $effect);
}
diff --git a/modules/image/image.test b/modules/image/image.test
index d4db2130b..25fddf64c 100644
--- a/modules/image/image.test
+++ b/modules/image/image.test
@@ -249,6 +249,51 @@ class ImageStylesPathAndUrlTestCase extends DrupalWebTestCase {
$this->drupalGet(str_replace(IMAGE_DERIVATIVE_TOKEN . '=', IMAGE_DERIVATIVE_TOKEN . '=Zo', $generate_url));
$this->assertResponse(200, 'Existing image was accessible at the URL wih an invalid token.');
}
+
+ // Allow insecure image derivatives to be created for the remainder of this
+ // test.
+ variable_set('image_allow_insecure_derivatives', TRUE);
+
+ // Create another working copy of the file.
+ $files = $this->drupalGetTestFiles('image');
+ $file = array_shift($files);
+ $image_info = image_get_info($file->uri);
+ $original_uri = file_unmanaged_copy($file->uri, $scheme . '://', FILE_EXISTS_RENAME);
+ // Let the image_module_test module know about this file, so it can claim
+ // ownership in hook_file_download().
+ variable_set('image_module_test_file_download', $original_uri);
+
+ // Get the URL of a file that has not been generated and try to create it.
+ $generated_uri = image_style_path($this->style_name, $original_uri);
+ $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
+ $generate_url = image_style_url($this->style_name, $original_uri);
+
+ // Check that the image is accessible even without the security token.
+ $this->drupalGet(str_replace(IMAGE_DERIVATIVE_TOKEN . '=', 'wrongparam=', $generate_url));
+ $this->assertResponse(200, 'Image was accessible at the URL with a missing token.');
+
+ // Check that a security token is still required when generating a second
+ // image derivative using the first one as a source.
+ $nested_uri = image_style_path($this->style_name, $generated_uri);
+ $nested_url = image_style_url($this->style_name, $generated_uri);
+ $nested_url_with_wrong_token = str_replace(IMAGE_DERIVATIVE_TOKEN . '=', 'wrongparam=', $nested_url);
+ $this->drupalGet($nested_url_with_wrong_token);
+ $this->assertResponse(403, 'Image generated from an earlier derivative was inaccessible at the URL with a missing token.');
+ // Check that this restriction cannot be bypassed by adding extra slashes
+ // to the URL.
+ $this->drupalGet(substr_replace($nested_url_with_wrong_token, '//styles/', strrpos($nested_url_with_wrong_token, '/styles/'), strlen('/styles/')));
+ $this->assertResponse(403, 'Image generated from an earlier derivative was inaccessible at the URL with a missing token, even with an extra forward slash in the URL.');
+ $this->drupalGet(substr_replace($nested_url_with_wrong_token, '/\styles/', strrpos($nested_url_with_wrong_token, '/styles/'), strlen('/styles/')));
+ $this->assertResponse(403, 'Image generated from an earlier derivative was inaccessible at the URL with a missing token, even with an extra backslash in the URL.');
+ // Make sure the image can still be generated if a correct token is used.
+ $this->drupalGet($nested_url);
+ $this->assertResponse(200, 'Image was accessible when a correct token was provided in the URL.');
+
+ // Check that requesting a nonexistent image does not create any new
+ // directories in the file system.
+ $directory = $scheme . '://styles/' . $this->style_name . '/' . $scheme . '/' . $this->randomName();
+ $this->drupalGet(file_create_url($directory . '/' . $this->randomName()));
+ $this->assertFalse(file_exists($directory), 'New directory was not created in the filesystem when requesting an unauthorized image.');
}
}