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

pscanrulesBeta: fix isolation scan rule isPage200 check #5957

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

atezet
Copy link

@atezet atezet commented Nov 27, 2024

Overview

Fix a bug in the site isolation scan rule.

Related Issues

zaproxy/zaproxy#8735

Checklist

  • Update help
  • Update changelog
  • Run ./gradlew spotlessApply for code formatting
  • Write tests
  • Check code coverage
  • Sign-off commits
  • Squash commits
  • Use a descriptive title

For more details, please refer to the developer rules and guidelines.

Copy link

github-actions bot commented Nov 27, 2024

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@atezet
Copy link
Author

atezet commented Nov 27, 2024

It is my understanding that this check is intended to filter out any non-success pages. I also thought it would make sense that non-200 custom pages should be filtered out, but the HttpStatusCode.isSuccess(...) call prevents that from being possible. Removing that turned out to also not work, as the isPage200 only accepts a status code of EXACTLY 200 (so not, e.g., 204).

If this understanding is wrong, the failing test (shouldNotRaiseAlertGivenSiteIsNotIsolatedWhenFailureIdentifiedByCustomPage) can be removed. If this is right, the isPage200 check should probably be fixed s.t. the HttpStatusCode.isSuccess(...) call can be removed.

@atezet
Copy link
Author

atezet commented Nov 27, 2024

I have read the CLA Document and I hereby sign the CLA

@thc202 thc202 changed the title Fix isolation scan rule isPage200 check pscanrulesBeta: fix isolation scan rule isPage200 check Nov 27, 2024
HttpMessage msg = new HttpMessage();
msg.setRequestHeader("GET / HTTP/1.1");
msg.setResponseHeader("HTTP/1.1 200 OK\r\n");
given(passiveScanData.isPage200(any())).willReturn(true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you noticed elsewhere this is unnecessary because a simple status code check is done first.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this line

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made some more changes, adding back a different mock. This conversation is irrelevant now.

HttpMessage msg = new HttpMessage();
msg.setRequestHeader("GET / HTTP/1.1");
msg.setResponseHeader("HTTP/1.1 200 OK\r\n" + "Content-Type: text/html");
given(passiveScanData.isPage200(any())).willReturn(false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this whole test, as this was meant to trigger a path that never existed (see earlier comment)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then set 404 instead of 200 🙂

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to replicate the Custom Pages example, but that didn't work in the old situation. I re-added the test, as this version using PassiveScanData.isSuccess actually works!

@kingthorin
Copy link
Member

Removing that turned out to also not work, as the isPage200 only accepts a status code of EXACTLY 200 (so not, e.g., 204).

It's actually a lot more involved than that, but yes it ultimately falls back to purely 200 if the user hasn't set any custom pages and analyzer wasn't able to identify the 404 handling.

Comment on lines 91 to 90
if (!HttpStatusCode.isSuccess(msg.getResponseHeader().getStatusCode())
// Specs don't state that errors pages should be excluded. However, successful responses are
// associated to a resource that should be protected, while error pages are not. Therefore,
// only consider HTTP Status code 2XX to avoid a False Positive
if (HttpStatusCode.isSuccess(msg.getResponseHeader().getStatusCode())
|| getHelper().isPage200(msg)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The correct is to call !isSuccess(msg).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I changed the flow from if !A return else do_something() to if A do_something(). This because A here was what is causing the bug; namely that if isPage200(...) the HttpMessage is skipped. So I believe this should either be:

if (!HttpStatusCode.isSuccess(msg.getResponseHeader().getStatusCode())
        && !getHelper().isPage200(msg)) {
        return;
}

rules.forEach(...);

or (what I wrote)

if (HttpStatusCode.isSuccess(msg.getResponseHeader().getStatusCode())
        || getHelper().isPage200(msg)) {
        rules.forEach(...);
}

That is; only scan pages that have status code 200-299 or are configured as non-standard error handling conditions as "page200" (see https://www.zaproxy.org/docs/desktop/start/features/custompages/). We could discuss whether this is what we want it to be, but at least we won't have so many false negatives as we have now.

Copy link
Member

@thc202 thc202 Nov 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be that the UI is not that clear but I highlighted the original code, which would be lines 91 to 92. I'm saying that the original code should have been (and should be) !isSuccess(msg). Note that isSuccess(HttpMessage) is other method than HttpStatusCode.isSuccess(HttpMessage), and isPage200 is already taken into account in the former.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, thanks that makes sense. Shall I change my PR up s.t. it uses isSuccess(msg)? I think that this is exactly what I was aiming for all along

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed it! Also fixed the tests by (re)adding mocks/stubs for isSuccess as it didn't seem to work otherwise

@psiinon
Copy link
Member

psiinon commented Nov 28, 2024

Logo
Checkmarx One – Scan Summary & Details20b4a645-2aac-47c8-834b-f8fe8f947b65

No New Or Fixed Issues Found

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

Successfully merging this pull request may close these issues.

4 participants