Skip to content
This repository was archived by the owner on Jul 16, 2020. It is now read-only.

Replay and freeze attacks for pip with TUF

Trishank Karthik Kuppusamy edited this page Sep 21, 2013 · 10 revisions

In a replay or freeze attack, we prevent pip from seeing updates by replaying previous metadata or data. This means that users will not be able to see the latest security updates to packages.

First, we set up the virtual environment (for cleanroom testing) and install pip-with-TUF:

$ cd /tmp
$ curl -O https://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.10.1.tar.gz
$ tar xvfz virtualenv-1.10.1.tar.gz
$ python virtualenv-1.10.1/virtualenv.py --no-site-packages replay-with-tuf
$ source replay-with-tuf/bin/activate
$ sudo apt-get install python-dev libgmp-dev
$ pip install --upgrade https://github.com/theupdateframework/tuf/archive/v0.7.5.zip
$ pip install --upgrade https://github.com/theupdateframework/pip/archive/trishank.poly.edu.zip

First, suppose the attackers on PyPI show you the current FooBar (0.2):

# POINT TO CURRENT REPOSITORY STATE.
$ curl http://mirror1.poly.edu/test-pip/replay/repository.current/tuf.interposition.json -o replay-with-tuf/local/lib/python2.7/site-packages/pip/tuf.interposition.json

# INSTALL LATEST FooBar (0.2).
$ pip install FooBar
Downloading/unpacking FooBar
  Downloading FooBar-0.2.tar.gz (unknown size): 541bytes downloaded
  Running setup.py egg_info for package FooBar
    
Installing collected packages: FooBar
  Running setup.py install for FooBar
    FooBar 0.2
    
Successfully installed FooBar
Cleaning up...

Now, when you try to upgrade FooBar, suppose the attackers on PyPI replay previous FooBar (0.1.):

# POINT TO PREVIOUS REPOSITORY STATE.
$ curl http://mirror1.poly.edu/test-pip/replay/repository.previous/tuf.interposition.json -o replay-with-tuf/local/lib/python2.7/site-packages/pip/tuf.interposition.json

# ATTACKER HAS DOWNGRADED FooBar (0.1) WITH PREVIOUS, VALID METADATA. PIP WITH TUF CATCHES REPLAY.
$ pip install --upgrade FooBar
Cleaning up...
Exception:
Traceback (most recent call last):
  File "/tmp/replay-with-tuf/local/lib/python2.7/site-packages/pip/basecommand.py", line 134, in main
    status = self.run(options, args)
  File "/tmp/replay-with-tuf/local/lib/python2.7/site-packages/pip/commands/install.py", line 270, in run
    sys.exit('TUF stopped the update due to an error:\n'+str(error))
SystemExit: TUF stopped the update due to an error:
No working mirror was found:
  mirror1.poly.edu: Downloaded timestamp is older (1) than the version currently installed (2).

Storing complete log in /home/trishank/.pip/pip.log

Finally, when you try to upgrade FooBar, suppose the attackers on PyPI froze the current FooBar (0.2):

# POINT TO CURRENT REPOSITORY STATE.
$ curl http://mirror1.poly.edu/test-pip/replay/repository.current/tuf.interposition.json -o replay-with-tuf/local/lib/python2.7/site-packages/pip/tuf.interposition.json

# Fast-forward system clock to the future.
$ sudo date --set="Sep 1 01:54:38 UTC 2014"

$ pip install --upgrade FooBar
Cleaning up...
Exception:
Traceback (most recent call last):
  File "/tmp/replay-with-tuf/local/lib/python2.7/site-packages/pip/basecommand.py", line 134, in main
    status = self.run(options, args)
  File "/tmp/replay-with-tuf/local/lib/python2.7/site-packages/pip/commands/install.py", line 270, in run
    sys.exit('TUF stopped the update due to an error:\n'+str(error))
SystemExit: TUF stopped the update due to an error:
Metadata expired on 2014-09-01 01:54:37 UTC.

Storing complete log in /home/trishank/.pip/pip.log

# Return system clock to a current time.
$ sudo ntpdate-debian 

Compare this with the situation where pip or PyPI works without TUF.

Clone this wiki locally