Skip to content

Commit eedba5b

Browse files
committed
inets: Tighten the defaults for httpd and remove nolimit
This prevents certain types of DOS attacks. You cannot configure nolimit anymore, instead if you need that you should configure a very high value.
1 parent 7d1dfc9 commit eedba5b

6 files changed

Lines changed: 22 additions & 17 deletions

File tree

lib/inets/doc/guides/hardening.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -229,22 +229,22 @@ or
229229

230230
### Request Size Limits
231231

232-
Several size limits default to `nolimit`, which allows arbitrarily large
232+
Before OTP 30 several size limits default to `nolimit`, which allows arbitrarily large
233233
requests that can exhaust memory. Set explicit limits:
234234

235235
```erlang
236-
[{max_uri_size, 8192}, %% 8 KB URI limit
236+
[{max_uri_size, 8192}, %% 8 KB URI limit (default since OTP 30)
237237
{max_header_size, 10240}, %% 10 KB (already the default)
238238
{max_body_size, 10_485_760}, %% 10 MB body limit
239239
{max_content_length, 10_485_760}] %% 10 MB Content-Length check
240240
```
241241

242-
- **[`max_uri_size`](`m:httpd#prop_max_uri`)** - Maximum URI length in bytes. Default: `nolimit`.
242+
- **[`max_uri_size`](`m:httpd#prop_max_uri`)** - Maximum URI length in bytes. Default: `8192` (8 KB).
243243

244244
- **[`max_header_size`](`m:httpd#prop_max_header_size`)** - Maximum total header size. Default: `10240` (10 KB).
245245

246246
- **[`max_body_size`](`m:httpd#prop_max_body_size`)** - Maximum received body size during parsing. Default:
247-
`nolimit`.
247+
`100_000_000` (100 MB).
248248

249249
- **[`max_content_length`](`m:httpd#prop_max_content_length`)** - Rejects requests whose `Content-Length` header
250250
exceeds this value with a 413 response, before reading the body. Default:
@@ -253,7 +253,7 @@ requests that can exhaust memory. Set explicit limits:
253253
- **[`max_client_body_chunk`](`m:httpd#max_client_body_chunk`)** - When handling large PUT or POST bodies via
254254
`mod_esi`, setting this option enforces chunked delivery to the ESI
255255
callback. This prevents the server from buffering the entire request body
256-
in memory, which could be exploited to cause memory exhaustion.
256+
in memory, which could be exploited to cause memory exhaustion. Default: `nolimit`.
257257

258258
> #### Note {: .info }
259259
>

lib/inets/src/http_lib/http_internal.hrl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@
2626

2727
-include_lib("inets/src/inets_app/inets_internal.hrl").
2828

29-
-define(HTTP_MAX_BODY_SIZE, nolimit).
29+
-define(HTTP_MAX_BODY_SIZE, ?HTTP_MAX_CONTENT_LENGTH). %% 100 MB, same as max-content length
3030
-define(HTTP_MAX_HEADER_SIZE, 10240).
31-
-define(HTTP_MAX_URI_SIZE, nolimit).
31+
-define(HTTP_MAX_URI_SIZE, 8192).
3232
-define(HTTP_MAX_VERSION_STRING, 8).
3333
-define(HTTP_MAX_METHOD_STRING, 20).
34-
-define(HTTP_MAX_CONTENT_LENGTH, 100000000).
34+
-define(HTTP_MAX_CONTENT_LENGTH, 100000000). %% 100 MB
3535

