def test():

  # Launch the server.
  port = random.randint(30000, 45000)
  command = ['python', 'slow_retrieval_server.py', str(port)]
  server_process = subprocess.Popen(command, stderr=subprocess.PIPE)
  time.sleep(.1)

  try:

    root_repo, url, server_proc, keyids = util_test_tools.init_repo(tuf=True)

    reg_repo = os.path.join(root_repo, 'reg_repo')

    # Make a file in 'reg_repo'.
    filepath = util_test_tools.add_file_to_repository(reg_repo, 'Test')
    
    # Path of the file relative to 'root_repo'.
    relative_filepath = os.path.relpath(filepath)

    # Tailor the url.
    url_to_file = 'http://localhost:'+str(port)+'/'+relative_filepath

    # Download the content of the file using the server.
    file_content = urllib.urlopen(url_to_file)

    print file_content.read()


  finally:
    if server_process.returncode is None:
      server_process.kill()
      print 'Slow server terminated.\n'

    util_test_tools.cleanup(root_repo, server_proc)
Example #2
0
    def setUp(self):
        unittest.TestCase.setUp(self)

        # Unpacking necessary parameters returned from init_repo()
        essential_params = util_test_tools.init_repo(tuf=True)
        self.root_repo = essential_params[0]
        self.url = essential_params[1]
        self.server_proc = essential_params[2]
        self.keyids = essential_params[3]
Example #3
0
  def setUp(self):
    unittest.TestCase.setUp(self)

    # Unpacking necessary parameters returned from init_repo()
    essential_params = util_test_tools.init_repo(tuf=True)
    self.root_repo = essential_params[0] 
    self.url = essential_params[1]
    self.server_proc = essential_params[2]
    self.keyids = essential_params[3]
    self.interpose_json = essential_params[4] 
def test_arbitrary_package_attack(TUF=False):
  """
  <Arguments>
    TUF:
      If set to 'False' all directories that start with 'tuf_' are ignored, 
      indicating that tuf is not implemented.

  <Purpose>
    Illustrate arbitrary package attack vulnerability.

  """

  ERROR_MSG = 'Arbitrary Package Attack was Successful!\n'


  try:
    # Setup.
    root_repo, url, server_proc, keyids = util_test_tools.init_repo(tuf=TUF)
    reg_repo = os.path.join(root_repo, 'reg_repo')
    tuf_repo = os.path.join(root_repo, 'tuf_repo')
    downloads = os.path.join(root_repo, 'downloads')
    targets_dir = os.path.join(tuf_repo, 'targets')

    # Add a file to 'repo' directory: {root_repo}
    filepath = util_test_tools.add_file_to_repository(reg_repo, 'Test A')
    file_basename = os.path.basename(filepath)
    url_to_repo = url+'reg_repo/'+file_basename
    downloaded_file = os.path.join(downloads, file_basename)

    if TUF:
      # Update TUF metadata before attacker modifies anything.
      util_test_tools.tuf_refresh_repo(root_repo, keyids)

      # Modify the url.  Remember that the interposition will intercept 
      # urls that have 'localhost:9999' hostname, which was specified in
      # the json interposition configuration file.  Look for 'hostname'
      # in 'util_test_tools.py'. Further, the 'file_basename' is the target
      # path relative to 'targets_dir'. 
      url_to_repo = 'http://localhost:9999/'+file_basename

      # Attacker modifies the file at the targets repository.
      target = os.path.join(targets_dir, file_basename)
      util_test_tools.modify_file_at_repository(target, 'Evil A')

    # Attacker modifies the file at the regular repository.
    util_test_tools.modify_file_at_repository(filepath, 'Evil A')

    # End of Setup.


    try:
      # Client downloads (tries to download) the file.
      _download(url=url_to_repo, filename=downloaded_file, tuf=TUF)

    except tuf.DownloadError:
      # If tuf.DownloadError is raised, this means that TUF has prevented
      # the download of an unrecognized file.  Enable the logging to see,
      # what actually happened.
      pass

    else:
      # Check whether the attack succeeded by inspecting the content of the
      # update.  The update should contain 'Test A'.  Technically it suffices
      # to check whether the file was downloaded or not.
      downloaded_content = util_test_tools.read_file_content(downloaded_file)
      if 'Test A' != downloaded_content:
        raise ArbitraryPackageAlert(ERROR_MSG)


  finally:
    util_test_tools.cleanup(root_repo, server_proc)
