Skip to content

Unable to use HttpClient configured with UseDefaultCredentials true when the process is running under a restricted token with restricted SIDs #102692

Open
@davidterins

Description

Description

I want to run a process with a restricted set of SIDs and in that process/application use HttpClient configured with UseDefaultCredentials to do request to a backend web api with the following flow:

From process 1

  1. Call method CreateRestrictedToken (provide a list a restricted sids as parameter)
  2. Call method CreateProcessAsUser providing the restricted token for the new process

From Process 2 that was launched from process 1's step 2

  1. Use the HttpClient to call some backend web api using the Negotiate authentication scheme using the credentials of the process by configuring HttpClient with UseDefaultCredentials: true

Reproduction Steps

Create an application representing each process described and then...
From process 1

  1. Call method CreateRestrictedToken
CreateRestrictedToken(
                    Token, // <-- current token
                    0,
                    0, IntPtr.Zero,
                    0, IntPtr.Zero,
                    (uint)restrictedSidStrings.Count, restrictedSidsPtr,  // <-- Provide some valid SID data to these two parameters
                    out SafeTokenHandle restrictedToken))
  1. Call method CreateProcessAsUser providing the restricted token for the new process providing the restricted token from step 1
CreateProcessAsUser(
                    restrictedToken,
                    appToRun,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    false,
                    0,
                    IntPtr.Zero,
                    startupFolder,
                    ref startupInfo,
                    out PROCESS_INFORMATION processInfo))

From Process 2 that was launched from process 1's step 2

  1. Use the HttpClient configured with UseDefaultCredentials: true
    var handler = new HttpClientHandler();
    var httpClient = new HttpClient(handler);
    var result = await httpClient.GetAsync(url);

Expected behavior

The api request is successfully sent from the client.

Actual behavior

When calling httpClient.GetAsync(url) the following exception + stacktrace is produced

Attempting to do http request to endpoint: https://localhost:7254/weatherforecast
System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
---> System.ComponentModel.Win32Exception (0x8009030E): No credentials are available in the security package
at System.Net.SSPIWrapper.AcquireCredentialsHandle(ISSPIInterface secModule, String package, CredentialUse intent, SCH_CREDENTIALS* scc)
at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(CredentialUse credUsage, SCH_CREDENTIALS* secureCredential)
at System.Net.Security.SslStreamPal.AcquireCredentialsHandleSchCredentials(SslAuthenticationOptions authOptions)
at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(SslAuthenticationOptions sslAuthenticationOptions, Boolean newCredentialsRequested)
--- End of inner exception stack trace ---
at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(SslAuthenticationOptions sslAuthenticationOptions, Boolean newCredentialsRequested)
at System.Net.Security.SslStream.AcquireCredentialsHandle(SslAuthenticationOptions sslAuthenticationOptions, Boolean newCredentialsRequested)
at System.Net.Security.SslStream.AcquireClientCredentials(Byte[]& thumbPrint, Boolean newCredentialsRequested)
at System.Net.Security.SslStream.GenerateToken(ReadOnlySpan1 inputBuffer, Byte[]& output) at System.Net.Security.SslStream.NextMessage(ReadOnlySpan1 incomingBuffer, ProtocolToken& token)
at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken)
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(QueueItem queueItem)
at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.AuthenticationHelper.SendWithAuthAsync(HttpRequestMessage request, Uri authUri, Boolean async, ICredentials credentials, Boolean preAuthenticate, Boolean isProxyAuth, Boolean doRequestAuth, HttpConnectionPool pool, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)

Regression?

Unkown

Known Workarounds

If enough security for one's use case to just rely on disdabled sids (deny only attribute), then it is possible to not specify any restricted SIDs and just pass disabled sids to the parameters of CreateRestrictedToken

CreateRestrictedToken(
                    Token, // <-- current token
                    0,
                    (uint)disabledSids.Count, disabledSidsPtr,  // <-- Provide some valid SID data to these two parameters
                    0, IntPtr.Zero,
                    0, IntPtr.Zero, // <-- Do not pass any restricted SIDs
                    out SafeTokenHandle restrictedToken))

Configuration

Which version of .NET is the code running on? - net8 (net8-windows)
What OS and version, and what distro if applicable? - Windows 11 - 10.0.22621 Build 22621
What is the architecture (x64, x86, ARM, ARM64)? - x64
Do you know whether it is specific to that configuration? - No
If you're using Blazor, which web browser(s) do you see this issue in? - No

Other information

No response

Activity

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

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions