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
This commit is contained in:
Zachary Bowen 2018-07-10 17:30:00 +02:00 committed by Troy McConaghy
parent 10953a64e7
commit f243b252ca
4 changed files with 94 additions and 4 deletions

View File

@ -33,5 +33,5 @@ RUN mkdir -p /usr/src/app
COPY . /usr/src/app/ COPY . /usr/src/app/
WORKDIR /usr/src/app WORKDIR /usr/src/app
RUN pip install --no-cache-dir --process-dependency-links -e .[dev] RUN pip install --no-cache-dir --process-dependency-links -e .[dev]
RUN bigchaindb -y configure "$backend" RUN bigchaindb -y configure

View File

@ -5,4 +5,5 @@ RUN pip install --upgrade \
pycco \ pycco \
websocket-client~=0.47.0 \ websocket-client~=0.47.0 \
pytest~=3.0 \ pytest~=3.0 \
bigchaindb-driver==0.5.0 bigchaindb-driver==0.5.0 \
blns

View File

@ -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)

View File

@ -15,8 +15,6 @@ services:
build: build:
context: . context: .
dockerfile: Dockerfile-dev dockerfile: Dockerfile-dev
args:
backend: localmongodb
volumes: volumes:
- ./bigchaindb:/usr/src/app/bigchaindb - ./bigchaindb:/usr/src/app/bigchaindb
- ./tests:/usr/src/app/tests - ./tests:/usr/src/app/tests