dotnet / dotnet/aspnetcore

Kestrel server returns 500 status code (instead of 400) if client corrupts TLS encrypted data

Open
#46,778 10 comments 0 reactions 0 assignees View on GitHub
area-networking
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 6h
Merged PRs (30d)
290

Description

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Describe the bug

The Kestrel server in ASP.NET Core will return a 500 HTTP status code response if a client garbles the TLS encrypted data for the body of a POST request sent to the service.

A 500 HTTP status code response indicates a service malfunction -- and if the same request is sent again in the future it might succeed. This is **not** the case for the described circumstance. If the client repeatedly garbles the TLS encrypted data for the POST request body, the service will continue to fail in processing the request.

The issue is that the client is sending bad data -- hence, the HTTP status code response should not be 500. Instead, it should be something like 400 (bad request).

Here's the definition of the [400 status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400). Note the warning that the client shouldn't repeat the request without modification, exactly matching the circumstances described here.

image

### Expected Behavior

The Kestrel server in ASP.NET Core should return a HTTP 400 status code response if the client sends garbled TLS encrypted data for the request body for a POST request.

### Steps To Reproduce

A simple repro has been created and published on GitHub.

* Sync public GitHub repo here: https://github.com/gkostal/aspnetcoretlsbug
* Follow directions in [readme.md](https://github.com/gkostal/aspnetcoretlsbug/blob/main/readme.md#reproducing-the-issue) file:
* In your command window, cd into the WebApplication1 directory and run `run.server.cmd`
* In another command window, cd into the ConsoleApp1 directory and run `run.client.with.corrupted.data.cmd`
* Observe HTTP 500 response from service, generated by Kestrel (`Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1ContentLengthMessageBody.ReadAsyncInternal`):
```
******************************************************************************************************************
Server response
******************************************************************************************************************
HTTP/1.1 500 Internal Server Error
Content-Type: text/plain; charset=utf-8
Date: Fri, 17 Feb 2023 18:02:37 GMT
Server: Kestrel
Transfer-Encoding: chunked

cec
System.IO.IOException: The decryption operation failed, see inner exception.
---> System.ComponentModel.Win32Exception (0x80090330): The specified data could not be decrypted.
--- End of inner exception stack trace ---
at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](TIOAdapter adapter, Memory`1 buffer)
at System.IO.Pipelines.StreamPipeReader.g__Core|36_0(StreamPipeReader reader, CancellationTokenSource tokenSource, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1ContentLengthMessageBody.ReadAsyncInternal(CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.ReadAsyncInternal(Memory`1 destination, CancellationToken cancellationToken)
at System.Text.Json.JsonSerializer.ReadFromStreamAsync(Stream utf8Json, ReadBufferState bufferState, CancellationToken cancellationToken)
at System.Text.Json.JsonSerializer.ReadAllAsync[TValue](Stream utf8Json, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)
at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value, Object container)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<g__Bind|0>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware.InvokeInternal(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

HEADERS
=======
Host: 127.0.0.1:7000
Content-Type: application/json; charset=utf-8
Content-Length: 1073

0
```

### Exceptions (if any)

_No response_

### .NET Version

6.0

### Anything else?

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.