Finish edits to repository tool doc and update code to fix issues with slow retrieval errors

This commit is contained in:
Vladimir Diaz 2016-10-21 11:36:48 -04:00
parent 404398a0b6
commit 07b4b24343
3 changed files with 35 additions and 16 deletions

View file

@ -891,25 +891,31 @@ Error: No working mirror was found:
### Slow Retrieval Attack ###
In a slow retrieval attack, an attacker responds to clients with a very slow
stream of data that essentially results in the client never continuing the
update process. For this example, we simulate a slow retrieval attack by
spawning a server that serves our update client data at a slow rate. TUF
should not be vulnerable to this attack, and the framework should raise an
update process. In this example, we simulate a slow retrieval attack by
spawning a server that serves data at a slow rate to our update client data.
TUF should not be vulnerable to this attack, and the framework should raise an
exception or error when it detects that a malicious server is serving it data
at a slow enough rate.
We first spawn a server that slowly streams data to a client request. The
'slow_retrieval_server.py' module can be copied over to the '../demo_repository'
directory from which to launch it.
We first spawn the server that slowly streams data to the client. The
'slow_retrieval_server.py' module (can be found in the tests/ directory of the
source code) should be copied over to the server's 'repository/' directory from
which to launch it.
```Bash
# Before launching the slow retrieval server, copy 'slow_retrieval_server.py'
# to the 'repository/' directory and run it from that directory. Assuming
# the current working directory is "repository/":
$ cp ../../../tests/slow_retrieval_server.py .
$ python slow_retrieval_server.py 8002 mode_2
```
The client may now make a request to the slow server on port 8002. However,
before doing so, we'll need to reduce (for the purposes of this demo) the
minimum average download rate allowed. Open the '.../demo/tuf/tuf/conf.py'
file and set MIN_AVERAGE_DOWNLOAD_SPEED to 1. This should make it so
that client correctly detects the slow retrieval server's delayed streaming.
The client may now make a request to the slow retrieval server on port 8002.
However, before doing so, we'll reduce (for the purposes of this demo) the
minimum average download rate allowed and download chunk size. Open the
'conf.py' module and set MIN_AVERAGE_DOWNLOAD_SPEED = 5 and CHUNK_SIZE = 1.
This should make it so that the client detects the slow retrieval server's
delayed streaming.
```Bash
$ python basic_client.py --verbose 1 --repo http://localhost:8002
@ -917,8 +923,8 @@ Error: No working mirror was found:
u'localhost:8002': SlowRetrievalError()
```
The framework should detect the attack and raise a SlowRetrievalError
exception to the client application.
The framework should detect the slow retrieval attack and raise a
SlowRetrievalError exception to the client application.
## Conclusion ##

View file

@ -258,7 +258,7 @@ def __init__(self, average_download_speed):
self.__average_download_speed = average_download_speed #bytes/second
def __str__(self):
return 'Download was too slow. The average download speed has gone' +\
return 'Download was too slow. The average download speed dropped' +\
' below the minimum download speed of ' +\
repr(self.__average_download_speed) + ' bytes per second.'

View file

@ -330,14 +330,14 @@ def _download_fixed_amount_of_data(connection, temp_file, required_length):
data = b''
read_amount = min(tuf.conf.CHUNK_SIZE,
required_length - number_of_bytes_received)
try:
data = connection.read(read_amount)
# Python 3.2 returns 'IOError' if the remote file object has timed out.
except (socket.error, IOError):
pass
number_of_bytes_received = number_of_bytes_received + len(data)
# Data successfully read from the connection. Store it.
@ -356,7 +356,13 @@ def _download_fixed_amount_of_data(connection, temp_file, required_length):
average_download_speed = number_of_bytes_received / seconds_spent_receiving
if average_download_speed < tuf.conf.MIN_AVERAGE_DOWNLOAD_SPEED:
logger.debug('The average download speed dropped below the minimum'
' average download speed set in conf.py.')
break
else:
logger.debug('The average download speed has not dipped below the'
' mimimum average download speed set in conf.py.')
# We might have no more data to read. Check number of bytes downloaded.
if not data:
@ -641,6 +647,13 @@ def _check_downloaded_length(total_downloaded, required_length,
# will log a warning anyway. This is useful when we wish to download the
# Timestamp or Root metadata, for which we have no signed metadata; so,
# we must guess a reasonable required_length for it.
if average_download_speed < tuf.conf.MIN_AVERAGE_DOWNLOAD_SPEED:
raise tuf.SlowRetrievalError(average_download_speed)
else:
logger.debug('Good average download speed: ' +
repr(average_download_speed) + ' bytes per second')
logger.info('Downloaded ' + str(total_downloaded) + ' bytes out of an'
' upper limit of ' + str(required_length) + ' bytes.')