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

UTF-8 Characters not accepted in headers when running .NET Core 2.2-preview3 behind IIS #4318

Closed
ionepaul opened this issue Nov 29, 2018 · 18 comments
Labels
✔️ Resolution: By Design Resolved because the behavior in this issue is the intended design.

Comments

@ionepaul
Copy link

I know that the issue regarding this #1144 was fixed in the .NET Core 2.2-preview2, but
UTF-8 Characters seems to be accepted in headers only when running the application directly through the Kerstel server.

I didn't not manage to make it run when the app is using IIS as the proxy for Kerstel.
Do I need to configure something on the IIS side? I tried both with ASP NET CORE MODULE V1 & V2, same result.

But is strange that the error seems to be from the Kerstel server:

Application started. Press Ctrl+C to shut down.
test-preview> dbug: Microsoft.AspNetCore.Server.Kestrel[1]
test-preview>       Connection id "0HLIM0U3DQJD8" started.
test-preview> info: Microsoft.AspNetCore.Server.Kestrel[17]
test-preview>       Connection id "0HLIM0U3DQJD8" bad request data: "Malformed request: invalid headers."
test-preview> Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Malformed request: invalid headers.
test-preview>    at Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException.Throw(RequestRejectionReason reason)
test-preview>    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1Connection.TryParseRequest(ReadResult result, Boolean& endConnection)
test-preview>    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
test-preview>    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequestsAsync[TContext](IHttpApplication`1 application)
test-preview> dbug: Microsoft.AspNetCore.Server.Kestrel[10]
test-preview>       Connection id "0HLIM0U3DQJD8" disconnecting.
test-preview> dbug: Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets[7]
test-preview>       Connection id "0HLIM0U3DQJD8" sending FIN.
test-preview> dbug: Microsoft.AspNetCore.Server.Kestrel[2]
test-preview>       Connection id "0HLIM0U3DQJD8" stopped.

dotnet --info:

.NET Core SDK (reflecting any global.json):
Version: 2.2.100-preview3-009430
Commit: e0a11c9929

Runtime Environment:
OS Name: Windows
OS Version: 10.0.17134
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\2.2.100-preview3-009430\

Host (useful for support):
Version: 2.2.0-preview3-27014-02
Commit: 525082ca3e

.NET Core SDKs installed:
2.1.202 [C:\Program Files\dotnet\sdk]
2.2.100-preview2-009404 [C:\Program Files\dotnet\sdk]
2.2.100-preview3-009430 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
Microsoft.AspNetCore.All 2.2.0-preview2-35157 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.2.0-preview3-35497 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.2.0-preview2-35157 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.2.0-preview3-35497 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.2.0-preview2-26905-02 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.2.0-preview3-27014-02 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]

Fiddler Trace

FiddlerTrace.zip

@ionepaul ionepaul changed the title UTF-8 Characters not accepted when running .NET Core 2.2-preview3 behind IIS UTF-8 Characters not accepted in headers when running .NET Core 2.2-preview3 behind IIS Nov 29, 2018
@Tratcher
Copy link
Member

@JunTaoLuo

@Tratcher
Copy link
Member

@blowdart
Copy link
Contributor

To be fair IIS is correct here. Cookie headers are supposed to be ASCII. Browsers are horribly inconsistent about what they allow and so Kestrel was adjusted to be non-spec compliant, because we were concerned about griefing. If you want a cross platform solution I'd suggest encoding, rather than relying on server behaviour.

@ionepaul
Copy link
Author

@blowdart IIS does accept UTF-8 headers that's not the issue and not the IIS is throwing the error

@ionepaul
Copy link
Author

@Tratcher yes, tried it with In-Process mode and the result was the same

@JunTaoLuo
Copy link
Contributor

@ionepaul From my investigations earlier in aspnet/KestrelHttpServer#1144 (comment), I would expect out-of-process IIS to fail but in-process to work. Can you attach your repro so I can take a look and see what component is causing the failure?

@ionepaul
Copy link
Author

I just tried it with the sample code when you create a new project, nothing fancy, and it adds 'inprocess' by default, though running it through IIS Express is not accepting UTF-8 characters in headers.

I've also tried to add hostingModel="inprocess" to a more complex app which is running over IIS, also specified AspNetCoreModuleV2, but seems that the application is not working with that hostingModel, the app pool is No Managed Code, I don't know if that needs to be changed when using 'inprocess' hosting model.

@crusu006
Copy link

crusu006 commented Dec 3, 2018

hi @JunTaoLuo,
I work with @ionepaul on the same project, and did some additional tests on this issue:

  • for reference, we tested with this header: Cookie: test=Désirée\r\n
  • in-process hosting, IIS Express and IIS: the app doesn't crash but the cookie is not available inside Request.Cookies (tested with regular "Desiree", and it works fine)
  • out-of-process IIS, IIS Express: throws exception
  • using just Kestrel: works fine

We added some breakpoints inside HttpParser.ParseHeaders(...), from Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http, for additional testing.

This allowed us to see the contents of the "buffer" param, and found an interesting difference between using IIS Express and Kestrel:

  • when using IIS Express, the buffer contains [67,111,111,107,105,101,58,32,116,101,115,116,61,68,233,115,105,114,233,101,13,10]
  • when using Kestrel, we're seeing: [67,111,111,107,105,101,58,32,116,101,115,116,61,68,195,169,115,105,114,195,169,101,13,10]
  • the arrays are the same, except for the part corresponding to "é": IIS Express uses "233" to represent the value, while Kestrel uses "[195,169]" (when using "233", UTF8Encoding throws an exception)

Digging deeper, http://www.fileformat.info/info/unicode/char/e9/index.htm, it looks like the correct UTF-8 representation is [195,169], while 233, is UTF-16 (Unicode) or UTF-32 (at least part of it - I think it should be [233,0] or [233,0,0,0])

We couldn't figure out how the buffer was being built, and why it's using different bytes for the same char.

Any tips would be awesome (sorry for the wall of text)

@Tratcher
Copy link
Member

Tratcher commented Dec 3, 2018

We're aware that the reverse proxy scenario (out-of-process) isn't going to work. ANCM uses WinHttp to forward the request to Kestrel and it does not handle Unicode characters correctly.

The scenarios we're expecting to work are direct kestrel and IIS in-process. It's odd that the cookie is missing for the in-process scenario. What do you get if you inspect the raw headers in the app?

@crusu006
Copy link

crusu006 commented Dec 3, 2018

When using In-process, with cookie "test=Désirée":

  • Request.Cookies["test"] is null
  • Request.Headers["Cookie"] has the actual value: "test=Désirée"
  • using "test=Desiree", works as expected

@Tratcher
Copy link
Member

Tratcher commented Dec 3, 2018

Hmm, the server shouldn't impact the Cookies parser. @JunTaoLuo can you repro this?

@JunTaoLuo
Copy link
Contributor

I'll take a look.

@JunTaoLuo
Copy link
Contributor

Let me clarify the behaviour. We parse UTF-8 value for header values which is why Request.Headers["Cookie"] will have the parsed value test=Désirée. However, the cookie parser is much stricter in terms of accepted characters: https://github.com/aspnet/AspNetCore/blob/master/src/Http/Headers/src/CookieHeaderValue.cs#L220-L229 which is why Request.Cookies["test"] is not populated with that value. The expectation here is that you'll need to handle UTF-8 values yourself here.

What I'm concerned about is the original logs that contains Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Malformed request: invalid headers. and the assertion that this shows up when Kestrel is behind IIS in-proc. That is unexpected though I haven't had the chance to try repro it yet.

@crusu006
Copy link

crusu006 commented Dec 4, 2018

@JunTaoLuo just to clarify, the "Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Malformed request: invalid headers." exception is not logged / thrown when using IIS in-proc (only when using IIS out-of-proc).

This was a confusion on our part (we thought we set the app to use "in process" but didn't).
Sorry about that.

We'll try to use IIS "in-proc" (we don't use / need that cookie value, and just want the request to get to our endpoint).
It would be nice to have a consistent behavior, but this is probably just an edge case.

@JunTaoLuo
Copy link
Contributor

I see. If that's the case I'd say everything is working as expected.

@JunTaoLuo JunTaoLuo added the ✔️ Resolution: By Design Resolved because the behavior in this issue is the intended design. label Dec 4, 2018
@ytqsl
Copy link

ytqsl commented Apr 30, 2019

@JunTaoLuo, @Tratcher we see this bad request behaviour with Kestrel 2.1.9, 2.1.10 and 2.2.4.

Repro:

  • asp.net core app hosted in a container
  • send GET with header test=Tk'emlúps te Secwépemc

Result: 400 bad request "Malformed request: invalid headers."

@Tratcher
Copy link
Member

Comments on closed issues are not tracked, please open a new issue with the details for your scenario.

Please also include a wireshark trace as that's the easiest way to confirm the encoding. You're not using IIS as a proxy to kestrel are you? That configuration still has encoding issues.

@ytqsl
Copy link

ytqsl commented Apr 30, 2019

#9874

@ghost ghost locked as resolved and limited conversation to collaborators Dec 3, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
✔️ Resolution: By Design Resolved because the behavior in this issue is the intended design.
Projects
None yet
Development

No branches or pull requests

6 participants