-
Notifications
You must be signed in to change notification settings - Fork 365
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
Allow NTLM authentication without a password #371
Changes from 1 commit
0f3ea6c
0933c3f
5b1f9e5
24124ef
109376c
4230a32
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -399,6 +399,9 @@ type NTLMBindRequest struct { | |
Username string | ||
// Password is the credentials to bind with | ||
Password string | ||
// AllowEmptyPassword sets whether the client allows binding with an empty password | ||
// (normally used for unauthenticated bind). | ||
AllowEmptyPassword bool | ||
// Hash is the hex NTLM hash to bind with. Password or hash must be provided | ||
Hash string | ||
// Controls are optional controls to send with the bind request | ||
|
@@ -442,6 +445,24 @@ func (l *Conn) NTLMBind(domain, username, password string) error { | |
return err | ||
} | ||
|
||
// NTLMUnauthenticatedBind performs an unauthenticated bind. | ||
// | ||
// A username may be provided for trace (e.g. logging) purpose only, but it is normally not | ||
// authenticated or otherwise validated by the LDAP server. | ||
// | ||
// See https://tools.ietf.org/html/rfc4513#section-5.1.2 . | ||
// See https://tools.ietf.org/html/rfc4513#section-6.3.1 . | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. May you please update/add links for the NTLM anonymous request? Maybe refer to this PDF from Microsoft, for example section "3.2.5.1.2 Server Receives an AUTHENTICATE_MESSAGE from the Client" https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-NLMP/%5BMS-NLMP%5D.pdf There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You forgot to update the comment for |
||
func (l *Conn) NTLMUnauthenticatedBind(domain, username string) error { | ||
req := &NTLMBindRequest{ | ||
Domain: domain, | ||
Username: username, | ||
Password: "", | ||
AllowEmptyPassword: true, | ||
} | ||
_, err := l.NTLMChallengeBind(req) | ||
return err | ||
} | ||
|
||
// NTLMBindWithHash performs an NTLM Bind with an NTLM hash instead of plaintext password (pass-the-hash) | ||
func (l *Conn) NTLMBindWithHash(domain, username, hash string) error { | ||
req := &NTLMBindRequest{ | ||
|
@@ -455,7 +476,7 @@ func (l *Conn) NTLMBindWithHash(domain, username, hash string) error { | |
|
||
// NTLMChallengeBind performs the NTLMSSP bind operation defined in the given request | ||
func (l *Conn) NTLMChallengeBind(ntlmBindRequest *NTLMBindRequest) (*NTLMBindResult, error) { | ||
if ntlmBindRequest.Password == "" && ntlmBindRequest.Hash == "" { | ||
if !ntlmBindRequest.AllowEmptyPassword && ntlmBindRequest.Password == "" && ntlmBindRequest.Hash == "" { | ||
return nil, NewError(ErrorEmptyPassword, errors.New("ldap: empty password not allowed by the client")) | ||
} | ||
|
||
|
@@ -496,10 +517,10 @@ func (l *Conn) NTLMChallengeBind(ntlmBindRequest *NTLMBindRequest) (*NTLMBindRes | |
var err error | ||
var responseMessage []byte | ||
// generate a response message to the challenge with the given Username/Password if password is provided | ||
if ntlmBindRequest.Password != "" { | ||
responseMessage, err = ntlmssp.ProcessChallenge(ntlmsspChallenge, ntlmBindRequest.Username, ntlmBindRequest.Password) | ||
} else if ntlmBindRequest.Hash != "" { | ||
if ntlmBindRequest.Hash != "" { | ||
responseMessage, err = ntlmssp.ProcessChallengeWithHash(ntlmsspChallenge, ntlmBindRequest.Username, ntlmBindRequest.Hash) | ||
} else if ntlmBindRequest.Password != "" || ntlmBindRequest.AllowEmptyPassword { | ||
responseMessage, err = ntlmssp.ProcessChallenge(ntlmsspChallenge, ntlmBindRequest.Username, ntlmBindRequest.Password) | ||
} else { | ||
err = fmt.Errorf("need a password or hash to generate reply") | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-NLMP/%5BMS-NLMP%5D.pdf
In the same document, see section "3.3.2 NTLM v2 Authentication" the pseudo code for the ServerChallenge:
I interpret that for a anonymous NTLM bind the username must be empty. I don't have an Active Directory server at hand as I'm on vacation, so I can't confirm the behaviour :/
Can someone confirm this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did not notice that paper. The results of my tests are below:
parsing ntlm-challenge: Anonymous authentication not supported
is returnedThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your tests, @nodauf !
It seems anonymous NTLM authentications aren't supported by the Go NTLM library:
May you update the comment of the function and remove these lines, as atleast a username is required for the NTLM challenge to succeed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for taking the time to look. The comments have been updated (in both root folder and v3 😅 )