def test_extraneous_dependency_attack(TUF=False):
    """
  <Purpose>
    Illustrate arbitrary package attack vulnerability.

  <Arguments>
    TUF:
      If set to 'False' all directories that start with 'tuf_' are ignored, 
      indicating that tuf is not implemented.

  """

    ERROR_MSG = 'Extraneous Dependency Attack was Successful!\n'

    try:
        # Setup.
        root_repo, url, server_proc, keyids = util_test_tools.init_repo(
            tuf=TUF)
        reg_repo = os.path.join(root_repo, 'reg_repo')
        tuf_repo = os.path.join(root_repo, 'tuf_repo')
        downloads = os.path.join(root_repo, 'downloads')
        targets_dir = os.path.join(tuf_repo, 'targets')

        # Add files to 'repo' directory: {root_repo}.
        good_dependency_filepath = util_test_tools.add_file_to_repository(
            reg_repo, '')
        good_dependency_basename = os.path.basename(good_dependency_filepath)

        bad_dependency_filepath = util_test_tools.add_file_to_repository(
            reg_repo, '')
        bad_dependency_basename = os.path.basename(bad_dependency_filepath)

        # The dependent file lists the good dependency.
        dependent_filepath = util_test_tools.add_file_to_repository(
            reg_repo, good_dependency_basename)
        dependent_basename = os.path.basename(dependent_filepath)

        url_to_repo = url + 'reg_repo/' + dependent_basename
        modified_dependency_list = good_dependency_basename+','+\
          bad_dependency_basename

        if TUF:
            # Update TUF metadata before attacker modifies anything.
            util_test_tools.tuf_refresh_repo(root_repo, keyids)

            # Modify the url.  Remember that the interposition will intercept
            # urls that have 'localhost:9999' hostname, which was specified in
            # the json interposition configuration file.  Look for 'hostname'
            # in 'util_test_tools.py'. Further, the 'file_basename' is the target
            # path relative to 'targets_dir'.
            url_to_repo = 'http://localhost:9999/' + dependent_basename

            # Attacker adds the dependency in the targets repository.
            target = os.path.join(targets_dir, dependent_basename)
            util_test_tools.modify_file_at_repository(
                target, modified_dependency_list)

        # Attacker adds the dependency in the regular repository.
        util_test_tools.modify_file_at_repository(dependent_filepath,
                                                  modified_dependency_list)

        # End of Setup.

        try:
            # Client downloads (tries to download) the file.
            _download(url=url_to_repo,
                      filename=dependent_basename,
                      directory=downloads,
                      TUF=TUF)

        except tuf.DownloadError:
            # If tuf.DownloadError is raised, this means that TUF has prevented
            # the download of an unrecognized file.  Enable the logging to see,
            # what actually happened.
            pass

        else:
            # Check if the legitimate dependency was downloaded.
            if not (os.path.exists(
                    os.path.join(downloads, good_dependency_basename))):
                raise tuf.DownloadError

            # Check if the extraneous dependency was downloaded.
            if os.path.exists(os.path.join(downloads,
                                           bad_dependency_basename)):
                raise ExtraneousDependencyAlert(ERROR_MSG)

    finally:
        util_test_tools.cleanup(root_repo, server_proc)
Example #6
0
def test_arbitrary_package_attack(TUF=False):
    """
  <Arguments>
    TUF:
      If set to 'False' all directories that start with 'tuf_' are ignored, 
      indicating that tuf is not implemented.

  <Purpose>
    Illustrate endless data attack vulnerability.

  """

    ERROR_MSG = 'Endless Data Attack was Successful!\n'

    try:
        # Setup.
        root_repo, url, server_proc, keyids = util_test_tools.init_repo(
            tuf=TUF)
        reg_repo = os.path.join(root_repo, 'reg_repo')
        tuf_repo = os.path.join(root_repo, 'tuf_repo')
        downloads = os.path.join(root_repo, 'downloads')
        tuf_targets = os.path.join(tuf_repo, 'targets')

        # Add a file to 'repo' directory: {root_repo}
        filepath = util_test_tools.add_file_to_repository(reg_repo, 'Test A')
        file_basename = os.path.basename(filepath)
        url_to_repo = url + 'reg_repo/' + file_basename
        downloaded_file = os.path.join(downloads, file_basename)
        endless_data = 'A' * 100

        if TUF:
            # Update TUF metadata before attacker modifies anything.
            util_test_tools.tuf_refresh_repo(root_repo, keyids)

            # Modify the url.  Remember that the interposition will intercept
            # urls that have 'localhost:9999' hostname, which was specified in
            # the json interposition configuration file.  Look for 'hostname'
            # in 'util_test_tools.py'. Further, the 'file_basename' is the target
            # path relative to 'targets_dir'.
            url_to_repo = 'http://localhost:9999/' + file_basename

            # Attacker modifies the file at the targets repository.
            target = os.path.join(tuf_targets, file_basename)
            util_test_tools.modify_file_at_repository(target, endless_data)

        # Attacker modifies the file at the regular repository.
        util_test_tools.modify_file_at_repository(filepath, endless_data)

        # End Setup.

        try:
            # Client downloads (tries to download) the file.
            _download(url=url_to_repo, filename=downloaded_file, tuf=TUF)

        except tuf.DownloadError:
            # If tuf.DownloadError is raised, this means that TUF has prevented
            # the download of an unrecognized file.  Enable the logging to see,
            # what actually happened.
            pass

        else:
            # Check whether the attack succeeded by inspecting the content of the
            # update.  The update should contain 'Test A'.  Technically it suffices
            # to check whether the file was downloaded or not.
            downloaded_content = util_test_tools.read_file_content(
                downloaded_file)
            if 'Test A' != downloaded_content:
                raise EndlessDataAttack(ERROR_MSG)

    finally:
        util_test_tools.cleanup(root_repo, server_proc)
