Recognize a possible endless data attack in the form of invalid JSON metadata.

This commit is contained in:
dachshund 2013-09-08 02:31:50 -04:00
parent 9f1e4f60e9
commit 3d340de4e8
3 changed files with 58 additions and 19 deletions

View file

@ -53,6 +53,21 @@ class FormatError(Error):
class InvalidMetadataJSONError(FormatError):
"""Indicate that a metadata file is not valid JSON."""
def __init__(self, exception):
# Store the original exception.
self.exception = exception
def __str__(self):
# Show the original exception.
return str(self.exception)
class UnsupportedAlgorithmError(Error):
"""Indicate an error while trying to identify a user-specified algorithm."""
pass

View file

@ -695,7 +695,10 @@ def __verify_metadata_file(self, metadata_file_object, metadata_role):
In case a targets role has signed for a target it was not delegated to.
tuf.FormatError:
In case the metadata file is somehow not valid.
In case the metadata file is valid JSON, but not valid TUF metadata.
tuf.InvalidMetadataJSONError:
In case the metadata file is not valid JSON.
tuf.ReplayedMetadataError:
In case the downloaded metadata file is older than the current one.
@ -715,10 +718,14 @@ def __verify_metadata_file(self, metadata_file_object, metadata_role):
"""
# Ensure the loaded 'metadata_signable' is properly formatted.
metadata_signable = \
tuf.util.load_json_string(metadata_file_object.read())
tuf.formats.check_signable_object_format(metadata_signable)
metadata = metadata_file_object.read()
try:
metadata_signable = tuf.util.load_json_string(metadata)
except Exception, exception:
raise tuf.InvalidMetadataJSONError(exception)
else:
# Ensure the loaded 'metadata_signable' is properly formatted.
tuf.formats.check_signable_object_format(metadata_signable)
# Is 'metadata_signable' newer than the currently installed
# version?

View file

@ -31,6 +31,8 @@
"""
from __future__ import print_function
import os
import shutil
import urllib
@ -46,10 +48,9 @@ class EndlessDataAttack(Exception):
def _download(url, filename, tuf=False):
if tuf:
def _download(url, filename, TUF=False):
if TUF:
urllib_tuf.urlretrieve(url, filename)
else:
urllib.urlretrieve(url, filename)
@ -115,13 +116,28 @@ def test_arbitrary_package_attack(TUF=False, TIMESTAMP=False):
try:
# Client downloads (tries to download) the file.
_download(url=url_to_repo, filename=downloaded_file, tuf=TUF)
_download(url=url_to_repo, filename=downloaded_file, TUF=TUF)
except (tuf.DownloadError, tuf.RepositoryError), e:
# If tuf.DownloadError or tuf.RepositoryError is raised, this means
# that TUF has prevented the download of an unrecognized file. Enable
# logging to see what actually happened.
logger.warn('Download failed: '+repr(e))
except tuf.NoWorkingMirrorError, exception:
endless_data_attack = False
for mirror_url, mirror_error in exception.mirror_errors.iteritems():
# We would get a bad hash error if the file was actually larger than
# the metadata said it was.
if isinstance(mirror_error, tuf.BadHashError):
endless_data_attack = True
break
# We would get invalid metadata JSON if the server deliberately sent
# malformed JSON as part of an endless data attack.
elif isinstance(mirror_error, tuf.InvalidMetadataJSONError):
endless_data_attack = True
break
# In case we did not detect what was likely an endless data attack, we
# reraise the exception to indicate that endless data attack detection
# failed.
if not endless_data_attack:
raise
else:
# Check whether the attack succeeded by inspecting the content of the
@ -156,11 +172,12 @@ def test_arbitrary_package_attack(TUF=False, TIMESTAMP=False):
try:
# FIXME: This test passes, but not yet because we avoided an endless data
# attack with timestamp metadata, but rather because the timestamp metadata
# is invalid.
# This test fails because the timestamp metadata has been extended with
# random data from its true length, thereby resulting in invalid JSON.
test_arbitrary_package_attack(TUF=True, TIMESTAMP=True)
raise EndlessDataAttack('Timestamp metadata is not yet immune from the endless data attack!')
except EndlessDataAttack, error:
print('With TUF: '+str(error))
print('With TUF: '+str(error))