Skip to content

Commit 520e0ec

Browse files
Merge pull request #72 from pressflow/drupal-7.56
Drupal 7.56
2 parents 6d69f12 + a1826ba commit 520e0ec

5 files changed

Lines changed: 96 additions & 3 deletions

File tree

CHANGELOG.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11

2+
Drupal 7.56, 2017-06-21
3+
-----------------------
4+
- Fixed security issues (access bypass). See SA-CORE-2017-003.
5+
26
Drupal 7.55, 2017-06-07
37
-----------------------
48
- Fixed incompatibility with PHP versions 7.0.19 and 7.1.5 due to duplicate

includes/bootstrap.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
/**
99
* The current system version.
1010
*/
11-
define('VERSION', '7.55');
11+
define('VERSION', '7.56');
1212

1313
/**
1414
* Core API compatibility.

includes/file.inc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1614,6 +1614,20 @@ function file_save_upload($form_field_name, $validators = array(), $destination
16141614

16151615
// If we made it this far it's safe to record this file in the database.
16161616
if ($file = file_save($file)) {
1617+
// Track non-public files in the session if they were uploaded by an
1618+
// anonymous user. This allows modules such as the File module to only
1619+
// grant view access to the specific anonymous user who uploaded the file.
1620+
// See file_file_download().
1621+
// The 'file_public_schema' variable is used to allow other publicly
1622+
// accessible file schemes to be treated the same as the public:// scheme
1623+
// provided by Drupal core and to avoid adding unnecessary data to the
1624+
// session (and the resulting bypass of the page cache) in those cases. For
1625+
// security reasons, only schemes that are completely publicly accessible,
1626+
// with no download restrictions, should be added to this variable. See
1627+
// file_managed_file_value().
1628+
if (!$user->uid && !in_array($destination_scheme, variable_get('file_public_schema', array('public')))) {
1629+
$_SESSION['anonymous_allowed_file_ids'][$file->fid] = $file->fid;
1630+
}
16171631
// Add file to the cache.
16181632
$upload_cache[$form_field_name] = $file;
16191633
return $file;

modules/file/file.module

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,9 @@ function file_file_download($uri, $field_type = 'file') {
146146
// headers for files controlled by other modules. Make an exception for
147147
// temporary files where the host entity has not yet been saved (for example,
148148
// an image preview on a node/add form) in which case, allow download by the
149-
// file's owner.
150-
if (empty($references) && ($file->status == FILE_STATUS_PERMANENT || $file->uid != $user->uid)) {
149+
// file's owner. For anonymous file owners, only the browser session that
150+
// uploaded the file should be granted access.
151+
if (empty($references) && ($file->status == FILE_STATUS_PERMANENT || $file->uid != $user->uid || (!$user->uid && empty($_SESSION['anonymous_allowed_file_ids'][$file->fid])))) {
151152
return;
152153
}
153154

modules/file/tests/file.test

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1551,6 +1551,80 @@ class FilePrivateTestCase extends FileFieldTestCase {
15511551
$this->assertNoRaw($node_file->filename, 'File without view field access permission does not appear after attempting to attach it to a new node.');
15521552
$this->drupalGet(file_create_url($node_file->uri));
15531553
$this->assertResponse(403, 'Confirmed that access is denied for the file without view field access permission after attempting to attach it to a new node.');
1554+
1555+
// As an anonymous user, create a temporary file with no references and
1556+
// confirm that only the session that uploaded it may view it.
1557+
$this->drupalLogout();
1558+
user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array(
1559+
"create $type_name content",
1560+
'access content',
1561+
));
1562+
$test_file = $this->getTestFile('text');
1563+
$this->drupalGet('node/add/' . $type_name);
1564+
$edit = array('files[' . $field_name . '_' . LANGUAGE_NONE . '_0]' => drupal_realpath($test_file->uri));
1565+
$this->drupalPost(NULL, $edit, t('Upload'));
1566+
$files = file_load_multiple(array(), array('uid' => 0));
1567+
$this->assertEqual(1, count($files), 'Loaded one anonymous file.');
1568+
$file = end($files);
1569+
$this->assertNotEqual($file->status, FILE_STATUS_PERMANENT, 'File is temporary.');
1570+
$usage = file_usage_list($file);
1571+
$this->assertFalse($usage, 'No file usage found.');
1572+
$file_url = file_create_url($file->uri);
1573+
$this->drupalGet($file_url);
1574+
$this->assertResponse(200, 'Confirmed that the anonymous uploader has access to the temporary file.');
1575+
// Close the prior connection and remove the session cookie.
1576+
$this->curlClose();
1577+
$this->cookies = array();
1578+
$this->drupalGet($file_url);
1579+
$this->assertResponse(403, 'Confirmed that another anonymous user cannot access the temporary file.');
1580+
1581+
// As an anonymous user, create a permanent file that is referenced by a
1582+
// published node and confirm that all anonymous users may view it.
1583+
$test_file = $this->getTestFile('text');
1584+
$this->drupalGet('node/add/' . $type_name);
1585+
$edit = array();
1586+
$edit['title'] = $this->randomName();
1587+
$edit['files[' . $field_name . '_' . LANGUAGE_NONE . '_0]'] = drupal_realpath($test_file->uri);
1588+
$this->drupalPost(NULL, $edit, t('Save'));
1589+
$new_node = $this->drupalGetNodeByTitle($edit['title']);
1590+
$file = file_load($new_node->{$field_name}[LANGUAGE_NONE][0]['fid']);
1591+
$this->assertEqual($file->status, FILE_STATUS_PERMANENT, 'File is permanent.');
1592+
$usage = file_usage_list($file);
1593+
$this->assertTrue($usage, 'File usage found.');
1594+
$file_url = file_create_url($file->uri);
1595+
$this->drupalGet($file_url);
1596+
$this->assertResponse(200, 'Confirmed that the anonymous uploader has access to the permanent file that is referenced by a published node.');
1597+
// Close the prior connection and remove the session cookie.
1598+
$this->curlClose();
1599+
$this->cookies = array();
1600+
$this->drupalGet($file_url);
1601+
$this->assertResponse(200, 'Confirmed that another anonymous user also has access to the permanent file that is referenced by a published node.');
1602+
1603+
// As an anonymous user, create a permanent file that is referenced by an
1604+
// unpublished node and confirm that no anonymous users may view it (even
1605+
// the session that uploaded the file) because they cannot view the
1606+
// unpublished node.
1607+
$test_file = $this->getTestFile('text');
1608+
$this->drupalGet('node/add/' . $type_name);
1609+
$edit = array();
1610+
$edit['title'] = $this->randomName();
1611+
$edit['files[' . $field_name . '_' . LANGUAGE_NONE . '_0]'] = drupal_realpath($test_file->uri);
1612+
$this->drupalPost(NULL, $edit, t('Save'));
1613+
$new_node = $this->drupalGetNodeByTitle($edit['title']);
1614+
$new_node->status = NODE_NOT_PUBLISHED;
1615+
node_save($new_node);
1616+
$file = file_load($new_node->{$field_name}[LANGUAGE_NONE][0]['fid']);
1617+
$this->assertEqual($file->status, FILE_STATUS_PERMANENT, 'File is permanent.');
1618+
$usage = file_usage_list($file);
1619+
$this->assertTrue($usage, 'File usage found.');
1620+
$file_url = file_create_url($file->uri);
1621+
$this->drupalGet($file_url);
1622+
$this->assertResponse(403, 'Confirmed that the anonymous uploader cannot access the permanent file when it is referenced by an unpublished node.');
1623+
// Close the prior connection and remove the session cookie.
1624+
$this->curlClose();
1625+
$this->cookies = array();
1626+
$this->drupalGet($file_url);
1627+
$this->assertResponse(403, 'Confirmed that another anonymous user cannot access the permanent file when it is referenced by an unpublished node.');
15541628
}
15551629
}
15561630

0 commit comments

Comments
 (0)