Skip to content

Loading PFX without admin causes CryptographicException #110217

Open
@timmac-qmc

Description

Description

After upgrading to .Net 9.0 on a API project the following codes throws the error "System.Security.Cryptography.CryptographicException: 'Access denied.'" when not run as Admin. This works fine without admin on .net 8.0.

builder.WebHost.UseKestrel(options =>
{
    options.ListenAnyIP(443, builder =>
    {
            builder.UseHttps("D:\\private_cert.pfx", "password");
    });
});

Reproduction Steps

  1. Create a new .Net 9.0 API project.
  2. In Program.cs load a certifcate using the code provided

Expected behavior

Project runs without issue

Actual behavior

Exception thrown: System.Security.Cryptography.CryptographicException: 'Access denied.'

 	System.Security.Cryptography.dll!System.Security.Cryptography.X509Certificates.X509CertificateLoader.ImportPfx(System.ReadOnlySpan<byte> data, System.ReadOnlySpan<char> password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags)	Unknown
 	System.Security.Cryptography.dll!System.Security.Cryptography.X509Certificates.X509CertificateLoader.LoadPkcs12NoLimits(System.ReadOnlyMemory<byte> data, System.ReadOnlySpan<char> password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags, ref System.Security.Cryptography.X509Certificates.X509CertificateLoader.Pkcs12Return earlyReturn)	Unknown
 	System.Security.Cryptography.dll!System.Security.Cryptography.X509Certificates.X509CertificateLoader.LoadPkcs12(System.ReadOnlyMemory<byte> data, System.ReadOnlySpan<char> password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags, System.Security.Cryptography.X509Certificates.Pkcs12LoaderLimits loaderLimits)	Unknown
 	System.Security.Cryptography.dll!System.Security.Cryptography.X509Certificates.X509CertificateLoader.LoadFromFile<System.Security.Cryptography.X509Certificates.X509CertificateLoader.Pkcs12Return>(string path, System.ReadOnlySpan<char> password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags, System.Security.Cryptography.X509Certificates.Pkcs12LoaderLimits loaderLimits, System.Security.Cryptography.X509Certificates.X509CertificateLoader.LoadFromFileFunc<System.Security.Cryptography.X509Certificates.X509CertificateLoader.Pkcs12Return> loader)	Unknown
 	System.Security.Cryptography.dll!System.Security.Cryptography.X509Certificates.X509CertificateLoader.LoadPkcs12PalFromFile(string path, System.ReadOnlySpan<char> password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags, System.Security.Cryptography.X509Certificates.Pkcs12LoaderLimits loaderLimits)	Unknown
 	System.Security.Cryptography.dll!System.Security.Cryptography.X509Certificates.CertificatePal.FromBlobOrFile(System.ReadOnlySpan<byte> rawData, string fileName, Microsoft.Win32.SafeHandles.SafePasswordHandle password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags)	Unknown
 	System.Security.Cryptography.dll!System.Security.Cryptography.X509Certificates.X509Certificate.X509Certificate(string fileName, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags)	Unknown
 	Microsoft.AspNetCore.Server.Kestrel.Core.dll!Microsoft.AspNetCore.Hosting.ListenOptionsHttpsExtensions.UseHttps(Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions listenOptions, string fileName, string password)	Unknown
>	Program.<Main>$.AnonymousMethod__0_18(Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions builder) Line 52	C#

Regression?

Yes, works on .Net 8.0

Known Workarounds

No response

Configuration

.Net 9.0
Windows 11 26100.2314 x64

Other information

No response

Activity

dotnet-policy-service

dotnet-policy-service commented on Nov 27, 2024

@dotnet-policy-service
Contributor

Tagging subscribers to this area: @dotnet/area-system-security, @bartonjs, @vcsjones
See info in area-owners.md if you want to be subscribed.

rabotond

rabotond commented on Nov 28, 2024

@rabotond

