Skip to content

Commit

Permalink
test/alternator: reproducer for DoS in unlimited-precision addition
Browse files Browse the repository at this point in the history
As already noted in issue scylladb#6794, whereas DynamoDB limits the magnitude
of numbers to between 10^-130 and 10^125, Scylla does not. In this patch
we add yet another test for this problem, but unlike previous tests
which just shown too much magnitude being allowed which always sounded
like a benign problem - the test in this patch shows that this "feature"
can be used to DoS Scylla - a user user can send a short request that
causes arbitrarily-large allocations, stalls and CPU usage.

The test is currently marked "skip" because it cause cause Scylla to
take a very long time and/or run out of memory. It passes on DynamoDB
because the excessive magnitude is simply not allowed there.

Refs scylladb#6794

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
  • Loading branch information
nyh committed May 2, 2023
1 parent 022465d commit 56b8b9d
Showing 1 changed file with 24 additions and 0 deletions.
24 changes: 24 additions & 0 deletions test/alternator/test_number.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,30 @@ def test_number_magnitude_not_allowed(test_table_s):
UpdateExpression='SET a = :val',
ExpressionAttributeValues={':val': num})

# DynamoDB limits the magnitude of the numbers (the exponent can be between
# -130 and 125). If we neglect to limit the magnitude, it can allow a user
# to request an addition operation between two numbers of wildly different
# magnitudes, that requires an unlimited amount of memory and CPU time - i.e.,
# a DoS attack. The attacker can cause a std::bad_alloc, large allocations,
# and very long scheduler stall, all with a very short request.
# Due to issue #6794 we need to skip this test, because it takes a very
# long time and/or crashes Scylla.
@pytest.mark.skip(reason="Issue #6794")
def test_number_magnitude_not_allowed_dos(test_table_s):
p = random_string()
# Python's "Decimal" type and the way it's used by the Boto3 library
# has its own limitations, so we need to bypass them with the wrapper
# client_no_transform(), and pass numbers directly to the protocol as
# strings.
a = "1.0"
b = "1.0e100000000"
with pytest.raises(ClientError, match='ValidationException.*overflow'):
with client_no_transform(test_table_s.meta.client) as client:
client.update_item(TableName=test_table_s.name,
Key={'p': {'S': p}},
UpdateExpression='SET x = :a + :b',
ExpressionAttributeValues={':a': {'N': a}, ':b': {'N': b}})

# Check that numbers up to the specified precision (38 decimal digits) can
# be stored and retrieved unchanged.
def test_number_precision_allowed(test_table_s):
Expand Down

0 comments on commit 56b8b9d

Please sign in to comment.