google / google/grr

Trivial DoS using the TransferStore.

Open
#607 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
5.1k
Forks
796
PR merge metrics
No merged PRs in 30d

Description

The TransferStore is implemented via a well known flow:
https://github.com/google/grr/blob/master/grr/server/grr_response_server/flows/general/transfer.py#L884

When a file is uploaded from the client, the client will send the bulk data in chunks to the TransferStore well known flow. The flow that initiated the upload receives only a summary of the bulk data (hash and size etc):
https://github.com/google/grr/blob/master/grr/client/grr_response_client/client_actions/file_finder_utils/uploading.py#L73

And it is this summary which is added towards the flow's network bandwidth quota.

Which means that a rogue client can always send any TransferStore requests to the well known flow - even if they have not been issued a flow which requires uploading any files (and therefore there are no network byte limits enforced).

Given that by issue (https://github.com/google/grr/issues/596) a rogue client can connect to any installation without prior authentication this opens the possibility of anyone sending TransferStore operations trivially from the internet.

This is problematic for installations with finite storage space as the TransferStore will just upload the data to the database. For example in the default implementation:
https://github.com/google/grr/blob/debc44219716f4178cd7c3c9f42aff730aa0e22a/grr/server/grr_response_server/blob_stores/memory_stream_bs.py#L19

The blob is uploaded directly into the database row.

Not only is the issue with the amount of data, but also with the number of rows. Typically a blob uploaded will store at least one row in the database (for MySqlAdvancedDB this is several rows - one for each attribute like type, hash etc). Given that a single client POST request can contain millions of TransferStore operations, it is possible to grow the number of rows in the database by millions of rows in a few seconds.

For databases with limited resources this may be problematic. For example the MySql database schema maintains quite a few indexes:
https://github.com/google/grr/blob/debc44219716f4178cd7c3c9f42aff730aa0e22a/grr/server/grr_response_server/data_stores/mysql_advanced_data_store.py#L803

and so these additional insert operations will cause a lot of database pressure. Further since the schema uses the same table for blob and for other data a slow table will affect all GRR operations, not just the transfer store feature.

The overall result is that an adversary can take down the GRR server in a few minutes with little effort on their part.

I think access to the transfer store should be only allowed if the client was given a flow which fetches files and even then, the total uploaded size must be counted towards the flow's quota. This will provide some cap on the amount of data that a rogue client may upload.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.