def test_mix_and_match_attack(TUF=False):
  """
  Attack design:
    There are 3 stages:
      Stage 1: Consists of a usual mode of operations using tuf.  Client 
      downloads a target file. (Initial download)

      Stage 2: The target file is legitimately modified and metadata correctly
      updated.  Client downloads the target file again. (Patched target download)

      Stage 3: The target file is legitimately modified  and metadata correctly
      updated again.  However, before client gets to download the newly patched
      target file the attacker replaces the release metadata, targets metadata
      and the target file with the ones from stage 1 (mix-and-match attack).
      Note that timestamp metadata is untouched.  Further note that same would
      happen if only target metadata, and target file are reverted.
  """

  ERROR_MSG = '\tMix-And-Match Attack was Successful!\n\n'


  try:
    # Setup / Stage 1
    # ---------------
    root_repo, url, server_proc, keyids = util_test_tools.init_repo(tuf=TUF)
    reg_repo = os.path.join(root_repo, 'reg_repo')
    downloads = os.path.join(root_repo, 'downloads')
    evil_dir = tempfile.mkdtemp(dir=root_repo)
    
    # Add file to 'repo' directory: {root_repo}
    filepath = util_test_tools.add_file_to_repository(reg_repo, 'A'*10)
    file_basename = os.path.basename(filepath)
    url_to_file = url+'reg_repo/'+file_basename
    downloaded_file = os.path.join(downloads, file_basename)

    # Attacker saves the initial file.
    shutil.copy(filepath, evil_dir)
    unpatched_file = os.path.join(evil_dir, file_basename)


    if TUF:
      print 'TUF ...'
      tuf_repo = os.path.join(root_repo, 'tuf_repo')
      tuf_targets = os.path.join(tuf_repo, 'targets')
      metadata_dir = os.path.join(tuf_repo, 'metadata')
      release_meta_file = os.path.join(metadata_dir, 'release.txt')
      targets_meta_file = os.path.join(metadata_dir, 'targets.txt')
      target = os.path.join(tuf_targets, file_basename)
      
      # Update TUF metadata before attacker modifies anything.
      util_test_tools.tuf_refresh_repo(root_repo, keyids)

      # Attacker saves the original metadata and the target file.
      #shutil.copy(target, evil_dir)
      shutil.copy(release_meta_file, evil_dir)
      shutil.copy(targets_meta_file, evil_dir)
      #target_old = os.path.join(evil_dir, file_basename)
      release_meta_file_old = os.path.join(evil_dir, 'release.txt')
      targets_meta_file_old = os.path.join(evil_dir, 'targets.txt')

      # Modify the url.  Remember that the interposition will intercept 
      # urls that have 'localhost:9999' hostname, which was specified in
      # the json interposition configuration file.  Look for 'hostname'
      # in 'util_test_tools.py'. Further, the 'file_basename' is the target
      # path relative to 'targets_dir'. 
      url_to_file = 'http://localhost:9999/'+file_basename


    # Client's initial download.
    _download(url=url_to_file, filename=downloaded_file, tuf=TUF)

    # Stage 2
    # -------
    # Developer patches the file and updates the repository.
    util_test_tools.modify_file_at_repository(filepath, 'B'*11)

    # Updating tuf repository.  This will copy files from regular repository
    # into tuf repository and refresh the metadata
    if TUF:
      util_test_tools.tuf_refresh_repo(root_repo, keyids)

    # Client downloads the patched file.
    _download(url=url_to_file, filename=downloaded_file, tuf=TUF)

    downloaded_content = util_test_tools.read_file_content(downloaded_file)

    # Stage 3
    # -------
    # Developer patches the file and updates the repository again.
    util_test_tools.modify_file_at_repository(filepath, 'C'*10)

    # Updating tuf repository.  This will copy files from regular repository
    # into tuf repository and refresh the metadata
    if TUF:
      util_test_tools.tuf_refresh_repo(root_repo, keyids)

      # Attacker replaces the metadata and the target file.
      shutil.copyfile(unpatched_file, target)
      shutil.copyfile(release_meta_file_old, release_meta_file)
      shutil.copyfile(targets_meta_file_old, targets_meta_file)

    # Attacker replaces the patched file with the unpatched one.
    shutil.copyfile(unpatched_file, filepath)

    # Client tries to downloads the newly patched file.
    try:
      _download(url=url_to_file, filename=downloaded_file, tuf=TUF)
    except tuf.MetadataNotAvailableError:
      pass

    # Check whether the attack succeeded by inspecting the content of the
    # update.  The update should contain 'Test NOT A'.
    downloaded_content = util_test_tools.read_file_content(downloaded_file)
    if ('B'*11) != downloaded_content:
      raise MixAndMatchAttackAlert(ERROR_MSG)


  finally:
    util_test_tools.cleanup(root_repo, server_proc)
