I need help with NTLM authentication configuration.
I am currently testing an AJAX web application using OWASP ZAP. The application is reachable via HTTPS and has NTLM auth enabled. When I run the scan, ZAP does not keep the proper sequence of NTLM negotiation. The expected way of NTLM connection is:
- Client sends GET to receive the website
- Server sends WWW-Authenticate: Negotiate and WWW-Authenticate: NTLM with 401 code
- Client sends auth information with Authorization:Negotiate
- Server responds with WWW-Authenticate: Negotiate and responds with requested page and code 200.
This scenario happens during the scan, but only first 2 steps - after receiving the Negotiate/NTLM challenge ZAP just starts the next test. Every few tests though, ZAP tries to perform the test by skipping step 3:
- ZAP sends Authorization:Negotiate with NTLM encoded with base64,
- Server sends WWW-Authenticate: Negotiate and WWW-Authenticate: NTLM with 401 code
After that ZAP just skips the test and saves an entry in zap.log:
"2018-07-16 18:07:57,969 [ZAP-ActiveScanner-1] ERROR HttpMethodDirector - Out of sequence NTLM response message org.apache.commons.httpclient.auth.MalformedChallengeException: Out of sequence NTLM response message".
Do you know what could be the issue here? Below I send you what I did with configuration, what are my logging options and what errors did I receive.
Steps to reproduce the behavior:
- Open the web browser with proxy configured for ZAP and click through the whole web application on https://example.com:9443/service (it's an AJAX service). I did not use an AJAX spider cause it often does not provide valid input on data-validated inputs.
- Sessions properties: Create new context with https://example.com:9443/service.*
- Sessions properties: Authentication: HTTP/NTLM Authentication
Hostname: https://example.com
Port: 8443
Realm: left empty (tried also with {AD Domain} and {AD Domain}.local)
Regex pattern identified in Logged In response: {string_from_logged_in_response}
- Sessions properties: Users: Add a valid user from the domain (tried both "{username}" and "{AD Domain}{username}")
4.Forced User: username set in step 3
Session management: HTTP Authentication Session Management
Authorization: HTTP Status Code: 401
Body contains regex: 'access restricted' (string that is placed on 401 page of the webapp). At least one of the conditions above must match.
After configuration run the scan:
On the Sites tree, right click on https://example.com:9443/service -> Attack -> Active Scan
In the Active Scan Scope tab:
Starting point: https://example.com:9443/service
Policy: Default
Context: The one configured above (step 1)
User: The one configured above (step 3)
- Start scan.
Logs I encounter - there is also one error with parsing the request body:
2018-07-16 18:07:57,414 [Thread-607] INFO HostProcess - Scanning 90 node(s) from https://example.com:9443/service as {user}
2018-07-16 18:07:57,418 [Thread-607] INFO HostProcess - start host https://example.com:9443/service | TestRemoteFileInclude strength MEDIUM threshold MEDIUM
2018-07-16 18:07:57,442 [Thread-607] ERROR HttpMethodDirector - Out of sequence NTLM response message
org.apache.commons.httpclient.auth.MalformedChallengeException: Out of sequence NTLM response message
at org.zaproxy.zap.network.ZapNTLMScheme.processChallenge(ZapNTLMScheme.java:131)
at org.apache.commons.httpclient.auth.AuthChallengeProcessor.processChallenge(AuthChallengeProcessor.java:162)
at org.apache.commons.httpclient.HttpMethodDirector.processWWWAuthChallenge(HttpMethodDirector.java:773)
at org.apache.commons.httpclient.HttpMethodDirector.processAuthenticationResponse(HttpMethodDirector.java:747)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:221)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
at org.parosproxy.paros.network.HttpSender.executeMethod(HttpSender.java:333)
at org.parosproxy.paros.network.HttpSender.runMethod(HttpSender.java:562)
at org.parosproxy.paros.network.HttpSender.send(HttpSender.java:523)
at org.parosproxy.paros.network.HttpSender.sendAuthenticated(HttpSender.java:501)
at org.parosproxy.paros.network.HttpSender.sendAuthenticated(HttpSender.java:490)
at org.parosproxy.paros.network.HttpSender.sendAndReceive(HttpSender.java:405)
at org.parosproxy.paros.network.HttpSender.sendAndReceive(HttpSender.java:362)
at org.parosproxy.paros.core.scanner.HostProcess.obtainResponse(HostProcess.java:507)
at org.parosproxy.paros.core.scanner.HostProcess.scanMessage(HostProcess.java:460)
at org.parosproxy.paros.core.scanner.HostProcess.processPlugin(HostProcess.java:371)
at org.parosproxy.paros.core.scanner.HostProcess.run(HostProcess.java:302)
at java.lang.Thread.run(Unknown Source)
2018-07-16 18:50:03,583 [ZAP-ActiveScanner-0] WARN VariantJSONQuery - Failed to parse the request body: Input is invalid JSON; does not start with '{' or '[', c=-1
java.lang.IllegalArgumentException: Input is invalid JSON; does not start with '{' or '[', c=-1
at org.parosproxy.paros.core.scanner.VariantJSONQuery.parseObject(VariantJSONQuery.java:117)
at org.parosproxy.paros.core.scanner.VariantJSONQuery.parseContent(VariantJSONQuery.java:61)
at org.parosproxy.paros.core.scanner.VariantAbstractRPCQuery.setRequestContent(VariantAbstractRPCQuery.java:167)
at org.parosproxy.paros.core.scanner.VariantAbstractRPCQuery.setMessage(VariantAbstractRPCQuery.java:51)
at org.parosproxy.paros.core.scanner.AbstractAppParamPlugin.scan(AbstractAppParamPlugin.java:161)
at org.parosproxy.paros.core.scanner.AbstractPlugin.run(AbstractPlugin.java:380)
at java.lang.Thread.run(Unknown Source)
Logging settings:
log4j.logger.org.parosproxy.paros=DEBUG
log4j.logger.org.zaproxy.zap=DEBUG
log4j.logger.org.apache.commons.httpclient=DEBUG
log4j.logger.httpclient.wire.header=DEBUG
log4j.logger.net.htmlparser.jericho=ERROR
Installation configuration:
ZAP: 2.7.0
Add-on: Set of default Add-ons.
OS: Windows 10 17134
Java: Java(TM) SE Runtime Environment (build 1.8.0_171-b11)
Browser: clicking through the application was done with Chrome, version 67.0.3396.99