From a013becc66b50db038c1f7f3539040b4482bba18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Sun, 6 Jan 2013 19:49:01 +0100 Subject: Add protection against slowloris vulnerability This changes the behavior of the `timeout` protocol option to mean "Time in which the full request line and headers must be received". The default of 5s should be fine for all normal uses. This change has no noticeable impact on performance and is thus enabled by default for everyone. It can be disabled by setting `timeout` to `infinity` although that is definitely not encouraged. Inspired by the contribution from @naryl on github. --- test/http_SUITE.erl | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'test/http_SUITE.erl') diff --git a/test/http_SUITE.erl b/test/http_SUITE.erl index 7ce0835..607178f 100644 --- a/test/http_SUITE.erl +++ b/test/http_SUITE.erl @@ -60,6 +60,8 @@ -export([set_resp_body/1]). -export([set_resp_header/1]). -export([set_resp_overwrite/1]). +-export([slowloris/1]). +-export([slowloris2/1]). -export([static_attribute_etag/1]). -export([static_function_etag/1]). -export([static_mimetypes_function/1]). @@ -110,6 +112,8 @@ groups() -> set_resp_body, set_resp_header, set_resp_overwrite, + slowloris, + slowloris2, static_attribute_etag, static_function_etag, static_mimetypes_function, @@ -812,6 +816,34 @@ set_resp_overwrite(Config) -> {<<"server">>, <<"DesireDrive/1.0">>} = lists:keyfind(<<"server">>, 1, Headers). +slowloris(Config) -> + Client = ?config(client, Config), + Transport = ?config(transport, Config), + {ok, Client2} = cowboy_client:connect( + Transport, "localhost", ?config(port, Config), Client), + try + [begin + {ok, _} = cowboy_client:raw_request([C], Client2), + receive after 25 -> ok end + end || C <- "GET / HTTP/1.1\r\nHost: localhost\r\n" + "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US)\r\n" + "Cookie: name=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\n\r\n"], + error(failure) + catch error:{badmatch, _} -> + ok + end. + +slowloris2(Config) -> + Client = ?config(client, Config), + Transport = ?config(transport, Config), + {ok, Client2} = cowboy_client:connect( + Transport, "localhost", ?config(port, Config), Client), + {ok, _} = cowboy_client:raw_request("GET / HTTP/1.1\r\n", Client2), + receive after 300 -> ok end, + {ok, _} = cowboy_client:raw_request("Host: localhost\r\n", Client2), + receive after 300 -> ok end, + {ok, 408, _, _} = cowboy_client:response(Client2). + static_attribute_etag(Config) -> Client = ?config(client, Config), {ok, Client2} = cowboy_client:request(<<"GET">>, -- cgit v1.2.3