protected function FileFieldWidgetTestCase::doTestTemporaryFileRemovalExploit in Drupal 7
Helper for testing exploiting the temporary file removal using fid.
Parameters
int $victim_uid: The victim user ID.
int $attacker_uid: The attacker user ID.
2 calls to FileFieldWidgetTestCase::doTestTemporaryFileRemovalExploit()
- FileFieldWidgetTestCase::testTemporaryFileRemovalExploit in modules/
file/ tests/ file.test - Tests exploiting the temporary file removal of another user using fid.
- FileFieldWidgetTestCase::testTemporaryFileRemovalExploitAnonymous in modules/
file/ tests/ file.test - Tests exploiting the temporary file removal for anonymous users using fid.
File
- modules/
file/ tests/ file.test, line 657 - Tests for file.module.
Class
- FileFieldWidgetTestCase
- Tests file field widget.
Code
protected function doTestTemporaryFileRemovalExploit($victim_uid, $attacker_uid) {
// Use 'page' instead of 'article', so that the 'article' image field does
// not conflict with this test. If in the future the 'page' type gets its
// own default file or image field, this test can be made more robust by
// using a custom node type.
$type_name = 'page';
$field_name = 'test_file_field';
$this
->createFileField($field_name, $type_name);
$test_file = $this
->getTestFile('text');
foreach (array(
'nojs',
'js',
) as $type) {
// Create a temporary file owned by the anonymous victim user. This will be
// as if they had uploaded the file, but not saved the node they were
// editing or creating.
$victim_tmp_file = $this
->createTemporaryFile('some text', $victim_uid);
$victim_tmp_file = file_load($victim_tmp_file->fid);
$this
->assertTrue($victim_tmp_file->status != FILE_STATUS_PERMANENT, 'New file saved to disk is temporary.');
$this
->assertFalse(empty($victim_tmp_file->fid), 'New file has a fid');
$this
->assertEqual($victim_uid, $victim_tmp_file->uid, 'New file belongs to the victim user');
// Have attacker create a new node with a different uploaded file and
// ensure it got uploaded successfully.
// @todo Can we test AJAX? See https://www.drupal.org/node/2538260
$edit = array(
'title' => $type . '-title',
);
// Attach a file to a node.
$langcode = LANGUAGE_NONE;
$edit['files[' . $field_name . '_' . $langcode . '_0]'] = drupal_realpath($test_file->uri);
$this
->drupalPost("node/add/{$type_name}", $edit, 'Save');
$node = $this
->drupalGetNodeByTitle($edit['title']);
$node_file = file_load($node->{$field_name}[$langcode][0]['fid']);
$this
->assertFileExists($node_file, 'New file saved to disk on node creation.');
$this
->assertEqual($attacker_uid, $node_file->uid, 'New file belongs to the attacker.');
// Ensure the file can be downloaded.
$this
->drupalGet(file_create_url($node_file->uri));
$this
->assertResponse(200, 'Confirmed that the generated URL is correct by downloading the shipped file.');
// "Click" the remove button (emulating either a nojs or js submission).
// In this POST request, the attacker "guesses" the fid of the victim's
// temporary file and uses that to remove this file.
$this
->drupalGet('node/' . $node->nid . '/edit');
switch ($type) {
case 'nojs':
$this
->drupalPost(NULL, array(
"{$field_name}[{$langcode}][0][fid]" => (string) $victim_tmp_file->fid,
), 'Remove');
break;
case 'js':
$button = $this
->xpath('//input[@type="submit" and @value="Remove"]');
$this
->drupalPostAJAX(NULL, array(
"{$field_name}[{$langcode}][0][fid]" => (string) $victim_tmp_file->fid,
), array(
(string) $button[0]['name'] => (string) $button[0]['value'],
));
break;
}
// The victim's temporary file should not be removed by the attacker's
// POST request.
$this
->assertFileExists($victim_tmp_file);
}
}