Projet

Général

Profil

Révision 134c7813

Ajouté par Mathieu Schiano Di Schiabica il y a environ 8 ans

Update to 7.43

Voir les différences:

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