0
Fork 0
mirror of https://github.com/ninenines/cowboy.git synced 2025-07-14 12:20:24 +00:00

Add test case http2_cancel_flood in security suite

This commit is contained in:
Viktor Söderqvist 2023-11-08 20:32:36 +01:00
parent 80b2a5b86a
commit 23eff8ce69

View file

@ -39,6 +39,7 @@ groups() ->
http2_empty_frame_flooding_push_promise, http2_empty_frame_flooding_push_promise,
http2_ping_flood, http2_ping_flood,
http2_reset_flood, http2_reset_flood,
http2_cancel_flood,
http2_settings_flood, http2_settings_flood,
http2_zero_length_header_leak http2_zero_length_header_leak
], ],
@ -72,6 +73,7 @@ init_dispatch(_) ->
cowboy_router:compile([{"localhost", [ cowboy_router:compile([{"localhost", [
{"/", hello_h, []}, {"/", hello_h, []},
{"/echo/:key", echo_h, []}, {"/echo/:key", echo_h, []},
{"/delay_hello", delay_hello_h, 1000},
{"/long_polling", long_polling_h, []}, {"/long_polling", long_polling_h, []},
{"/resp/:key[/:arg]", resp_h, []} {"/resp/:key[/:arg]", resp_h, []}
]}]). ]}]).
@ -229,6 +231,48 @@ http2_reset_flood(Config) ->
ok ok
end. end.
http2_cancel_flood(Config) ->
doc("Confirm that Cowboy detects the rapid reset attack. (CVE-2023-44487)"),
http2_cancel_flood_helper(Config, 1, 500),
http2_cancel_flood_helper(Config, 10, 50),
http2_cancel_flood_helper(Config, 500, 1),
ok.
http2_cancel_flood_helper(Config, NumStreamsPerBatch, NumBatches) ->
{ok, Socket} = rfc7540_SUITE:do_handshake(Config),
{HeadersBlock, _} = cow_hpack:encode([
{<<":method">>, <<"GET">>},
{<<":scheme">>, <<"http">>},
{<<":authority">>, <<"localhost">>}, %% @todo Correct port number.
{<<":path">>, <<"/delay_hello">>}
]),
AllStreamIDs = lists:seq(1, NumBatches * NumStreamsPerBatch * 2, 2),
ct:pal("http2_cancel_flood_helper(..., ~p, ~p)", [NumStreamsPerBatch, NumBatches]),
_ = lists:foldl(
fun (_BatchNumber, AvailableStreamIDs) ->
%% Take a bunch of IDs from the available stream IDs.
%% Send HEADERS for all these and then cancel them.
{IDs, RemainingStreamIDs} = lists:split(NumStreamsPerBatch, AvailableStreamIDs),
_ = gen_tcp:send(Socket, [cow_http2:headers(ID, fin, HeadersBlock) || ID <- IDs]),
_ = gen_tcp:send(Socket, [<<4:24, 3:8, 0:8, ID:32, 8:32>> || ID <- IDs]),
RemainingStreamIDs
end,
AllStreamIDs,
lists:seq(1, NumBatches, 1)),
%% When Cowboy detects a flood it must close the connection.
case gen_tcp:recv(Socket, 9, 6000) of
{ok, <<_:24, 7:8, 0:8, 0:32>>} ->
%% GOAWAY with error code 11 = enhance your calm
{ok, <<_LastStreamId:32, ErrorCode:32>>} =
gen_tcp:recv(Socket, 8, 1000),
11 = ErrorCode, %% ENHANCE_YOUR_CALM
ok;
%% We also accept the connection being closed immediately,
%% which may happen because we send the GOAWAY right before closing.
{error, closed} ->
ok
end.
%% @todo If we ever implement the PRIORITY mechanism, this test should %% @todo If we ever implement the PRIORITY mechanism, this test should
%% be implemented as well. CVE-2019-9513 https://www.kb.cert.org/vuls/id/605641/ %% be implemented as well. CVE-2019-9513 https://www.kb.cert.org/vuls/id/605641/
%% http2_resource_loop %% http2_resource_loop