3636
-define(DATA_20MB, <<0:16#A000000>>).
3737

lib/inets/src/http_server/httpd.erl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,8 @@ property list.
172172
client before closing the connection. Default is `150`.
173173

174174
- [](){: #prop_max_body_size } **`{max_body_size, integer()}`**
175-
Limits the size of the message body of an HTTP request. Default is no limit.
175+
Limits the size of the message body of an HTTP request. Default is `100000000` (100
176+
MB).
176177

177178
- [](){: #prop_max_clients } **`{max_clients, integer()}`**
178179
Limits the number of simultaneous requests that can be supported. Default is
@@ -187,7 +188,7 @@ property list.
187188
MB).
188189

189190
- [](){: #prop_max_uri } **`{max_uri_size, integer()}`**
190-
Limits the size of the HTTP request URI. Default is no limit.
191+
Limits the size of the HTTP request URI. Default is `8192` (8 KB).
191192

192193
- [](){: #prop_max_keep_alive_req } **`{max_keep_alive_request, integer()}`**
193194
The number of requests that a client can do on one connection. When the server

lib/inets/src/http_server/httpd_conf.erl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,12 @@ validate_config_params([{max_content_length, Value} | Rest])
197197
validate_config_params([{max_content_length, Value} | _]) ->
198198
throw({max_content_length, Value});
199199

200+
validate_config_params([{max_uri_size, Value} | Rest])
201+
when is_integer(Value) andalso (Value > 0) ->
202+
validate_config_params(Rest);
203+
validate_config_params([{max_uri_size, Value} | _]) ->
204+
throw({max_uri_size, Value});
205+
200206
validate_config_params([{server_name, Value} | Rest])
201207
when is_list(Value) ->
202208
validate_config_params(Rest);

lib/inets/src/http_server/httpd_request.erl

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,7 @@ parse_method(_, _, _, Max, _, _) ->
148148
%% will be able to handle it.
149149
{error, {size_error, Max, 413, "Method unreasonably long"}, default_version()}.
150150

151-
parse_uri(_, _, Current, MaxURI, _, _)
152-
when (Current > MaxURI) andalso (MaxURI =/= nolimit) ->
151+
parse_uri(_, _, Current, MaxURI, _, _) when Current > MaxURI ->
153152
%% We do not know the version of the client as it comes after the
154153
%% uri send the lowest version in the response so that the client
155154
%% will be able to handle it.
@@ -180,8 +179,7 @@ parse_version(<<Octet, Rest/binary>>, Version, Current, Max, Options, Result) w
180179
parse_version(_, _, _, Max,_,_) ->
181180
{error, {size_error, Max, 413, "Version string unreasonably long"}, default_version()}.
182181

183-
parse_headers(_, _, _, Current, Max, _, Result)
184-
when Max =/= nolimit andalso Current > Max ->
182+
parse_headers(_, _, _, Current, Max, _, Result) when Current > Max ->
185183
HttpVersion = lists:nth(3, lists:reverse(Result)),
186184
{error, {size_error, Max, 413, "Headers unreasonably long"}, HttpVersion};
187185

lib/inets/src/http_server/httpd_request_handler.erl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,7 @@ handle_body(#state{headers = Headers, body = Body,
536536
_ ->
537537
Length = list_to_integer(Headers#http_request_h.'content-length'),
538538
MaxChunk = max_client_body_chunk(ConfigDB),
539-
case Length =< MaxBodySize orelse MaxBodySize == nolimit of
539+
case Length =< MaxBodySize of
540540
true ->
541541
case httpd_request:body_chunk_first(Body, Length, MaxChunk) of
542542
%% This is the case that the we need more data to complete
@@ -572,7 +572,7 @@ handle_expect(#state{headers = Headers, mod =
572572
MaxBodySize) ->
573573
Length = list_to_integer(Headers#http_request_h.'content-length'),
574574
case expect(Headers, ModData#mod.http_version, ConfigDB) of
575-
continue when (MaxBodySize > Length) orelse (MaxBodySize =:= nolimit) ->
575+
continue when MaxBodySize > Length ->
576576
httpd_response:send_status(ModData, 100, ""),
577577
ok;
578578
continue when MaxBodySize < Length ->
@@ -762,7 +762,7 @@ max_uri_size(ConfigDB) ->
762762
httpd_util:lookup(ConfigDB, max_uri_size, ?HTTP_MAX_URI_SIZE).
763763

764764
max_body_size(ConfigDB) ->
765-
httpd_util:lookup(ConfigDB, max_body_size, nolimit).
765+
httpd_util:lookup(ConfigDB, max_body_size, ?HTTP_MAX_BODY_SIZE).
766766

767767
max_keep_alive_request(ConfigDB) ->
768768
httpd_util:lookup(ConfigDB, max_keep_alive_request, infinity).

0 commit comments

Comments
 (0)