Example #8
0
  def setUp(self):
    """
    The target delegations tree is fixed as such:
      targets -> [T1, T2]
      T1 -> [T3]
    """
    global version
    version = version+1
    expiration = tuf.formats.format_time(time.time()+86400)

    root_repo, url, server_proc, keyids = util_test_tools.init_repo(tuf=True)

    # Server side repository.
    tuf_repo = os.path.join(root_repo, 'tuf_repo')
    keystore_dir = os.path.join(tuf_repo, 'keystore')
    metadata_dir = os.path.join(tuf_repo, 'metadata')
    targets_dir = os.path.join(tuf_repo, 'targets')

    # We need to provide clients with a way to reach the tuf repository.
    tuf_repo_relpath = os.path.basename(tuf_repo)
    tuf_url = url+tuf_repo_relpath

    # Add files to the server side repository.
    # target1 = 'targets_dir/[random].txt'
    # target2 = 'targets_dir/[random].txt'
    add_target = util_test_tools.add_file_to_repository
    target1_path = add_target(targets_dir, data='target1')
    target2_path = add_target(targets_dir, data='target2')

    # Target paths relative to the 'targets_dir'.
    # Ex: targetX = 'targets/delegator/delegatee.txt'
    target1 = os.path.relpath(target1_path, tuf_repo)
    target2 = os.path.relpath(target2_path, tuf_repo)

    # Relative to repository's targets directory.
    target_filepaths = [target1, target2]

    # Store in self only the variables relevant for tests.
    self.root_repo = root_repo
    self.tuf_repo = tuf_repo
    self.server_proc = server_proc
    self.target_filepaths = target_filepaths
    # Targets delegated from A to B.
    self.delegated_targets = {}
    # Targets actually signed by B.
    self.signed_targets = {}
    self.mirrors = {
      "mirror1": {
        "url_prefix": tuf_url,
        "metadata_path": "metadata",
        "targets_path": "targets",
        "confined_target_dirs": [""]
      }
    }
    # Aliases for targets roles.
    self.T0 = 'targets'
    self.T1 = 'targets/T1'
    self.T2 = 'targets/T2'
    self.T3 = 'targets/T1/T3'

    # Get tracked and assigned targets, and generate targets metadata.
    self.make_targets_metadata()
    assert hasattr(self, 'T0_metadata')
    assert hasattr(self, 'T1_metadata')
    assert hasattr(self, 'T2_metadata')
    assert hasattr(self, 'T3_metadata')

    # Make delegation directories at the server's repository.
    metadata_targets_dir = os.path.join(metadata_dir, 'targets')
    metadata_T1_dir = os.path.join(metadata_targets_dir, 'T1')
    os.makedirs(metadata_T1_dir)

    # Delegations metadata paths for the 3 delegated targets roles.
    T0_path = os.path.join(metadata_dir, 'targets.txt')
    T1_path = os.path.join(metadata_targets_dir, 'T1.txt')
    T2_path = os.path.join(metadata_targets_dir, 'T2.txt')
    T3_path = os.path.join(metadata_T1_dir, 'T3.txt')

    # Generate RSA keys for the 3 delegatees.
    key1 = signerlib.generate_and_save_rsa_key(keystore_dir, 'T1')
    key2 = signerlib.generate_and_save_rsa_key(keystore_dir, 'T2')
    key3 = signerlib.generate_and_save_rsa_key(keystore_dir, 'T3')

    # ID for each of the 3 keys.
    key1_id = key1['keyid']
    key2_id = key2['keyid']
    key3_id = key3['keyid']

    # ID, in a list, for each of the 3 keys.
    key1_ids = [key1_id]
    key2_ids = [key2_id]
    key3_ids = [key3_id]

    # Public-key JSON for each of the 3 keys.
    key1_val = tuf.rsa_key.create_in_metadata_format(key1['keyval'])
    key2_val = tuf.rsa_key.create_in_metadata_format(key2['keyval'])
    key3_val = tuf.rsa_key.create_in_metadata_format(key3['keyval'])

    # Create delegation role metadata for each of the 3 delegated targets roles.
    make_role_metadata = tuf.formats.make_role_metadata

    T1_targets = self.relpath_from_targets(self.delegated_targets[self.T1])
    T1_role = make_role_metadata(key1_ids, 1, name=self.T1, paths=T1_targets)

    T2_targets = self.relpath_from_targets(self.delegated_targets[self.T2])
    T2_role = make_role_metadata(key2_ids, 1, name=self.T2, paths=T2_targets)

    T3_targets = self.relpath_from_targets(self.delegated_targets[self.T3])
    T3_role = make_role_metadata(key3_ids, 1, name=self.T3, paths=T3_targets)

    # Assign 'delegations' object for 'targets':
    self.T0_metadata['signed']['delegations'] = {
      'keys': {key1_id: key1_val, key2_id: key2_val},
      'roles': [T1_role, T2_role]
    }

    # Assign 'delegations' object for 'targets/T1':
    self.T1_metadata['signed']['delegations'] = {
      'keys': {key3_id: key3_val},
      'roles': [T3_role]
    }

    sign = signerlib.sign_metadata
    write = signerlib.write_metadata_file

    # Sign new metadata objects.
    T0_signable = sign(self.T0_metadata, keyids, T0_path)
    T1_signable = sign(self.T1_metadata, key1_ids, T1_path)
    T2_signable = sign(self.T2_metadata, key2_ids, T2_path)
    T3_signable = sign(self.T3_metadata, key3_ids, T3_path)
    # Save new metadata objects.
    write(T0_signable, T0_path)
    write(T1_signable, T1_path)
    write(T2_signable, T2_path)
    write(T3_signable, T3_path)

    # Timestamp a new release to reflect latest targets.
    signerlib.build_release_file(keyids, metadata_dir, version, expiration)
    signerlib.build_timestamp_file(keyids, metadata_dir, version, expiration)

    # Unload all keys.
    keystore.clear_keystore()
def test_indefinite_freeze_attack(TUF=False):
  """
  <Arguments>
    TUF:
      If set to 'False' all directories that start with 'tuf_' are ignored, 
      indicating that tuf is not implemented.

  The idea here is to expire timestamp metadata so that the attacker 

  """

  ERROR_MSG = '\tIndefinite Freeze Attack was Successful!\n\n'


  try:
    # Setup.
    root_repo, url, server_proc, keyids = util_test_tools.init_repo(tuf=TUF)
    reg_repo = os.path.join(root_repo, 'reg_repo')
    tuf_repo = os.path.join(root_repo, 'tuf_repo')
    metadata_dir = os.path.join(tuf_repo, 'metadata')
    downloads = os.path.join(root_repo, 'downloads')
    
    # Add file to 'repo' directory: {root_repo}
    filepath = util_test_tools.add_file_to_repository(reg_repo, 'Test A')
    file_basename = os.path.basename(filepath)
    url_to_repo = url+'reg_repo/'+file_basename
    downloaded_file = os.path.join(downloads, file_basename)

    if TUF:
      print 'TUF ...'

      # Update TUF metadata before attacker modifies anything.
      util_test_tools.tuf_refresh_repo(root_repo, keyids)

      # Modify the url.  Remember that the interposition will intercept 
      # urls that have 'localhost:9999' hostname, which was specified in
      # the json interposition configuration file.  Look for 'hostname'
      # in 'util_test_tools.py'. Further, the 'file_basename' is the target
      # path relative to 'targets_dir'. 
      url_to_repo = 'http://localhost:9999/'+file_basename

      # Make timestamp metadata with close expiration date (2s).
      _remake_timestamp(metadata_dir, keyids)


    # Client performs initial download.
    try:
      _download(url=url_to_repo, filename=downloaded_file, tuf=TUF)
    except tuf.ExpiredMetadataError:
      msg = ('Metadata has expired too soon, extend expiration period. '+
             'Current expiration is set to: '+repr(EXPIRATION)+' second(s).')
      sys.exit(msg)

    # Expire timestamp.
    time.sleep(EXPIRATION)

    # Try downloading again, this should raise an error.
    try:
      _download(url=url_to_repo, filename=downloaded_file, tuf=TUF)
    except tuf.ExpiredMetadataError, error:
      pass
    else:
