Révision 134c7813
Ajouté par Mathieu Schiano Di Schiabica il y a environ 8 ans
drupal7/modules/file/tests/file.test | ||
---|---|---|
218 | 218 |
$message = isset($message) ? $message : format_string('File %file is permanent.', array('%file' => $file->uri)); |
219 | 219 |
$this->assertTrue($file->status == FILE_STATUS_PERMANENT, $message); |
220 | 220 |
} |
221 |
|
|
222 |
/** |
|
223 |
* Creates a temporary file, for a specific user. |
|
224 |
* |
|
225 |
* @param string $data |
|
226 |
* A string containing the contents of the file. |
|
227 |
* @param int $uid |
|
228 |
* The user ID of the file owner. |
|
229 |
* |
|
230 |
* @return object |
|
231 |
* A file object, or FALSE on error. |
|
232 |
*/ |
|
233 |
function createTemporaryFile($data, $uid = NULL) { |
|
234 |
$file = file_save_data($data, NULL, NULL); |
|
235 |
|
|
236 |
if ($file) { |
|
237 |
$file->uid = isset($uid) ? $uid : $this->admin_user->uid; |
|
238 |
// Change the file status to be temporary. |
|
239 |
$file->status = NULL; |
|
240 |
return file_save($file); |
|
241 |
} |
|
242 |
|
|
243 |
return $file; |
|
244 |
} |
|
221 | 245 |
} |
222 | 246 |
|
223 | 247 |
/** |
... | ... | |
526 | 550 |
} |
527 | 551 |
} |
528 | 552 |
|
553 |
/** |
|
554 |
* Tests exploiting the temporary file removal of another user using fid. |
|
555 |
*/ |
|
556 |
function testTemporaryFileRemovalExploit() { |
|
557 |
// Create a victim user. |
|
558 |
$victim_user = $this->drupalCreateUser(); |
|
559 |
|
|
560 |
// Create an attacker user. |
|
561 |
$attacker_user = $this->drupalCreateUser(array( |
|
562 |
'access content', |
|
563 |
'create page content', |
|
564 |
'edit any page content', |
|
565 |
)); |
|
566 |
|
|
567 |
// Log in as the attacker user. |
|
568 |
$this->drupalLogin($attacker_user); |
|
569 |
|
|
570 |
// Perform tests using the newly created users. |
|
571 |
$this->doTestTemporaryFileRemovalExploit($victim_user->uid, $attacker_user->uid); |
|
572 |
} |
|
573 |
|
|
574 |
/** |
|
575 |
* Tests exploiting the temporary file removal for anonymous users using fid. |
|
576 |
*/ |
|
577 |
public function testTemporaryFileRemovalExploitAnonymous() { |
|
578 |
// Set up an anonymous victim user. |
|
579 |
$victim_uid = 0; |
|
580 |
|
|
581 |
// Set up an anonymous attacker user. |
|
582 |
$attacker_uid = 0; |
|
583 |
|
|
584 |
// Set up permissions for anonymous attacker user. |
|
585 |
user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array( |
|
586 |
'access content' => TRUE, |
|
587 |
'create page content' => TRUE, |
|
588 |
'edit any page content' => TRUE, |
|
589 |
)); |
|
590 |
|
|
591 |
// In order to simulate being the anonymous attacker user, we need to log |
|
592 |
// out here since setUp() has logged in the admin. |
|
593 |
$this->drupalLogout(); |
|
594 |
|
|
595 |
// Perform tests using the newly set up users. |
|
596 |
$this->doTestTemporaryFileRemovalExploit($victim_uid, $attacker_uid); |
|
597 |
} |
|
598 |
|
|
599 |
/** |
|
600 |
* Helper for testing exploiting the temporary file removal using fid. |
|
601 |
* |
|
602 |
* @param int $victim_uid |
|
603 |
* The victim user ID. |
|
604 |
* @param int $attacker_uid |
|
605 |
* The attacker user ID. |
|
606 |
*/ |
|
607 |
protected function doTestTemporaryFileRemovalExploit($victim_uid, $attacker_uid) { |
|
608 |
// Use 'page' instead of 'article', so that the 'article' image field does |
|
609 |
// not conflict with this test. If in the future the 'page' type gets its |
|
610 |
// own default file or image field, this test can be made more robust by |
|
611 |
// using a custom node type. |
|
612 |
$type_name = 'page'; |
|
613 |
$field_name = 'test_file_field'; |
|
614 |
$this->createFileField($field_name, $type_name); |
|
615 |
|
|
616 |
$test_file = $this->getTestFile('text'); |
|
617 |
foreach (array('nojs', 'js') as $type) { |
|
618 |
// Create a temporary file owned by the anonymous victim user. This will be |
|
619 |
// as if they had uploaded the file, but not saved the node they were |
|
620 |
// editing or creating. |
|
621 |
$victim_tmp_file = $this->createTemporaryFile('some text', $victim_uid); |
|
622 |
$victim_tmp_file = file_load($victim_tmp_file->fid); |
|
623 |
$this->assertTrue($victim_tmp_file->status != FILE_STATUS_PERMANENT, 'New file saved to disk is temporary.'); |
|
624 |
$this->assertFalse(empty($victim_tmp_file->fid), 'New file has a fid'); |
|
625 |
$this->assertEqual($victim_uid, $victim_tmp_file->uid, 'New file belongs to the victim user'); |
|
626 |
|
|
627 |
// Have attacker create a new node with a different uploaded file and |
|
628 |
// ensure it got uploaded successfully. |
|
629 |
// @todo Can we test AJAX? See https://www.drupal.org/node/2538260 |
|
630 |
$edit = array( |
|
631 |
'title' => $type . '-title', |
|
632 |
); |
|
633 |
|
|
634 |
// Attach a file to a node. |
|
635 |
$langcode = LANGUAGE_NONE; |
|
636 |
$edit['files[' . $field_name . '_' . $langcode . '_0]'] = drupal_realpath($test_file->uri); |
|
637 |
$this->drupalPost("node/add/$type_name", $edit, 'Save'); |
|
638 |
$node = $this->drupalGetNodeByTitle($edit['title']); |
|
639 |
$node_file = file_load($node->{$field_name}[$langcode][0]['fid']); |
|
640 |
$this->assertFileExists($node_file, 'New file saved to disk on node creation.'); |
|
641 |
$this->assertEqual($attacker_uid, $node_file->uid, 'New file belongs to the attacker.'); |
|
642 |
|
|
643 |
// Ensure the file can be downloaded. |
|
644 |
$this->drupalGet(file_create_url($node_file->uri)); |
|
645 |
$this->assertResponse(200, 'Confirmed that the generated URL is correct by downloading the shipped file.'); |
|
646 |
|
|
647 |
// "Click" the remove button (emulating either a nojs or js submission). |
|
648 |
// In this POST request, the attacker "guesses" the fid of the victim's |
|
649 |
// temporary file and uses that to remove this file. |
|
650 |
$this->drupalGet('node/' . $node->nid . '/edit'); |
|
651 |
switch ($type) { |
|
652 |
case 'nojs': |
|
653 |
$this->drupalPost(NULL, array("{$field_name}[$langcode][0][fid]" => (string) $victim_tmp_file->fid), 'Remove'); |
|
654 |
break; |
|
655 |
case 'js': |
|
656 |
$button = $this->xpath('//input[@type="submit" and @value="Remove"]'); |
|
657 |
$this->drupalPostAJAX(NULL, array("{$field_name}[$langcode][0][fid]" => (string) $victim_tmp_file->fid), array((string) $button[0]['name'] => (string) $button[0]['value'])); |
|
658 |
break; |
|
659 |
} |
|
660 |
|
|
661 |
// The victim's temporary file should not be removed by the attacker's |
|
662 |
// POST request. |
|
663 |
$this->assertFileExists($victim_tmp_file); |
|
664 |
} |
|
665 |
} |
|
666 |
|
|
529 | 667 |
/** |
530 | 668 |
* Tests upload and remove buttons for multiple multi-valued File fields. |
531 | 669 |
*/ |
Formats disponibles : Unified diff
Update to 7.43