zaproxy / zaproxy

The ZAP core project
https://www.zaproxy.org
Apache License 2.0
12.21k stars 2.21k forks source link

ZAP creates an incorrect Authorization header when testing APIs #8506

Closed AlBellom closed 3 weeks ago

AlBellom commented 3 weeks ago

Describe the bug

I am running owasp/zap2docker-stable to test APIs. It appears that ZAP creates an incorrect Authorization header under certain circumstances.

This is the content of the option.prop file that causes ZAP to generate an incorrect header:

replacer.full_list(0).description=Authentication
replacer.full_list(0).enabled=true
replacer.full_list(0).matchtype=REQ_HEADER
replacer.full_list(0).matchstr=Authorization
replacer.full_list(0).regex=false
replacer.full_list(0).replacement=Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

The resulting header is:

Authorization: Bearer 
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

There is newline after the string Bearer.

The following is the content of the option.prop file for which ZAP generates a correct header. I arbitrary shorten the token.

replacer.full_list(0).description=Authentication
replacer.full_list(0).enabled=true
replacer.full_list(0).matchtype=REQ_HEADER
replacer.full_list(0).matchstr=Authorization
replacer.full_list(0).regex=false
replacer.full_list(0).replacement=Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

The resulting header is:

Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

It looks like ZAP insert a newline if the replacement string is longer than a certain value.

Steps to reproduce the behavior

  1. Create the following option.prop file:
    replacer.full_list(0).description=Authentication
    replacer.full_list(0).enabled=true
    replacer.full_list(0).matchtype=REQ_HEADER
    replacer.full_list(0).matchstr=Authorization
    replacer.full_list(0).regex=false
    replacer.full_list(0).replacement=Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  2. Run the following script:
    docker run -v $(pwd):/zap/wrk/:rw -t owasp/zap2docker-stable zap-api-scan.py \
    -d \
    -t /zap/wrk/swagger.json \
    -f openapi \
    -z "-configfile /zap/wrk/options.prop" \
    -r report.html
  3. Using a proxy like Proxyman observe that the Authorization header contains a newline:
    Authorization: Bearer
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    Note: I cannot provide the Swagger file, however any Swagger file would work.

Expected behavior

The generated Authorization header should not contain a newline:

Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Software versions

owasp/zap2docker-stable

Screenshots

No response

Errors from the zap.log file

No response

Additional context

No response

Would you like to help fix this issue?

psiinon commented 3 weeks ago

This should work, although I havnt checked the details. FYI the auth env vars are probably a better solution for this usecase: https://www.zaproxy.org/docs/getting-further/authentication/handling-auth-yourself/#authentication-env-vars

thc202 commented 3 weeks ago

Wire log using the provided option.prop file:

http-outgoing-0 >> "Authorization: Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[\r][\n]"

I don't see a newline there.

AlBellom commented 3 weeks ago

@thc202 Do you get that log entry on your server? I use a proxy to look at requests. The proxy shows that there is a newline after the Bearer string. This is consistent with the API not being able to authenticate the requests coming from ZAP. Screenshot 2024-05-30 at 2 16 26 PM

thc202 commented 3 weeks ago

That log is what's being sent to the server, but to clear any doubts just tried again with https://httpbin.org/headers and see the same:

{
  "headers": {
    "Accept": "application/json", 
    "Authorization": "Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 
    "Cache-Control": "no-cache", 
    "Host": "httpbin.org", 
    "Pragma": "no-cache", 
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; rv:125.0) Gecko/20100101 Firefox/125.0", 
    "X-Amzn-Trace-Id": "Root=1-12345"
  }
}

No newline in the Authorization header (now using the latest info in the issue).

thc202 commented 3 weeks ago

I don't know that proxy but that just looks like plain word wrapping not a newline in the header, did you make sure the token is correct? Maybe it's failing because it's no longer valid (though it might well be other reason).

thc202 commented 3 weeks ago

Closing, the replacer seems to be working correctly, feel free to leave a comment if you can provide the steps to reproduce it.

AlBellom commented 3 weeks ago

There is bug in Proxyman that cause the Authentication header to display incorrectly when the length of the token exceeds what can be shown on one line. It is not obvious with an auth token, give its length, as the Proxyman window can be extended so much. Proxyman arbitrarily breaks the line after the string Bearer even if there is no newline.