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

UNTRUSTED_SPN_SOURCE should not be set #67

Closed
grawity opened this issue Mar 15, 2022 · 6 comments · Fixed by #68
Closed

UNTRUSTED_SPN_SOURCE should not be set #67

grawity opened this issue Mar 15, 2022 · 6 comments · Fixed by #68

Comments

@grawity
Copy link

grawity commented Mar 15, 2022

(Continuing from jborean93/smbprotocol#169)

Windows servers have a security policy Microsoft network server: Server SPN target name validation level, which (if enabled) will check the SPN sent in MSV_AV_TARGET_NAME and will reject authentication if it thinks you're authenticating to an unrecognized SPN. (I assume this is meant to prevent NTLM relay attacks, though it also adds checks to Kerberos SPNs as well.)

Latest gss-ntlmssp Git now sends the SPN in the correct format, but still gets rejected by Windows servers with this policy enabled. The biggest difference I can see between gss-ntlmssp and working clients (Win10, Samba, pyspnego) is that gss-ntlmssp now sets the UNTRUSTED_SPN_SOURCE flag in MSV_AV_FLAGS, which none of the other clients do, and if I understand the NTLM spec right this flag tells the server to pretend the SPN field was empty (which the newly added checks then reject as unrecognized).

@simo5
Copy link
Collaborator

simo5 commented Mar 15, 2022

My goal is to find out what trusted/untrusted really means, and then stop setting untrusted where possible, potentially in all cases if it turns out we should always trust the caller.

@jborean93
Copy link

I did some digging and had confirmation that on Windows this flag is controlled by ISC_REQ_UNVERIFIED_TARGET_NAME. When calling SSPI with that ISC set I can also confirm that it sets the untrusted SPN source flag in NTLM.

I did some testing with the various permutations and on SMB this is what I found

Policy Valid SPN Invalid SPN No SPN Unverified Valid SPN Unverified Invalid SPN Unverified No SPN
Off Y Y Y Y Y Y
Accept Y N Y N N Y
Required Y N N N N N

It seems like having this AV flag set essentially has the server treat any provided SPN from the client as invalid when the policy is set to Accept or Required. Interestingly enough if the policy is just Accept and no MSV_AV_TARGET_NAME field was supplied then the server will continue to act like no SPN is specified and thus doesn't fail validation.

A guess why this AV flag was added rather than just omitting the MSV_AV_TARGET_NAME field is due to the behaviour above and wanting to preserve backwards compatibility with non-MS hosts or maybe even older MS hosts. It could also be that InitializeSecurtyContext is unable to provide an NTLM token without the MSV_AV_TARGET_NAME field as a NULL value for pTargetName just has MSV_AV_TARGET_NAME set to a null value rather than being omitted entirely. I was only able to verify the No SPN scenarios with my custom client when I could omit the AV field.

Going forward if we wanted to match the behaviour in SSPI then it sounds like we don't want this AV flag set by default and to add a new OID that can be used with gss_set_sec_context_option to set this flag before the authentication starts. An alternative option is to always set as untrusted and have the client opt into marking it as trusted but that is the opposite of what most clients do today (doesn't necessarily mean it's a bad idea).

@simo5
Copy link
Collaborator

simo5 commented Mar 15, 2022

Sounds to me that SSPI just trusts the client to tell it, and by default trusts the value. The client application seem to have to go out of its way to mark a SPN as untrusted.
If this is correct I do not see why we need to make it any more difficult.
I will just create a PR to stop doing that and add a TODO to potentially provide, one day, a way to set the untrusted flag if we find any use for it (it is not clear at all to me in what situation a windows client application would want to set it), do you have any example of client using this flag ?

@jborean93
Copy link

I will just create a PR to stop doing that and add a TODO to potentially provide, one day, a way to set the untrusted flag if we find any use for it (it is not clear at all to me in what situation a windows client application would want to set it), do you have any example of client using this flag ?

I do not but when asking Steve the same question he stated

SSPI doesn't ever infer it. The caller either set it or it didn't. There are internal callers in Windows that do set it based on various conditions.

I didn't really go further into what those conditions may be or what components may do it. Ultimately I think gssntlmssp as you said should not have it set and provide a mechanism (some time in the future) where a caller could mark it as untrusted. I don't see any way that this library can determine the trustworthiness of the value.

@simo5
Copy link
Collaborator

simo5 commented Mar 15, 2022

@jborean93 can you check if #68 makes things work again?

@jborean93
Copy link

Can confirm it works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants