The extrinsic set_stickied_threads in runtime-modules/forum/src/lib.rs allows a forum moderator to store a vector of stickied_ids on-chain. There are two issues in this extrinsic, that together result in an issue of moderate severity:
The stickied_ids vector is not checked for duplicate ids.
No deposit is charged for setting stickied_ids.
Combining this two issues would allow an attacker to fill up storage very cheaply and clutter the blockchain storage.
Checking for duplicate ids and fixing issue X would mitigate this issue.
Issue details
A forum moderator can set sticky threads by calling the set_stickied_threads extrinsic in runtime-modules/forum/src/lib.rs. This extrinsic checks for every thread id if that thread id exists and then stores the whole stickied_ids vector on-chain:
The stickied_ids vector is not checked for duplicate ids. As a result, a malicious forum moderator can store a very large vector on-chain by submitting a vector stickied_ids that just consists of one thread id repeated a lot of times.
No deposit is charged for setting stickied_ids. We recommend to always require a deposit that scales linearly with the input when storing arbitrary-length user input on-chain.
Note that there is no deposit charged for creating a thread as well.
Risk
This issue would allow an attacker to fill up the blockchain storage by setting with a very long stickied_ids vector for a lot categories. A full storage is problematic because it could lead to an infeasible amount of storage being required to run a blockchain node.
The risk is reduced by two factors:
Only a category moderator can set sticky threads.
Only one sticky_thread_ids vector per category is stored. This limits the potential to fill up the blockchain storage.
Mitigation
The mitigation is two-fold:
Ensure that the stickied_ids vector does not contain any duplicate thread ids.
To ensure that a correct deposit is charged, we see two possibilities:
2.1 Charge a deposit that scales linearly with the length of the stickied_ids vector. An example of how this could be calculated can be found in the Substrate runtime, see here
Another extrinsic in Substrate which can be taken as an example is the set_identity extrinsic in Substrate/frame/identity/src/lib.rs
fn set_identity(
let extra_fields = info.additional.len() as u32;
[...]
let fd = <BalanceOf<T>>::from(extra_fields) * T::FieldDeposit::get();
2.2 Charge a deposit for each thread. This is the same fix as suggested in issue #5. Note that this will only completely fix the issue if the set_stickied_threads enforces that the stickied_ids vector is duplicate-free. If that is the case, then each of the threads will already have had a deposit charged for it, making it unnecessary to charge a deposit again here.
Summary
The extrinsic
set_stickied_threads
inruntime-modules/forum/src/lib.rs
allows a forum moderator to store a vector ofstickied_ids
on-chain. There are two issues in this extrinsic, that together result in an issue of moderate severity:stickied_ids
vector is not checked for duplicate ids.stickied_ids
.Combining this two issues would allow an attacker to fill up storage very cheaply and clutter the blockchain storage.
Checking for duplicate ids and fixing issue X would mitigate this issue.
Issue details
A forum moderator can set sticky threads by calling the
set_stickied_threads
extrinsic inruntime-modules/forum/src/lib.rs
. This extrinsic checks for every thread id if that thread id exists and then stores the wholestickied_ids
vector on-chain:There are two issues with that process:
stickied_ids
that just consists of one thread id repeated a lot of times.Note that there is no deposit charged for creating a thread as well.
Risk
This issue would allow an attacker to fill up the blockchain storage by setting with a very long
stickied_ids
vector for a lot categories. A full storage is problematic because it could lead to an infeasible amount of storage being required to run a blockchain node.The risk is reduced by two factors:
sticky_thread_ids
vector per category is stored. This limits the potential to fill up the blockchain storage.Mitigation
The mitigation is two-fold:
stickied_ids
vector does not contain any duplicate thread ids.To ensure that a correct deposit is charged, we see two possibilities:
2.1 Charge a deposit that scales linearly with the length of the
stickied_ids
vector. An example of how this could be calculated can be found in the Substrate runtime, see herewhich contains this function:
Another extrinsic in Substrate which can be taken as an example is the
set_identity
extrinsic inSubstrate/frame/identity/src/lib.rs
2.2 Charge a deposit for each thread. This is the same fix as suggested in issue #5. Note that this will only completely fix the issue if the
set_stickied_threads
enforces that thestickied_ids
vector is duplicate-free. If that is the case, then each of the threads will already have had a deposit charged for it, making it unnecessary to charge a deposit again here.