Example #10
0
    def setUp(self):
        """
    The target delegations tree is fixed as such:
      targets -> [T1, T2]
      T1 -> [T3]
    """
        global version
        version = version + 1
        expiration = tuf.formats.format_time(time.time() + 86400)

        root_repo, url, server_proc, keyids = util_test_tools.init_repo(
            tuf=True)

        # Server side repository.
        tuf_repo = os.path.join(root_repo, 'tuf_repo')
        keystore_dir = os.path.join(tuf_repo, 'keystore')
        metadata_dir = os.path.join(tuf_repo, 'metadata')
        targets_dir = os.path.join(tuf_repo, 'targets')

        # We need to provide clients with a way to reach the tuf repository.
        tuf_repo_relpath = os.path.basename(tuf_repo)
        tuf_url = url + tuf_repo_relpath

        # Add files to the server side repository.
        # target1 = 'targets_dir/[random].txt'
        # target2 = 'targets_dir/[random].txt'
        add_target = util_test_tools.add_file_to_repository
        target1_path = add_target(targets_dir, data='target1')
        target2_path = add_target(targets_dir, data='target2')

        # Target paths relative to the 'targets_dir'.
        # Ex: targetX = 'targets/delegator/delegatee.txt'
        target1 = os.path.relpath(target1_path, tuf_repo)
        target2 = os.path.relpath(target2_path, tuf_repo)

        # Relative to repository's targets directory.
        target_filepaths = [target1, target2]

        # Store in self only the variables relevant for tests.
        self.root_repo = root_repo
        self.tuf_repo = tuf_repo
        self.server_proc = server_proc
        self.target_filepaths = target_filepaths
        # Targets delegated from A to B.
        self.delegated_targets = {}
        # Targets actually signed by B.
        self.signed_targets = {}
        self.mirrors = {
            "mirror1": {
                "url_prefix": tuf_url,
                "metadata_path": "metadata",
                "targets_path": "targets",
                "confined_target_dirs": [""]
            }
        }
        # Aliases for targets roles.
        self.T0 = 'targets'
        self.T1 = 'targets/T1'
        self.T2 = 'targets/T2'
        self.T3 = 'targets/T1/T3'

        # Get tracked and assigned targets, and generate targets metadata.
        self.make_targets_metadata()
        assert hasattr(self, 'T0_metadata')
        assert hasattr(self, 'T1_metadata')
        assert hasattr(self, 'T2_metadata')
        assert hasattr(self, 'T3_metadata')

        # Make delegation directories at the server's repository.
        metadata_targets_dir = os.path.join(metadata_dir, 'targets')
        metadata_T1_dir = os.path.join(metadata_targets_dir, 'T1')
        os.makedirs(metadata_T1_dir)

        # Delegations metadata paths for the 3 delegated targets roles.
        T0_path = os.path.join(metadata_dir, 'targets.txt')
        T1_path = os.path.join(metadata_targets_dir, 'T1.txt')
        T2_path = os.path.join(metadata_targets_dir, 'T2.txt')
        T3_path = os.path.join(metadata_T1_dir, 'T3.txt')

        # Generate RSA keys for the 3 delegatees.
        key1 = signerlib.generate_and_save_rsa_key(keystore_dir, 'T1')
        key2 = signerlib.generate_and_save_rsa_key(keystore_dir, 'T2')
        key3 = signerlib.generate_and_save_rsa_key(keystore_dir, 'T3')

        # ID for each of the 3 keys.
        key1_id = key1['keyid']
        key2_id = key2['keyid']
        key3_id = key3['keyid']

        # ID, in a list, for each of the 3 keys.
        key1_ids = [key1_id]
        key2_ids = [key2_id]
        key3_ids = [key3_id]

        # Public-key JSON for each of the 3 keys.
        key1_val = tuf.rsa_key.create_in_metadata_format(key1['keyval'])
        key2_val = tuf.rsa_key.create_in_metadata_format(key2['keyval'])
        key3_val = tuf.rsa_key.create_in_metadata_format(key3['keyval'])

        # Create delegation role metadata for each of the 3 delegated targets roles.
        make_role_metadata = tuf.formats.make_role_metadata

        T1_targets = self.relpath_from_targets(self.delegated_targets[self.T1])
        T1_role = make_role_metadata(key1_ids,
                                     1,
                                     name=self.T1,
                                     paths=T1_targets)

        T2_targets = self.relpath_from_targets(self.delegated_targets[self.T2])
        T2_role = make_role_metadata(key2_ids,
                                     1,
                                     name=self.T2,
                                     paths=T2_targets)

        T3_targets = self.relpath_from_targets(self.delegated_targets[self.T3])
        T3_role = make_role_metadata(key3_ids,
                                     1,
                                     name=self.T3,
                                     paths=T3_targets)

        # Assign 'delegations' object for 'targets':
        self.T0_metadata['signed']['delegations'] = {
            'keys': {
                key1_id: key1_val,
                key2_id: key2_val
            },
            'roles': [T1_role, T2_role]
        }

        # Assign 'delegations' object for 'targets/T1':
        self.T1_metadata['signed']['delegations'] = {
            'keys': {
                key3_id: key3_val
            },
            'roles': [T3_role]
        }

        sign = signerlib.sign_metadata
        write = signerlib.write_metadata_file

        # Sign new metadata objects.
        T0_signable = sign(self.T0_metadata, keyids, T0_path)
        T1_signable = sign(self.T1_metadata, key1_ids, T1_path)
        T2_signable = sign(self.T2_metadata, key2_ids, T2_path)
        T3_signable = sign(self.T3_metadata, key3_ids, T3_path)
        # Save new metadata objects.
        write(T0_signable, T0_path)
        write(T1_signable, T1_path)
        write(T2_signable, T2_path)
        write(T3_signable, T3_path)

        # Timestamp a new release to reflect latest targets.
        signerlib.build_release_file(keyids, metadata_dir, version, expiration)
        signerlib.build_timestamp_file(keyids, metadata_dir, version,
                                       expiration)

        # Unload all keys.
        keystore.clear_keystore()
