From f243b252ca25885b8681365b239b68686ed9754a Mon Sep 17 00:00:00 2001 From: Zachary Bowen Date: Tue, 10 Jul 2018 17:30:00 +0200 Subject: [PATCH] Problem: we don't have any tests to cover malicious strings (#2334) * Problem: we don't have any tests for malicious strings Solution: Use a parameterized test that fuzzes over a library of potentially hazardous strings * Needed to update the Dockerfile to install blns * Removed unnecessary import from Dockerfile-dev * Made the conditions under which the test expects an error more explicit * Improved reporting in case of a bad status code * Removed some over-zealous assertions. * Removed `sent_transaction` from assertation error response * *Problem: blns was removed as a dependency while fixing a merge conflict Solution: added it back to the Dockerfile * *Problem: made a typo when adding blns to the Dockerfile Solution: fixed the typo --- Dockerfile-dev | 2 +- acceptance/python/Dockerfile | 3 +- acceptance/python/src/test_naughty_strings.py | 91 +++++++++++++++++++ docker-compose.yml | 2 - 4 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 acceptance/python/src/test_naughty_strings.py diff --git a/Dockerfile-dev b/Dockerfile-dev index 2902a08f..05e4bf98 100644 --- a/Dockerfile-dev +++ b/Dockerfile-dev @@ -33,5 +33,5 @@ RUN mkdir -p /usr/src/app COPY . /usr/src/app/ WORKDIR /usr/src/app RUN pip install --no-cache-dir --process-dependency-links -e .[dev] -RUN bigchaindb -y configure "$backend" +RUN bigchaindb -y configure diff --git a/acceptance/python/Dockerfile b/acceptance/python/Dockerfile index 9e06a7b0..b01105cb 100644 --- a/acceptance/python/Dockerfile +++ b/acceptance/python/Dockerfile @@ -5,4 +5,5 @@ RUN pip install --upgrade \ pycco \ websocket-client~=0.47.0 \ pytest~=3.0 \ - bigchaindb-driver==0.5.0 + bigchaindb-driver==0.5.0 \ + blns \ No newline at end of file diff --git a/acceptance/python/src/test_naughty_strings.py b/acceptance/python/src/test_naughty_strings.py new file mode 100644 index 00000000..54664183 --- /dev/null +++ b/acceptance/python/src/test_naughty_strings.py @@ -0,0 +1,91 @@ +# ## Testing potentially hazardous strings +# This test uses a library of `naughty` strings (code injections, weird unicode chars., etc.) as both keys and values. +# We look for either a successful tx, or in the case that we use a naughty string as a key, and it violates some key +# constraints, we expect to receive a well formatted error message. + +# ## Imports +# We need some utils from the `os` package, we will interact with +# env variables. +import os + +# Since the naughty strings get encoded and decoded in odd ways, we'll use a regex to sweep those details under the rug. +import re + +# We'll use a nice library of naughty strings... +from blns import blns + +# And parameterize our test so each one is treated as a separate test case +import pytest + +# For this test case we import and use the Python Driver. +from bigchaindb_driver import BigchainDB +from bigchaindb_driver.crypto import generate_keypair +from bigchaindb_driver.exceptions import BadRequest + +naughty_strings = blns.all() + + +# This is our base test case, but we'll reuse it to send naughty strings as both keys and values. +def send_naughty_tx(asset, metadata): + # ## Set up a connection to BigchainDB + # Check [test_basic.py](./test_basic.html) to get some more details + # about the endpoint. + bdb = BigchainDB(os.environ.get('BIGCHAINDB_ENDPOINT')) + + # Here's Alice. + alice = generate_keypair() + + # Alice is in a naughty mood today, so she creates a tx with some naughty strings + prepared_transaction = bdb.transactions.prepare( + operation='CREATE', + signers=alice.public_key, + asset=asset, + metadata=metadata) + + # She fulfills the transaction + fulfilled_transaction = bdb.transactions.fulfill( + prepared_transaction, + private_keys=alice.private_key) + + # The fulfilled tx gets sent to the BDB network + try: + sent_transaction = bdb.transactions.send(fulfilled_transaction) + except BadRequest as e: + sent_transaction = e + + # If her key contained a '.', began with a '$', or contained a NUL character + regex = '.*\..*|\$.*|.*\x00.*' + key = next(iter(metadata)) + if re.match(regex, key): + # Then she expects a nicely formatted error code + status_code = sent_transaction.status_code + error = sent_transaction.error + regex = '\{"message":"Invalid transaction \\(ValidationError\\): Invalid key name .* in asset object. ' \ + 'The key name cannot contain characters .* or null characters","status":400\}\n' + assert status_code == 400 + assert re.fullmatch(regex, error), sent_transaction + # Otherwise, she expects to see her transaction in the database + elif 'id' in sent_transaction.keys(): + tx_id = sent_transaction['id'] + assert bdb.transactions.retrieve(tx_id) + # If neither condition was true, then something weird happened... + else: + raise TypeError(sent_transaction) + + +@pytest.mark.parametrize("naughty_string", naughty_strings, ids=naughty_strings) +def test_naughty_keys(naughty_string): + + asset = {'data': {naughty_string: 'nice_value'}} + metadata = {naughty_string: 'nice_value'} + + send_naughty_tx(asset, metadata) + + +@pytest.mark.parametrize("naughty_string", naughty_strings, ids=naughty_strings) +def test_naughty_values(naughty_string): + + asset = {'data': {'nice_key': naughty_string}} + metadata = {'nice_key': naughty_string} + + send_naughty_tx(asset, metadata) diff --git a/docker-compose.yml b/docker-compose.yml index 160d776c..30bb23b6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,8 +15,6 @@ services: build: context: . dockerfile: Dockerfile-dev - args: - backend: localmongodb volumes: - ./bigchaindb:/usr/src/app/bigchaindb - ./tests:/usr/src/app/tests