I am facing the same. Works on .net8 but exception on .net9. Running it with admin mode solves it.

barrie-poultryplan

barrie-poultryplan commented on Dec 3, 2024

@barrie-poultryplan

Same issue here.

jimitndiaye

jimitndiaye commented on Dec 4, 2024

@jimitndiaye

Same issue here: dotnet/aspnetcore#59300

added this to the 9.0.x milestone on Dec 5, 2024
jeffhandley

jeffhandley commented on Dec 5, 2024

@jeffhandley
Member

@krwq Please investigate this. The repro in dotnet/aspnetcore#59300 looks like a good way to get started.

DierkDroth

DierkDroth commented on Dec 8, 2024

@DierkDroth

I have a different scenario which is running into trouble with .NET9 and which is failing for potentially the same reason.

I understand that

X509Certificate2 certificate = new X509Certificate2(byte[] data, string password)

... now is obsolete with .NET9, which is why I replaced it by

X509Certificate2 certificate = X509CertificateLoader.LoadPkcs12(byte[] data, string password)

The certificate itself is used by the Kestrel server:

builder.WebHost.ConfigureKestrel(kestrel =>
{
	kestrel.ListenAnyIP(port, portOptions =>
	{
		portOptions.UseHttps(certificate);
	});
});

This works fine if the Kestrel server is running on the target (Linux) server. However, for development and debugging purposes I'm running the Kestrel server on my local Windows 11 machine as well where a SSH script reroutes the remote server port to my local machine.

Code above only works on my local machine if I'm running Visual Studio as administrator. The local Kestrel server can't be reached if running as non-admin.

Can you please confirm/deny that the source of trouble is the same as reports above?
Thanks in advance

krwq

krwq commented on Dec 9, 2024

@krwq
Member

@DierkDroth it's likely related to the same piece of code but IMO failing for different reason - it will be beneficial if you could share steps how to create cert similar to yours.

The simple repro for this issue is just this (ASP.NET is not needed):
new X509Certificate2("cert.pfx", "1234") (creating cert as described in dotnet/aspnetcore#59300) and it can be worked around simply with X509CertificateLoader.LoadPkcs12(File.ReadAllBytes("cert.pfx"), "1234"). I noticed that this is another way to repro:

Pkcs12LoaderLimits limits = new Pkcs12LoaderLimits()
{
    PreserveStorageProvider = true // true => seeing access denied; false => works
};

X509CertificateLoader.LoadPkcs12(File.ReadAllBytes("cert.pfx"), "1234", loaderLimits: limits);

which seems inconsistent with what you're describing. I'd be still interested in seeing steps how to create a cert you're describing. We also noticed that for some reason this didn't repro for everyone.

This most likely regressed with: #107005 but it was also fixing another issue so we need to figure out solution which makes this work with both scenarios and most likely your test case as well (and therefore my request to share steps to create your cert). With that PR reverted locally I wasn't able to repro this problem anymore but I've additionally seen some more tests failing locally with Access Denied (but it was less tests failing with this reverted) and that doesn't repro on CI for some reason. Given our main expert in this area @bartonjs is out of office and holidays season approaching I'm not sure if we will be able to make any fix this year but collecting more information and test cases will be very valuable to fix this correctly in the next iteration.

DierkDroth

DierkDroth commented on Dec 9, 2024

@DierkDroth

@krwq additional details:

  • I don't need to apply Pkcs12LoaderLimits to reproduce the issue
  • I get the exception as reported by the OP when not replacing the obsolete code but going with the X509Certificate2.ctor
  • I don't get any exception at all when replacing the obsolete code as per my post. Not even Kestrel throws any exception, it's just not working.
    Please let me know if you needed anything else.

I can't comment on how this regression was introduced to the .NET code, since I'm not part of the .NET9 dev team

6 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions

    Loading PFX without admin causes CryptographicException · Issue #110217 · dotnet/runtime