def test_replay_attack(TUF=False):
  """
  <Arguments>
    TUF:
      If set to 'False' all directories that start with 'tuf_' are ignored, 
      indicating that tuf is not implemented.

  <Purpose>
    

  """

  try:
    # Setup.
    root_repo, url, server_proc, keyids, interpose_json = \
      util_test_tools.init_repo(tuf=TUF)
    reg_repo = os.path.join(root_repo, 'reg_repo')
    tuf_repo = os.path.join(root_repo, 'tuf_repo')
    downloads = os.path.join(root_repo, 'downloads')
    tuf_targets = os.path.join(tuf_repo, 'targets')

    # Add file to 'repo' directory: {root_repo}
    filepath = util_test_tools.add_file_to_repository(reg_repo, 'Test A')
    file_basename = os.path.basename(filepath)
    url_to_repo = url+'reg_repo/'+file_basename
    downloaded_file = os.path.join(downloads, file_basename)

    # Attacker saves the original file into 'evil_dir'.
    evil_dir = tempfile.mkdtemp(dir=root_repo)
    vulnerable_file = os.path.join(evil_dir, file_basename)
    shutil.copy(filepath, evil_dir)

    # Refresh the tuf repository and apply tuf interpose.
    if TUF:
      util_test_tools.tuf_refresh_repo(root_repo, keyids)
      tuf.interposition.configure(interpose_json)
      tuf.interposition.interpose()

    # End Setup.

    # Client performs initial update.
    urllib.urlretrieve(url_to_repo, downloaded_file)

    # Downloads are stored in the same directory '{root_repo}/downloads/'
    # for regular and tuf clients.
    downloaded_content = util_test_tools.read_file_content(downloaded_file)
    msg = '[Initial Updata] Failed to download the file.'
    if 'Test A' != downloaded_content:
      raise TestSetupError(msg)

    # Developer patches the file and updates the repository.
    util_test_tools.modify_file_at_repository(filepath, 'Test NOT A')

    # Updating tuf repository.  This will copy files from regular repository
    # into tuf repository and refresh the metad 
    if TUF:
      util_test_tools.tuf_refresh_repo(root_repo, keyids)

    # Client downloads the patched file.
    urllib.urlretrieve(url_to_repo, downloaded_file)

    # Content of the downloaded file.
    downloaded_content = util_test_tools.read_file_content(downloaded_file)
    msg = '[Update] Failed to update the file.'
    if 'Test NOT A' != downloaded_content:
      raise TestSetupError(msg)

    # Attacker tries to be clever, he manages to modifies regular and tuf 
    # targets directory by replacing a patched file with an old one.
    if os.path.isdir(tuf_targets):
      target = os.path.join(tuf_targets, file_basename)
      util_test_tools.delete_file_at_repository(target)
      shutil.copy(vulnerable_file, tuf_targets)
      # Verify that 'target' is an old, un-patched file.
      target = os.path.join(tuf_targets, file_basename)
      target_content = util_test_tools.read_file_content(target)
      msg = "The 'target' file contains new data!"
      if 'Test A' != target_content:
        raise TestSetupError(msg)
    else:
      util_test_tools.delete_file_at_repository(filepath)
      shutil.copy(vulnerable_file, reg_repo)

    # Client downloads the file once time.
    urllib.urlretrieve(url_to_repo, downloaded_file)

    # Check whether the attack succeeded by inspecting the content of the
    # update.  The update should contain 'Test NOT A'.
    downloaded_content = util_test_tools.read_file_content(downloaded_file)
    msg = 'Replay attack was successful!\n'
    if 'Test NOT A' != downloaded_content:
      raise ReplayAttackError(msg)

  finally:
    tuf.interposition.go_away()
    util_test_tools.cleanup(root_repo, server_proc)
