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

Support SSLKEYLOGFILE in SslStream #37915

Closed
bgrainger opened this issue Jun 15, 2020 · 38 comments · Fixed by #90429 or #100665
Closed

Support SSLKEYLOGFILE in SslStream #37915

bgrainger opened this issue Jun 15, 2020 · 38 comments · Fixed by #90429 or #100665
Assignees
Labels
area-System.Net.Security enhancement Product code improvement that does NOT require public API changes/additions in-pr There is an active PR which will close this issue when it is merged
Milestone

Comments

@bgrainger
Copy link
Contributor

SSLKEYLOGFILE is a feature provided by Chrome and Firefox that logs the pre-master secret to a file (specified by the SSLKEYLOGFILE environment variable) during TLS negotiation. The format of the file is documented here: https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format.

This allows encrypted data in a packet capture to be decrypted by Wireshark (without having to know the server's private key): https://wiki.wireshark.org/TLS#Using_the_.28Pre.29-Master-Secret.

As HTTPS and HTTP/2 become more popular, it will be increasingly more useful to be able to decrypt packet captures for network analysis; as per http://gary-nebbett.blogspot.com/2018/06/tracing-https-traffic-on-microsoft.html. (This use case also seems to be implied by #35369.)

The ability to use a network trace analysis tool is especially useful when HTTP/2 is in use because the binary encoding of HTTP/2 can easily be decoded and nicely presented by such tools.

It would be great if TLS negotiation performed by SslStream could also log these secrets so that tools like Wireshark could be used to decrypt packet captures involving .NET clients. (Note that I'm not necessarily asking for the SSLKEYLOGFILE environment variable to be specifically supported, but just some opt-in way of dumping the same data; SSLKEYLOGFILE seemed like the most concise way to describe the feature.)

Besides HTTPS, another use case would be TLS negotiation in a different protocol; for example, the MySQL protocol upgrades from plain text to TLS, and being able to decrypt the packets in Wireshark would make diagnosing issues easier: mysql-net/MySqlConnector#780 (comment)

One potential problem is that Schannel doesn't support exporting this information, which could make it difficult to implement this feature on all platforms: https://social.technet.microsoft.com/Forums/en-US/4041d78a-21bb-44fd-9a96-6579ea8129d1/obtaining-sslkeylogfilelike-data-from-edge-et-al-schannel-clients?forum=messageanalyzer

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added area-System.Net.Security untriaged New issue has not been triaged by the area owner labels Jun 15, 2020
@ghost
Copy link

ghost commented Jun 15, 2020

Tagging subscribers to this area: @dotnet/ncl
Notify danmosemsft if you want to be subscribed.

@karelz karelz added this to the Future milestone Jun 18, 2020
@karelz karelz added enhancement Product code improvement that does NOT require public API changes/additions and removed untriaged New issue has not been triaged by the area owner labels Jun 18, 2020
@karelz
Copy link
Member

karelz commented Jun 18, 2020

Triage: Useful for diagnostics to be able to view the traffic unencrypted.

@booyaa
Copy link

booyaa commented Jan 18, 2021

Just as an aside, I foolishly assumed that given libcurl is a dependency when bootstrapping .net core in Linux, that you could export SSLKEYLOGFILE as an environment variable (see docs). Sadly, I can confirm this does not generate a key log file. So this feature would be very helpful.

Update: apparently SSLKEYLOGFILE started working overnight. Using Azure App Service, custom Docker image based off mcr.microsoft.com/dotnet/core/aspnet:3.1.8-alpine3.12 stopped working again... after a restart

@wfurt
Copy link
Member

wfurt commented Jan 28, 2021

While SSLKEYLOGFILE may be problematic because of forward secrecy and platform dependency, I was experimenting with alternative approach. https://github.com/wfurt/PcapStream gives you option to create decrypted captures with HttpClient, Kestrel and perhaps other scenarios. It is in early stage but any feedback would be appreciated.

The MSQL use case is still problematic AFAIK as the client frames encrypted bits to TDS. I don't know Wireshark can deal with that. I did not have luck.

@wpbrown
Copy link

wpbrown commented Feb 24, 2021

Native support in the runtime would be great. In the meantime, I've created a solution for Linux with OpenSSL 1.1.1+ (i.e. Ubuntu 18.04 up on amd64 or 20.04 all archs) that works by wrapping SSL_new and dlsym. A basic LD_PRELOAD substitution doesn't work because the .NET runtime provides an open handle to dlsym, so dlsym needs to be wrapped as well.

@wfurt wfurt self-assigned this Nov 16, 2022
@upsampled
Copy link

I understand this is a sensitive topic, but as TLSs is a common interface between organizations this feature is used to resolve disputes. IE: "See we are sending X but your are responding with Y and we expect Z. You can reproduce this collection procedure at your end as well to verify."

The idea that both parties can collect a common pcap, decrypt with their own SSLKEYLOGFILE, and reach consensus is commonplace.

@raffaeler
Copy link

Is there any ongoing work on this?

@wfurt
Copy link
Member

wfurt commented Mar 28, 2023

not really. We agreed to support it in DEBUG build in way similar to #83001. But the urgency is lower IMHO as there are other alternatives.

@wfurt wfurt added the help wanted [up-for-grabs] Good issue for external contributors label Mar 28, 2023
@raffaeler
Copy link

@wfurt I am very concerned about letting this option available only for debug builds. There is a very high risk of seeing debug code being deployed in production which is problematic for other reasons.
We already have secrets in the environment variables and this new variable has the same risk level.

Also, the provided workarounds are briliant but do not provide a solution for all the cases and require rebuilding which is something that can be hard to ask in large organizations.

@wfurt
Copy link
Member

wfurt commented Mar 28, 2023

When I said DEBUG I mean debug build for runtime. That is not published to usual feeds so there should be no confusion IMHO. Of course, somebody can work hard and mess it up anyway but it seems like this is what browsers do so we would be on par. (for Linux)

The rebuild is somewhat intentional. To limit risk you mentioned we down't want to make it too simple. You can always build it always and have App specific overrides to enable it - if that meets policy of give organization.

@raffaeler
Copy link

@wfurt just to be sure:

  • do you mean a DEBUG build of the runtime that is on a different download repository?
  • is this enabled on the sdk by default (which for debug purposes by design)?
  • Are those debug builds available through the VS installer as well? (I ask this because the updates continuously uninstall/reinstall new releases from the main feed. This is done also from WU for security patches)
  • Is this limited to QUIC (given the title of the PR) or for anything TLS related?

To limit risk you mentioned we down't want to make it too simple

I understand the concerns, but if I think to the container workloads, should the environment variables be defeated, security is already gone.

@wfurt
Copy link
Member

wfurt commented Mar 28, 2023

The PR is just for Quic, SslStream change can mimic that for TLS in future. And there are no debug binary bits available for download AFAIK. (but you can grab them for example from PR runs)

So the goal is to make it possible for somebody who is determined and knows what to do. Ease of access and wide availability is not priority at the moment.

@raffaeler
Copy link

Got it, thank you

@hannadeng
Copy link

Is there any update on this?

This feature is also very meaningful for gRPC on .NET. In most enterprise scenario, the gRPC traffic should be encrypted by TLS. A method to decrypt the TLS traffic is necessary for analyzing the streaming data. Whilst according to WireShark Wiki , currently C#/dotnet does not support TLS session secret key from either client or server side, while other languages like Java/Golang do support it.

It's better for .NET Core to support an easier way of decrypting HTTPS traffic, like exporting the TLS session secret key or any other method.

@raffaeler
Copy link

@hannadeng I don't think that this would be helpful in your case (gRPC).
Unfortunately this debug feature is QUIC only and only works if you get the runtime from a different feed.
For me it is a no-go.

@hannadeng
Copy link

#83001.

Thanks @raffaeler . Maybe my question is not quite clear. Let me explain more. I understand #83001. is only for QUIC and will not be applicable in my case (gRPC - HTTP2 protocol). Whilst I thought the original issue requested by bgrainger is a kind of general request for supporting decrypting TLS, including HTTP/2 protocol. Appreciate @JamesNK could help input more insights.

@raffaeler
Copy link

@hannadeng I am totally with you. I would love to have the opportunity to monitor the SSL convesation with the required level of precautions needed to avoid misues.
Anyway in this thread I was said that they won't implement the decryption outside QUIC protocol.
You, me and many others are stuck, that's it.

@hannadeng
Copy link

@hannadeng I am totally with you. I would love to have the opportunity to monitor the SSL convesation with the required level of precautions needed to avoid misues. Anyway in this thread I was said that they won't implement the decryption outside QUIC protocol. You, me and many others are stuck, that's it.

Got it. Thanks again!

@wfurt
Copy link
Member

wfurt commented Jun 5, 2023

When #83001 is done I plan to do it for SslStream as well - Debug build on Linux only. But I don't have much time for either one at the moment.

If there a reason why https://github.com/wfurt/PcapStream does not work for you @hannadeng ? It should give you ability to decode and debug HTTP/2 and gRPC.

@karelz karelz modified the milestones: Future, 8.0.0 Aug 15, 2023
@dotnet dotnet locked as resolved and limited conversation to collaborators Sep 14, 2023
@ManickaP ManickaP modified the milestones: 8.0.0, 9.0.0 Nov 22, 2023
@ManickaP
Copy link
Member

Tentatively re-opening to discuss the requirement for DEBUG build (as this no longer applies to browsers - Firefox, Chromiun, nor CLI tools - cUrl)
And to make sure we implement this for Windows as well, see #94843

@ManickaP ManickaP reopened this Nov 22, 2023
@dotnet dotnet unlocked this conversation Nov 22, 2023
@raffaeler
Copy link

I would like to know if there is any chance to discuss supporting SSLKEYLOGFILE in release builds of the CLR, using an environment variable to enable easier diagnostics.
To support this request:

  • Even on dev machines, I doubt that the majority of devs would install a debug build. In my experience they would rather switch to plain http to make the test and hopefully restore back https
  • Env variables are already used to hide secrets, this is no different
  • When using dotnet/aspire, we can request a future feature triggering a warning whenever the env variable is turned on potentially exposing the distributed app to SSLKEYLOGFILE

If this is out of discussion for .NET 9, please make a statement so that we avoid 'noise' in this comments.
Thanks!

@ManickaP
Copy link
Member

I would like to know if there is any chance to discuss supporting SSLKEYLOGFILE in release builds of the CLR, using an environment variable to enable easier diagnostics.

That's the intent here.

If this is out of discussion for .NET 9, please make a statement so that we avoid 'noise' in this comments.

No, I'd like to solve this in .NET 9.

And thank you for describing your scenario, that will help make my case.

@nathan130200
Copy link

Any updates?

@ManickaP
Copy link
Member

Thanks for the remainder, I just kicked off an internal discussion about this.

@rzikm rzikm removed the help wanted [up-for-grabs] Good issue for external contributors label Mar 26, 2024
@rzikm rzikm self-assigned this Apr 5, 2024
@dotnet-policy-service dotnet-policy-service bot added the in-pr There is an active PR which will close this issue when it is merged label Apr 5, 2024
@upsampled
Copy link

Can you elaborate on why the SslStream cannot emit the Traffic or Handshake secret?

OS SslStream QuicConnection
Windows Not possible Yes

@wfurt
Copy link
Member

wfurt commented Apr 10, 2024

There is no API on Windows to extract the secrets @upsampled . SslStream does not implement TLS - it just wraps underlying OS functions and therefore it is dependent on the provided capabilities.

@wfurt
Copy link
Member

wfurt commented Apr 10, 2024

If Windows client is your only one option thee are other ways how to peek inside - something like Fiddler or PcapStream should still work.

@rzikm
Copy link
Member

rzikm commented Apr 11, 2024

Can you elaborate on why the SslStream cannot emit the Traffic or Handshake secret?

The underlying OS library (Schannel) does not give out secrets to the application. In fact, the secrets are not kept in the app process memory at all, but instead reside in lsass.exe process and there is IPC between the two under the hood. https://b.poc.fun/decrypting-schannel-tls-part-1/ may be an interesting read (although the method described may not be practical).

Schannel added support for exporting TLS 1.3 secrets specifically in order to support implementing QUIC (QUIC requires access to encryption secrets because it interleaves TLS + other protocol data + application data and applies custom encryption using the secrets derived by TLS layer). That support is intentionally limited to very specific use case where Schannel gives out unencrypted TLS messages and encryption secrets separately. IIRC, this mode does not work for TLS 1.2.

We could theoretically use that mode and apply TLS framing+encryption in .NET, but that has few problems:

  • Only TLS 1.3 would be supported, version detection may be problematic because the leave the version detection/negotiation on Schannel.
  • For security reasons, that code could be only used when SSLKEYLOGFILE functionality was desired in order to avoid accidental vulnerabilities in production code
  • Connected to the above: there would be potentially observable difference between SSLKEYLOGFILE and normal behavior, thus making the feature potentially useless

All-in-all, the implementation cost far outweighs possible benefits and it might be better to use other tools like wfurt mentioned.

@upsampled
Copy link

upsampled commented Apr 11, 2024

Schannel added support for exporting TLS 1.3 secrets specifically in order to support implementing QUIC

Are those same exporting mechanisms available for TLSv13 over TCP? I am assuming this is to support 0-RTT or the PSK-binder mechanisms in TLSv13 and both also are possible over TCP.

I guess I am asking if the below is true

OS SslStream (<=TLSv12) SslStream (TLSv13) QuicConnection (TLSv13)
Windows Not possible Possible Yes

@rzikm
Copy link
Member

rzikm commented Apr 11, 2024

Are those same exporting mechanisms available for TLSv13 over TCP?

No, let me clarify. The secrets are exported only if the TLS version is 1.3 and it is operating in "recordless mode" (where it strips outer encryption and provides unencrypted TLS messages).

SChannel does not know about TCP, it is simply exchanging data via buffers and sending data is up to other code.

Putting the stripped encryption back in .NET code is the complex and problematic part which is the main reason we won't invest into that, for reasons listed in my previous comment.

@nathan130200
Copy link

Can you elaborate on why the SslStream cannot emit the Traffic or Handshake secret?

OS SslStream QuicConnection
Windows Not possible Yes

In windows maybe you can consider using some OpenSSL wrapper instead of SslStream. Like OpenSSL Net does

@wfurt
Copy link
Member

wfurt commented Apr 11, 2024

Can you elaborate on why the SslStream cannot emit the Traffic or Handshake secret?
OS SslStream QuicConnection
Windows Not possible Yes

In windows maybe you can consider using some OpenSSL wrapper instead of SslStream. Like OpenSSL Net does

we could. But that has massive implications for certifications, performance, security and integration with OS functions like Cert store. As I mentioned above, there are other ways how to solve debugging TLS traffic @nathan130200

@nathan130200
Copy link

It makes sense, and it ends up becoming unfeasible to do this at the moment, especially when we talk about performance.

@jimm98y
Copy link

jimm98y commented Apr 11, 2024

If Windows client is your only one option there are other ways how to peek inside - something like Fiddler or PcapStream should still work.

PcapStream looks nice, but it is only usable if you are the app developer (not always the case, you might want to debug a third-party app/component).

Fiddler is only usable if the app supports proxies and does not implement SSL pinning or similar mechanisms. It does not help with non-HTTP connections as far as I know.

Imagine you are an app developer using a third-party component that implements some protocol (e.g. BACnet SC, SNMPv3, SRTP...) and you'd want to debug an issue in the communication in between your app using that component and an actual device. For this example let's consider a scenario when the third-party component does not expose the underlying streams to the developer directly, meaning we have to go through some API and we cannot use PcapStream.
If the component is using OpenSSL (with keylog for debugging), then it's quite easy: you configure the environment which you fully control to dump the keys, point Wireshark to that file and you'll see the decrypted traffic -> happy debugging.
However, if that third-party library is not using OpenSSL, then you're out of luck. Is the issue you are trying to debug in your code? Is it in the third-party component? Is it on the device? What's happening on the wire?

I think there should be some easy opt-in mechanism like the one in OpenSSL to allow developers to peek inside the TLS encrypted stream and see the decrypted traffic, provided they fully control at least one side of the connection. But I understand from the previous comments that maybe it's not an issue of .NET, but Windows API in general. Is my understanding correct?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.Net.Security enhancement Product code improvement that does NOT require public API changes/additions in-pr There is an active PR which will close this issue when it is merged
Projects
None yet
16 participants