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

[NTLM] does not work when there is a valid credential in the Credential Manager #1622

Closed
toughengineer opened this Issue Jun 28, 2017 · 6 comments

Comments

Projects
None yet
4 participants
@toughengineer
Contributor

toughengineer commented Jun 28, 2017

I did this

On a Windows machine with logon user credentials that are accepted on the server NTLM authentication works ok:

curl -v -u : --ntlm localhost/test-auth
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
* Server auth using NTLM with user ''
> GET /test-auth HTTP/1.1
> Host: localhost
> Authorization: NTLM TlRMTVNTUAABAAAAB7IIogIAAgAxAAAACQAJACgAAAAGAbEdAAAAD05PVk
lLT1YtUEtM
> User-Agent: curl/7.54.1-DEV
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< Content-Type: text/html; charset=us-ascii
< Server: Microsoft-HTTPAPI/2.0
< WWW-Authenticate: NTLM TlRMTVNTUAACAAAABAAEADgAAAAFwomiylQDEB1UzWYwkNoBAAAAAHI
AcgA8AAAABgGxHQAAAA9LAEwAAgAEAEsATAABABIATgBPAFYASQBLAE8AVgAtAFAABAAMAGEAdgBwAC4
AcgB1AAMAIABuAG8AdgBpAGsAbwB2AC0AcAAuAGEAdgBwAC4AcgB1AAUADABhAHYAcAAuAHIAdQAHAAg
AxdbtfBvw0gEAAAAA
< Date: Wed, 28 Jun 2017 14:33:19 GMT
< Content-Length: 341
<
* Ignoring the response-body
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'http://localhost/test-auth'
* Found bundle for host localhost: 0x742168 [can pipeline]
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (127.0.0.1) port 80 (#0)
* Server auth using NTLM with user ''
> GET /test-auth HTTP/1.1
> Host: localhost
> Authorization: NTLM TlRMTVNTUAADAAAAAAAAAFgAAAAAAAAAWAAAAAAAAABYAAAAAAAAAFgAAA
AAAAAAWAAAAAAAAABYAAAABcKIogYBsR0AAAAPpF55Fg3FIqBMDUgLMi4e7w==
> User-Agent: curl/7.54.1-DEV
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Content-Type: text/html; charset=UTF-8
< Location: http://localhost/test-auth/
< Server: Microsoft-IIS/7.5
< Persistent-Auth: true
< X-Powered-By: ASP.NET
< Date: Wed, 28 Jun 2017 14:33:19 GMT
< Content-Length: 150
<
<head><title>Document Moved</title></head>
<body><h1>Object Moved</h1>This document may be found <a HREF="http://localhost/test-auth/">here</a></body>
* Connection #0 to host localhost left intact

On a Windows machine where logon user credentials are not accepted on the server the user may add a credential record for that server to the Windows Credential Manager. In this case curl fails to authenticate on the server:
curl -v -u : --ntlm remote-server/test-auth
*   Trying 10.16.81.156...
* TCP_NODELAY set
* Connected to remote-server (10.16.81.156) port 80 (#0)
* Server auth using NTLM with user ''
> GET /test-auth HTTP/1.1
> Host: remote-server
> Authorization: NTLM TlRMTVNTUAABAAAAB7IIogkACQAqAAAAAgACACgAAAAGAbEdAAAAD1ZNV0
9SS0dST1VQ
> User-Agent: curl/7.54.1-DEV
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< Content-Type: text/html; charset=us-ascii
< Server: Microsoft-HTTPAPI/2.0
< WWW-Authenticate: NTLM TlRMTVNTUAACAAAABAAEADgAAAAFgomir/ZxK+uKVEIAAAAAAAAAAHI
AcgA8AAAABgGxHQAAAA9LAEwAAgAEAEsATAABABIATgBPAFYASQBLAE8AVgAtAFAABAAMAGEAdgBwAC4
AcgB1AAMAIABuAG8AdgBpAGsAbwB2AC0AcAAuAGEAdgBwAC4AcgB1AAUADABhAHYAcAAuAHIAdQAHAAg
Ad7UWYB7w0gEAAAAA
< Date: Wed, 28 Jun 2017 14:53:59 GMT
< Content-Length: 341
<
* Ignoring the response-body
* Connection #0 to host remote-server left intact
* Issue another request to this URL: 'http://remote-server/test-auth'
* Found bundle for host remote-server: 0x67c490 [can pipeline]
* Re-using existing connection! (#0) with host remote-server
* Connected to remote-server (10.16.81.156) port 80 (#0)
* Server auth using NTLM with user ''
> GET /test-auth HTTP/1.1
> Host: remote-server
> Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGwAAAD6APoAhAAAAAQABABYAAAADAAMAFwAAA
AEAAQAaAAAAAAAAAB+AQAABYKIogYBsR0AAAAPnY5BsWXZfbo+yiqNhj57Z1YATQBWAE0AVwBhAHIAZQ
BWAE0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG0omJJ4aCwoSDUMF808rDQEBAAAAAAAAd7UWYB7w0g
EGkqTp1j8rAgAAAAACAAQASwBMAAEAEgBOAE8AVgBJAEsATwBWAC0AUAAEAAwAYQB2AHAALgByAHUAAw
AgAG4AbwB2AGkAawBvAHYALQBwAC4AYQB2AHAALgByAHUABQAMAGEAdgBwAC4AcgB1AAcACAB3tRZgHv
DSAQYABAACAAAACAAwADAAAAAAAAAAAQAAAAAgAAB3Lkajk4OkQP0WHQH99odKOWwKgX64hPOYLgjnvV
lf+QoAEAAAAAAAAAAAAAAAAAAAAAAACQAAAAAAAAAAAAAAAAAAAA==
> User-Agent: curl/7.54.1-DEV
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< Cache-Control: private
< Content-Type: text/html; charset=utf-8
< Server: Microsoft-IIS/7.5
< WWW-Authenticate: Digest qop="auth",algorithm=MD5-sess,nonce="+Upgraded+v155a8
b3a152ed4ac80cf8d5067db93d0775491b601ef0d2010046dc605bf4df0800ee572ccb08f408cd4c
c29bbec116d5de4c6b05fdf6ffea",charset=utf-8,realm="Digest"
< WWW-Authenticate: Negotiate
* NTLM handshake rejected
* Authentication problem. Ignoring this.
< WWW-Authenticate: NTLM
< WWW-Authenticate: Basic realm="remote-server"
< X-Powered-By: ASP.NET
< Date: Wed, 28 Jun 2017 14:53:59 GMT
< Content-Length: 6538
<
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x
html1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>IIS 7.5 Detailed Error - 401.1 - Unauthorized</title>
<style type="text/css">
<!--
body{margin:0;font-size:.7em;font-family:Verdana,Arial,Helvetica,sans-serif;back
ground:#CBE1EF;}
code{margin:0;color:#006600;font-size:1.1em;font-weight:bold;}
.config_source code{font-size:.8em;color:#000000;}
pre{margin:0;font-size:1.4em;word-wrap:break-word;}
ul,ol{margin:10px 0 10px 40px;}
ul.first,ol.first{margin-top:5px;}
fieldset{padding:0 15px 10px 15px;}
.summary-container fieldset{padding-bottom:5px;margin-top:4px;}
legend.no-expand-all{padding:2px 15px 4px 10px;margin:0 0 0 -12px;}
legend{color:#333333;padding:4px 15px 4px 10px;margin:4px 0 8px -12px;_margin-to
p:0px;
 border-top:1px solid #EDEDED;border-left:1px solid #EDEDED;border-right:1px sol
id #969696;
 border-bottom:1px solid #969696;background:#E7ECF0;font-weight:bold;font-size:1
em;}
a:link,a:visited{color:#007EFF;font-weight:bold;}
a:hover{text-decoration:none;}
h1{font-size:2.4em;margin:0;color:#FFF;}
h2{font-size:1.7em;margin:0;color:#CC0000;}
h3{font-size:1.4em;margin:10px 0 0 0;color:#CC0000;}
h4{font-size:1.2em;margin:10px 0 5px 0;
}#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:"trebuchet M
S",Verdana,sans-serif;
 color:#FFF;background-color:#5C87B2;
}#content{margin:0 0 0 2%;position:relative;}
.summary-container,.content-container{background:#FFF;width:96%;margin-top:8px;p
adding:10px;position:relative;}
.config_source{background:#fff5c4;}
.content-container p{margin:0 0 10px 0;
}#details-left{width:35%;float:left;margin-right:2%;
}#details-right{width:63%;float:left;overflow:hidden;
}#server_version{width:96%;_height:1px;min-height:1px;margin:0 0 5px 0;padding:1
1px 2% 8px 2%;color:#FFFFFF;
 background-color:#5A7FA5;border-bottom:1px solid #C1CFDD;border-top:1px solid #
4A6C8E;font-weight:normal;
 font-size:1em;color:#FFF;text-align:right;
}#server_version p{margin:5px 0;}
table{margin:4px 0 4px 0;width:100%;border:none;}
td,th{vertical-align:top;padding:3px 0;text-align:left;font-weight:bold;border:n
one;}
th{width:30%;text-align:right;padding-right:2%;font-weight:normal;}
thead th{background-color:#ebebeb;width:25%;
}#details-right th{width:20%;}
table tr.alt td,table tr.alt th{background-color:#ebebeb;}
.highlight-code{color:#CC0000;font-weight:bold;font-style:italic;}
.clear{clear:both;}
.preferred{padding:0 5px 2px 5px;font-weight:normal;background:#006633;color:#FF
F;font-size:.8em;}
-->
</style>

</head>
<body>
<div id="header"><h1>Server Error in Application "DEFAULT WEB SITE"</h1></div>
<div id="server_version"><p>Internet Information Services 7.5</p></div>
<div id="content">
<div class="content-container">
 <fieldset><legend>Error Summary</legend>
  <h2>HTTP Error 401.1 - Unauthorized</h2>
  <h3>You do not have permission to view this directory or page using the creden
tials that you supplied.</h3>
 </fieldset>
</div>
<div class="content-container">
 <fieldset><legend>Detailed Error Information</legend>
  <div id="details-left">
   <table border="0" cellpadding="0" cellspacing="0">
    <tr class="alt"><th>Module</th><td>WindowsAuthenticationModule</td></tr>
    <tr><th>Notification</th><td>AuthenticateRequest</td></tr>
    <tr class="alt"><th>Handler</th><td>ExtensionlessUrlHandler-Integrated-4.0</
td></tr>
    <tr><th>Error Code</th><td>0xc000006d</td></tr>

   </table>
  </div>
  <div id="details-right">
   <table border="0" cellpadding="0" cellspacing="0">
    <tr class="alt"><th>Requested URL</th><td>http://remote-server:80/test-auth<
/td></tr>
    <tr><th>Physical Path</th><td>C:\inetpub\wwwroot\test-auth</td></tr>
    <tr class="alt"><th>Logon Method</th><td>Not yet determined</td></tr>
    <tr><th>Logon User</th><td>Not yet determined</td></tr>

   </table>
   <div class="clear"></div>
  </div>
 </fieldset>
</div>
<div class="content-container">
 <fieldset><legend>Most likely causes:</legend>
  <ul>  <li>The username supplied to IIS is invalid.</li>       <li>The password
 supplied to IIS was not typed correctly. </li>         <li>Incorrect credential
s were cached by the browser.</li>      <li>IIS could not verify the identity of
 the username and password provided.</li>       <li>The resource is configured f
or Anonymous authentication, but the configured anonymous account either has an
invalid password or was disabled.</li>  <li>The server is configured to deny log
in privileges to the authenticating user or the group in which the user is a mem
ber.</li>       <li>Invalid Kerberos configuration may be the cause if all of th
e following are true:</li>      <ul>            <li>Integrated authentication wa
s used.</li>            <li>the application pool identity is a custom account.</
li>             <li>the server is a member of a domain.</li>    </ul> </ul>
 </fieldset>
</div>
<div class="content-container">
 <fieldset><legend>Things you can try:</legend>
  <ul>  <li>Verify that the username and password are correct, and are not cache
d by the browser.</li>  <li>Use a different username and password.</li>
<li>If you are using a custom anonymous account, verify that the password has no
t expired.</li>         <li>Verify that the authenticating user or the user's gr
oup, has not been denied login access to the server.</li>       <li>Verify that
the account was not locked out due to numerous failed login attempts.</li>
<li>If you are using authentication and the server is a member of a domain, veri
fy that you have configured the application pool identity using the utility SETS
PN.exe, or changed the configuration so that NTLM is the favored authentication
type.</li>      <li>Create a tracing rule to track failed requests for this HTTP
 status code. For more information about creating a tracing rule for failed requ
ests, click <a href="http://go.microsoft.com/fwlink/?LinkID=66439">here</a>. </l
i> </ul>
 </fieldset>
</div>


<div class="content-container">
 <fieldset><legend>Links and More Information</legend>
  This error occurs when either the username or password supplied to IIS is inva
lid, or when IIS cannot use the username and password to authenticate the user.

  <p><a href="http://go.microsoft.com/fwlink/?LinkID=62293&amp;IIS70Error=401,1,
0xc000006d,7601">View more information &raquo;</a></p>
  <p>Microsoft Knowledge Base Articles:</p>
 <ul><li>907273</li><li>871179</li><li>896861</li></ul>

 </fieldset>
</div>
</div>
</body>
</html>
* Connection #0 to host remote-server left intact

While on both machines Negotiate method works just fine.
curl -v -u : --negotiate localhost/test-auth
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /test-auth HTTP/1.1
> Host: localhost
> User-Agent: curl/7.54.1-DEV
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< Cache-Control: private
< Content-Type: text/html; charset=utf-8
< Server: Microsoft-IIS/7.5
< WWW-Authenticate: Negotiate
< WWW-Authenticate: NTLM
< X-Powered-By: ASP.NET
< Date: Wed, 28 Jun 2017 15:24:08 GMT
< Content-Length: 6295
<
* Ignoring the response-body
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'http://localhost/test-auth'
* Found bundle for host localhost: 0x517da8 [can pipeline]
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (127.0.0.1) port 80 (#0)
* Server auth using Negotiate with user ''
> GET /test-auth HTTP/1.1
> Host: localhost
> Authorization: Negotiate YHUGBisGAQUFAqBrMGmgMDAuBgorBgEEAYI3AgIKBgkqhkiC9xIBAgIGCSqGSIb3EgECAgYKKwYBBAGCNwICHqI1BDNOVExNU1NQAAEAAAC3sgjiAgACADEAAAAJAAkAKAAAA
AYBsR0AAAAPTk9WSUtPVi1QS0w=
> User-Agent: curl/7.54.1-DEV
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< Content-Type: text/html; charset=us-ascii
< Server: Microsoft-HTTPAPI/2.0
< WWW-Authenticate: Negotiate oYHKMIHHoAMKAQGhDAYKKwYBBAGCNwICCqKBsQSBrk5UTE1TU1AAAgAAAAQABAA4AAAANcKJ4voD8bHyYmOPsLtGBwAAAAByAHIAPAAAAAYBsR0AAAAPSwBMAAIABABLAE
wAAQASAE4ATwBWAEkASwBPAFYALQBQAAQADABhAHYAcAAuAHIAdQADACAAbgBvAHYAaQBrAG8AdgAtAHAALgBhAHYAcAAuAHIAdQAFAAwAYQB2AHAALgByAHUABwAIAIThH5Yi8NIBAAAAAA==
< Date: Wed, 28 Jun 2017 15:24:08 GMT
< Content-Length: 341
<
* Ignoring the response-body
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'http://localhost/test-auth'
* Found bundle for host localhost: 0x517da8 [can pipeline]
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (127.0.0.1) port 80 (#0)
* Server auth using Negotiate with user ''
> GET /test-auth HTTP/1.1
> Host: localhost
> Authorization: Negotiate oXcwdaADCgEBoloEWE5UTE1TU1AAAwAAAAAAAABYAAAAAAAAAFgAAAAAAAAAWAAAAAAAAABYAAAAAAAAAFgAAAAAAAAAWAAAADXCiOIGAbEdAAAAD4ctkoRdd4oeo1uMXV3Oh
DCjEgQQAQAAACyiMdYF1Hr8AAAAAA==
> User-Agent: curl/7.54.1-DEV
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Content-Type: text/html; charset=UTF-8
< Location: http://localhost/test-auth/
< Server: Microsoft-IIS/7.5
< Persistent-Auth: true
< X-Powered-By: ASP.NET
< WWW-Authenticate: Negotiate oRswGaADCgEAoxIEEAEAAACtLEmvX68whwAAAAA=
< Date: Wed, 28 Jun 2017 15:24:08 GMT
< Content-Length: 150
<
<head><title>Document Moved</title></head>
<body><h1>Object Moved</h1>This document may be found <a HREF="http://localhost/test-auth/">here</a></body>
* Closing connection 0
curl -v -u : --negotiate remote-server/test-auth
*   Trying 10.16.81.156...
* TCP_NODELAY set
* Connected to remote-server (10.16.81.156) port 80 (#0)
> GET /test-auth HTTP/1.1
> Host: remote-server
> User-Agent: curl/7.54.1-DEV
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< Cache-Control: private
< Content-Type: text/html; charset=utf-8
< Server: Microsoft-IIS/7.5
< WWW-Authenticate: Negotiate
< WWW-Authenticate: NTLM
< X-Powered-By: ASP.NET
< Date: Wed, 28 Jun 2017 15:22:56 GMT
< Content-Length: 6299
<
* Ignoring the response-body
* Connection #0 to host remote-server left intact
* Issue another request to this URL: 'http://remote-server/test-auth'
* Found bundle for host remote-server: 0x60e548 [can pipeline]
* Re-using existing connection! (#0) with host remote-server
* Connected to remote-server (10.16.81.156) port 80 (#0)
* Server auth using Negotiate with user ''
> GET /test-auth HTTP/1.1
> Host: remote-server
> Authorization: Negotiate TlRMTVNTUAABAAAAt4II4gAAAAAAAAAAAAAAAAAAAAAGAbEdAAAAD
w==
> User-Agent: curl/7.54.1-DEV
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< Content-Type: text/html; charset=us-ascii
< Server: Microsoft-HTTPAPI/2.0
< WWW-Authenticate: Negotiate TlRMTVNTUAACAAAABAAEADgAAAA1goniWzXQVeb/bCkAAAAAAA
AAAHIAcgA8AAAABgGxHQAAAA9LAEwAAgAEAEsATAABABIATgBPAFYASQBLAE8AVgAtAFAABAAMAGEAdg
BwAC4AcgB1AAMAIABuAG8AdgBpAGsAbwB2AC0AcAAuAGEAdgBwAC4AcgB1AAUADABhAHYAcAAuAHIAdQ
AHAAgAzuUyayLw0gEAAAAA
< Date: Wed, 28 Jun 2017 15:22:56 GMT
< Content-Length: 341
<
* Ignoring the response-body
* Connection #0 to host remote-server left intact
* Issue another request to this URL: 'http://remote-server/test-auth'
* Found bundle for host remote-server: 0x60e548 [can pipeline]
* Re-using existing connection! (#0) with host remote-server
* Connected to remote-server (10.16.81.156) port 80 (#0)
* Server auth using Negotiate with user ''
> GET /test-auth HTTP/1.1
> Host: remote-server
> Authorization: Negotiate TlRMTVNTUAADAAAAGAAYAHIAAAAeAR4BigAAAAQABABYAAAAEgASA
FwAAAAEAAQAbgAAABAAEACoAQAANYKI4gYBsR0AAAAPW+ZtZgFTNRcgOtnlHOaKg2sAbABuAG8AdgBpA
GsAbwB2AF8AcABWAE0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ/sl8s8kkqR3YkwpFz7h3gEBAAAAA
AAAzuUyayLw0gFrcP1ueqci9AAAAAACAAQASwBMAAEAEgBOAE8AVgBJAEsATwBWAC0AUAAEAAwAYQB2A
HAALgByAHUAAwAgAG4AbwB2AGkAawBvAHYALQBwAC4AYQB2AHAALgByAHUABQAMAGEAdgBwAC4AcgB1A
AcACADO5TJrIvDSAQYABAACAAAACAAwADAAAAAAAAAAAQAAAAAgAAB3Lkajk4OkQP0WHQH99odKOWwKg
X64hPOYLgjnvVlf+QoAEAAAAAAAAAAAAAAAAAAAAAAACQAkAEgAVABUAFAALwByAGUAbQBvAHQAZQAtA
HMAZQByAHYAZQByAAAAAAAAAAAAAAAAAFRxig/ZaY41FFjctrVihjc=
> User-Agent: curl/7.54.1-DEV
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Content-Type: text/html; charset=UTF-8
< Location: http://remote-server/test-auth/
< Server: Microsoft-IIS/7.5
< Persistent-Auth: true
< X-Powered-By: ASP.NET
< Date: Wed, 28 Jun 2017 15:22:56 GMT
< Content-Length: 154
<
<head><title>Document Moved</title></head>
<body><h1>Object Moved</h1>This document may be found <a HREF="http://remote-ser
ver/test-auth/">here</a></body>
* Closing connection 0

I expected the following

Both Negotiate and NTLM methods should work similarly, i.e. NTLM method should work when either logon user creds are accepted on the server, or there is a record for the server in Windows Credential Manager.

The solution is to provide host as an SPN to InitializeSecurityContext() calls in ntlm_sspi.c the same way it is done in spnego_sspi.c.

curl/libcurl version

curl 7.54.1-DEV (i386-pc-win32) libcurl/7.54.1-DEV WinSSL WinIDN
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher http https imap imaps ldap pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IDN Largefile SSPI Kerberos SPNEGO NTLM SSL

operating system

Microsoft Windows [Version 6.1.7601]

@frenche

This comment has been minimized.

Show comment
Hide comment
@frenche

frenche Jul 2, 2017

Contributor

So if I understand correctly, if we pass the SPN to InitializeSecurityContext() and there are saved credentials to this target host in Windows-Credential-Manager, then these credentials would be prefered over logon credentials, right? did you test indeed passing the SPN?

Assuming this is the prefered way, and given we already get this behavior in spnego (where we must pass the target), I think it would be ok to change as you have suggested.

Contributor

frenche commented Jul 2, 2017

So if I understand correctly, if we pass the SPN to InitializeSecurityContext() and there are saved credentials to this target host in Windows-Credential-Manager, then these credentials would be prefered over logon credentials, right? did you test indeed passing the SPN?

Assuming this is the prefered way, and given we already get this behavior in spnego (where we must pass the target), I think it would be ok to change as you have suggested.

@toughengineer

This comment has been minimized.

Show comment
Hide comment
@toughengineer

toughengineer Jul 2, 2017

Contributor

Hi, @frenche .
You are correct.
To check it I hardcoded the SPN string instead of (TCHAR *) TEXT("") in Curl_auth_create_ntlm_type1_message() and Curl_auth_create_ntlm_type3_message() in ntlm_sspi.c and it worked like a charm.
Chrome provides the SPN like this in case of proxy authentication:

HTTP/proxy.example.com

However I did not figure out the exact requirements for the form of SPN, i.e. is the serviceclass/ portion required or should you add port to the name or simply host name is enough.
I will double check it tomorrow and tell you.

Contributor

toughengineer commented Jul 2, 2017

Hi, @frenche .
You are correct.
To check it I hardcoded the SPN string instead of (TCHAR *) TEXT("") in Curl_auth_create_ntlm_type1_message() and Curl_auth_create_ntlm_type3_message() in ntlm_sspi.c and it worked like a charm.
Chrome provides the SPN like this in case of proxy authentication:

HTTP/proxy.example.com

However I did not figure out the exact requirements for the form of SPN, i.e. is the serviceclass/ portion required or should you add port to the name or simply host name is enough.
I will double check it tomorrow and tell you.

@toughengineer

This comment has been minimized.

Show comment
Hide comment
@toughengineer

toughengineer Jul 3, 2017

Contributor

So I found out how it works even further.
The server sends type 2 message containing identity information like this:

Msg Type: 2 (Challenge)
Target Name: u'AD_DOMAIN'
Challenge: 0x1d827c72abe0c317
Context: ''
Target:
    AD domain name (2): AD_DOMAIN
    Server name (1): SERVER
    DNS domain name (4): example.com
    FQDN (3): server.example.com
    Parent DNS domain (5): example.com
    Server Timestamp (7): ????????
OS Ver: '????????'
Flags: 0x-5d767dfb ["Negotiate Unicode", "Request Target", "Negotiate NTLM", "Negotiate Always Sign", "Target Type Domain", "Negotiate NTLM2 Key", "Negotiate Target Info", "unknown", "Negotiate 128", "Negotiate 56"]

so if a record exists in the Credential Manager for the FQDN (e.g. server.example.com) it works even if you provide empty SPN to the InitializeSecurityContext() call.
But often we use aliases which differ from that FQDN in the identity info and in that case provided SPN helps.
Finally my experiments show that provided SPN and address in the Credential Manager must be the same. The serviceclass/ part (e.g. HTTP/example.com) seems to be ignored. And since WinInet and IE store it as just a hostname (e.g. server.example.com) without port or path, I think the best solution is to provide SPN as just a host, i.e. the exact same way it is done in spnego_sspi.c.

Contributor

toughengineer commented Jul 3, 2017

So I found out how it works even further.
The server sends type 2 message containing identity information like this:

Msg Type: 2 (Challenge)
Target Name: u'AD_DOMAIN'
Challenge: 0x1d827c72abe0c317
Context: ''
Target:
    AD domain name (2): AD_DOMAIN
    Server name (1): SERVER
    DNS domain name (4): example.com
    FQDN (3): server.example.com
    Parent DNS domain (5): example.com
    Server Timestamp (7): ????????
OS Ver: '????????'
Flags: 0x-5d767dfb ["Negotiate Unicode", "Request Target", "Negotiate NTLM", "Negotiate Always Sign", "Target Type Domain", "Negotiate NTLM2 Key", "Negotiate Target Info", "unknown", "Negotiate 128", "Negotiate 56"]

so if a record exists in the Credential Manager for the FQDN (e.g. server.example.com) it works even if you provide empty SPN to the InitializeSecurityContext() call.
But often we use aliases which differ from that FQDN in the identity info and in that case provided SPN helps.
Finally my experiments show that provided SPN and address in the Credential Manager must be the same. The serviceclass/ part (e.g. HTTP/example.com) seems to be ignored. And since WinInet and IE store it as just a hostname (e.g. server.example.com) without port or path, I think the best solution is to provide SPN as just a host, i.e. the exact same way it is done in spnego_sspi.c.

@frenche

This comment has been minimized.

Show comment
Hide comment
@frenche

frenche Jul 18, 2017

Contributor

The server sends type 2 message containing identity information like this...

It sound a bit strange from security perspectives that SSPI trusts the server to tell it what credentials to use from cred-manager.

I'd say that would be more of a reason to specify the target host to SSPI as suggested.
It would be nice to see some related documentation though (I didn't find much).

Contributor

frenche commented Jul 18, 2017

The server sends type 2 message containing identity information like this...

It sound a bit strange from security perspectives that SSPI trusts the server to tell it what credentials to use from cred-manager.

I'd say that would be more of a reason to specify the target host to SSPI as suggested.
It would be nice to see some related documentation though (I didn't find much).

@toughengineer

This comment has been minimized.

Show comment
Hide comment
@toughengineer

toughengineer Jul 19, 2017

Contributor

It may be unclear from my previous message, but you assumed absolutely correct that domain name from type 2 NTLM message is used to find credentials only if the SPN provided in the InitializeSecurityContext() call is empty. Otherwise the provided SPN is used to find a record in the Credential Manger.
Partially I agree with your point security wise. But I can't imagine a useful attack employing this feature.

Anyway I would be super happy if this is fixed in the upcoming release with my changes or by any other means.

Contributor

toughengineer commented Jul 19, 2017

It may be unclear from my previous message, but you assumed absolutely correct that domain name from type 2 NTLM message is used to find credentials only if the SPN provided in the InitializeSecurityContext() call is empty. Otherwise the provided SPN is used to find a record in the Credential Manger.
Partially I agree with your point security wise. But I can't imagine a useful attack employing this feature.

Anyway I would be super happy if this is fixed in the upcoming release with my changes or by any other means.

@pfeigl

This comment has been minimized.

Show comment
Hide comment
@pfeigl

pfeigl Nov 16, 2017

This would be very nice, if it got fixed. Essentially this windows credential manager is used intensively in setups where you have to access resources in a different domain than your local domain.

pfeigl commented Nov 16, 2017

This would be very nice, if it got fixed. Essentially this windows credential manager is used intensively in setups where you have to access resources in a different domain than your local domain.

@lock lock bot locked as resolved and limited conversation to collaborators Jul 15, 2018

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