def test_extraneous_dependencies_attack():

  try:

    # Setup.
    root_repo, url, server_proc, keyids = util_test_tools.init_repo(tuf=True)
    reg_repo = os.path.join(root_repo, 'reg_repo')
    tuf_repo = os.path.join(root_repo, 'tuf_repo')
    keystore_dir = os.path.join(tuf_repo, 'keystore')
    metadata_dir = os.path.join(tuf_repo, 'metadata')
    downloads_dir = os.path.join(root_repo, 'downloads')
    targets_dir = os.path.join(tuf_repo, 'targets')

    # 'roles' holds information about delegated roles.
    roles = {'role1':{'password':['pass1']},
                       'role2':{'password':['pass2']}}

    # Add files to 'reg_repo' directory: {root_repo}
    role1_path = tempfile.mkdtemp(dir=reg_repo)
    roles['role1']['filepath'] = \
      util_test_tools.add_file_to_repository(role1_path, 'Test A')

    role2_path = tempfile.mkdtemp(dir=reg_repo)
    roles['role2']['filepath'] = \
      util_test_tools.add_file_to_repository(role2_path, 'Test B')

    # Update TUF repository.
    util_test_tools.make_targets_meta(root_repo)
    util_test_tools.make_release_meta(root_repo)
    util_test_tools.make_timestamp_meta(root_repo)


    def _make_delegation(rolename):

      # Indicate which file client downloads.
      rel_filepath = os.path.relpath(roles[rolename]['filepath'], reg_repo)
      roles[rolename]['target_path'] = os.path.join(targets_dir, rel_filepath)
      rolepath, file_basename = os.path.split(roles[rolename]['filepath'])
      junk, role_relpath = os.path.split(rolepath)
      roles[rolename]['targets_dir'] = os.path.join(targets_dir, role_relpath)
      roles[rolename]['metadata_dir'] =  os.path.join(metadata_dir, 'targets')

      # Create a key to sign a new delegated role.
      password = roles[rolename]['password'][0]
      key = signerlib.generate_and_save_rsa_key(keystore_dir, password)
      roles[rolename]['keyid'] = [key['keyid']]
      roles[rolename]['dest_path'] = os.path.join(downloads_dir, file_basename)

      # Create delegation one.
      util_test_tools.create_delegation(tuf_repo, 
                                        roles[rolename]['targets_dir'], 
                                        roles[rolename]['keyid'], password, 
                                        'targets', rolename)

      # Update TUF repository.
      # util_test_tools.make_targets_meta(root_repo)
      util_test_tools.make_release_meta(root_repo)
      util_test_tools.make_timestamp_meta(root_repo)

      # Modify the url.  Remember that the interposition will intercept 
      # urls that have 'localhost:9999' hostname, which was specified in
      # the json interposition configuration file.  Look for 'hostname'
      # in 'util_test_tools.py'. Further, the 'file_basename' is the target
      # path relative to 'targets_dir'. 
      roles[rolename]['url'] = 'http://localhost:9999/'+rel_filepath

      # Perform a client download.
      urllib_tuf.urlretrieve(roles[rolename]['url'],
                             roles[rolename]['dest_path'])


    _make_delegation('role1')
    _make_delegation('role2')


    # The attack.
    # Modify a target that was delegated to 'role2'.
    util_test_tools.modify_file_at_repository(roles['role2']['target_path'], 
                                              'Test NOT B')

    # Load the keystore before rebuilding the metadata.
    tuf.repo.keystore.load_keystore_from_keyfiles(keystore_dir,
                                                  roles['role1']['keyid'],
                                                  roles['role1']['password'])

    # Rebuild the delegation role metadata.
    signerlib.build_delegated_role_file(roles['role2']['targets_dir'], 
                                        roles['role1']['keyid'], metadata_dir,
                                        roles['role1']['metadata_dir'],
                                        'role1.txt')

    # Update release and timestamp metadata.
    util_test_tools.make_release_meta(root_repo)
    util_test_tools.make_timestamp_meta(root_repo)


    # Perform another client download.
    try:
      urllib_tuf.urlretrieve(roles['role2']['url'], roles['role2']['dest_path'])
    except tuf.MetadataNotAvailableError, e:
      raise


  finally:  
    server_proc.kill()
    util_test_tools.cleanup(root_repo, server_proc)
Example #13
0
def test_mix_and_match_attack(TUF=False):
    """
  Attack design:
    There are 3 stages:
      Stage 1: Consists of a usual mode of operations using tuf.  Client 
      downloads a target file. (Initial download)

      Stage 2: The target file is legitimately modified and metadata correctly
      updated.  Client downloads the target file again. (Patched target download)

      Stage 3: The target file is legitimately modified  and metadata correctly
      updated again.  However, before client gets to download the newly patched
      target file the attacker replaces the release metadata, targets metadata
      and the target file with the ones from stage 1 (mix-and-match attack).
      Note that timestamp metadata is untouched.  Further note that same would
      happen if only target metadata, and target file are reverted.
  """

    ERROR_MSG = '\tMix-And-Match Attack was Successful!\n\n'

    try:
        # Setup / Stage 1
        # ---------------
        root_repo, url, server_proc, keyids = util_test_tools.init_repo(
            tuf=TUF)
        reg_repo = os.path.join(root_repo, 'reg_repo')
        downloads = os.path.join(root_repo, 'downloads')
        evil_dir = tempfile.mkdtemp(dir=root_repo)

        # Add file to 'repo' directory: {root_repo}
        filepath = util_test_tools.add_file_to_repository(reg_repo, 'A' * 10)
        file_basename = os.path.basename(filepath)
        url_to_file = url + 'reg_repo/' + file_basename
        downloaded_file = os.path.join(downloads, file_basename)

        # Attacker saves the initial file.
        shutil.copy(filepath, evil_dir)
        unpatched_file = os.path.join(evil_dir, file_basename)

        if TUF:
            print 'TUF ...'
            tuf_repo = os.path.join(root_repo, 'tuf_repo')
            tuf_targets = os.path.join(tuf_repo, 'targets')
            metadata_dir = os.path.join(tuf_repo, 'metadata')
            release_meta_file = os.path.join(metadata_dir, 'release.txt')
            targets_meta_file = os.path.join(metadata_dir, 'targets.txt')
            target = os.path.join(tuf_targets, file_basename)

            # Update TUF metadata before attacker modifies anything.
            util_test_tools.tuf_refresh_repo(root_repo, keyids)

            # Attacker saves the original metadata and the target file.
            #shutil.copy(target, evil_dir)
            shutil.copy(release_meta_file, evil_dir)
            shutil.copy(targets_meta_file, evil_dir)
            #target_old = os.path.join(evil_dir, file_basename)
            release_meta_file_old = os.path.join(evil_dir, 'release.txt')
            targets_meta_file_old = os.path.join(evil_dir, 'targets.txt')

            # Modify the url.  Remember that the interposition will intercept
            # urls that have 'localhost:9999' hostname, which was specified in
            # the json interposition configuration file.  Look for 'hostname'
            # in 'util_test_tools.py'. Further, the 'file_basename' is the target
            # path relative to 'targets_dir'.
            url_to_file = 'http://localhost:9999/' + file_basename

        # Client's initial download.
        _download(url=url_to_file, filename=downloaded_file, tuf=TUF)

        # Stage 2
        # -------
        # Developer patches the file and updates the repository.
        util_test_tools.modify_file_at_repository(filepath, 'B' * 11)

        # Updating tuf repository.  This will copy files from regular repository
        # into tuf repository and refresh the metadata
        if TUF:
            util_test_tools.tuf_refresh_repo(root_repo, keyids)

        # Client downloads the patched file.
        _download(url=url_to_file, filename=downloaded_file, tuf=TUF)

        downloaded_content = util_test_tools.read_file_content(downloaded_file)

        # Stage 3
        # -------
        # Developer patches the file and updates the repository again.
        util_test_tools.modify_file_at_repository(filepath, 'C' * 10)

        # Updating tuf repository.  This will copy files from regular repository
        # into tuf repository and refresh the metadata
        if TUF:
            util_test_tools.tuf_refresh_repo(root_repo, keyids)

            # Attacker replaces the metadata and the target file.
            shutil.copyfile(unpatched_file, target)
            shutil.copyfile(release_meta_file_old, release_meta_file)
            shutil.copyfile(targets_meta_file_old, targets_meta_file)

        # Attacker replaces the patched file with the unpatched one.
        shutil.copyfile(unpatched_file, filepath)

        # Client tries to downloads the newly patched file.
        try:
            _download(url=url_to_file, filename=downloaded_file, tuf=TUF)
        except tuf.MetadataNotAvailableError:
            pass

        # Check whether the attack succeeded by inspecting the content of the
        # update.  The update should contain 'Test NOT A'.
        downloaded_content = util_test_tools.read_file_content(downloaded_file)
        if ('B' * 11) != downloaded_content:
            raise MixAndMatchAttackAlert(ERROR_MSG)

    finally:
        util_test_tools.cleanup(root_repo, server_proc)
Example #14
0
def test_replay_attack(TUF=False):
  """
  <Arguments>
    TUF:
      If set to 'False' all directories that start with 'tuf_' are ignored, 
      indicating that tuf is not implemented.

  <Purpose>
    Illustrate replay attack vulnerability.

  """

  ERROR_MSG = 'Replay Attack was Successful!\n'


  try:
    # Setup.
    root_repo, url, server_proc, keyids = util_test_tools.init_repo(tuf=TUF)
    reg_repo = os.path.join(root_repo, 'reg_repo')
    tuf_repo = os.path.join(root_repo, 'tuf_repo')
    downloads = os.path.join(root_repo, 'downloads')
    tuf_targets = os.path.join(tuf_repo, 'targets')

    # Add file to 'repo' directory: {root_repo}
    filepath = util_test_tools.add_file_to_repository(reg_repo, 'Test A')
    file_basename = os.path.basename(filepath)
    url_to_repo = url+'reg_repo/'+file_basename
    downloaded_file = os.path.join(downloads, file_basename)

    # Attacker saves the original file into 'evil_dir'.
    evil_dir = tempfile.mkdtemp(dir=root_repo)
    vulnerable_file = os.path.join(evil_dir, file_basename)
    shutil.copy(filepath, evil_dir)

    if TUF:
      # Update TUF metadata before attacker modifies anything.
      util_test_tools.tuf_refresh_repo(root_repo, keyids)

      # Modify the url.  Remember that the interposition will intercept 
      # urls that have 'localhost:9999' hostname, which was specified in
      # the json interposition configuration file.  Look for 'hostname'
      # in 'util_test_tools.py'. Further, the 'file_basename' is the target
      # path relative to 'targets_dir'. 
      url_to_repo = 'http://localhost:9999/'+file_basename

    # End of Setup.


    # Client performs initial update.
    _download(url=url_to_repo, filename=downloaded_file, tuf=TUF)

    # Downloads are stored in the same directory '{root_repo}/downloads/'
    # for regular and tuf clients.
    downloaded_content = util_test_tools.read_file_content(downloaded_file)
    if 'Test A' != downloaded_content:
      raise TestSetupError('[Initial Updata] Failed to download the file.')

    # Developer patches the file and updates the repository.
    util_test_tools.modify_file_at_repository(filepath, 'Test NOT A')

    # Updating tuf repository.  This will copy files from regular repository
    # into tuf repository and refresh the metad 
    if TUF:
      util_test_tools.tuf_refresh_repo(root_repo, keyids)


    # Client downloads the patched file.
    _download(url=url_to_repo, filename=downloaded_file, tuf=TUF)

    # Content of the downloaded file.
    downloaded_content = util_test_tools.read_file_content(downloaded_file)
    if 'Test NOT A' != downloaded_content:
      raise TestSetupError('[Update] Failed to update the file.')

    # Attacker tries to be clever, he manages to modifies regular and tuf 
    # targets directory by replacing a patched file with an old one.
    if os.path.isdir(tuf_targets):
      target = os.path.join(tuf_targets, file_basename)
      util_test_tools.delete_file_at_repository(target)
      shutil.copy(vulnerable_file, tuf_targets)
      # Verify that 'target' is an old, un-patched file.
      target = os.path.join(tuf_targets, file_basename)
      target_content = util_test_tools.read_file_content(target)
      if 'Test A' != target_content:
        raise TestSetupError("The 'target' file contains new data!")

    else:
      util_test_tools.delete_file_at_repository(filepath)
      shutil.copy(vulnerable_file, reg_repo)


    # Client downloads the file once more.
    _download(url=url_to_repo, filename=downloaded_file, tuf=TUF)

    # Check whether the attack succeeded by inspecting the content of the
    # update.  The update should contain 'Test NOT A'.
    downloaded_content = util_test_tools.read_file_content(downloaded_file)
    if 'Test NOT A' != downloaded_content:
      raise ReplayAttackAlert(ERROR_MSG)


  finally:
    util_test_tools.cleanup(root_repo, server_proc)