-
Notifications
You must be signed in to change notification settings - Fork 179
Introduce scope limiter on cascading rules to enforce scope #805
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
Conversation
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
Signed-off-by: Jop Zitman <jop.zitman@secura.com> # Conflicts: # hooks/cascading-scans/hook/hook.test.js
|
Thanks for your effort already! Some initial thoughts on what you wrote: I like the idea of shifting this from the CascadingScan definition to the Scan definition, makes a lot more sense there in principle, and it should work fine for single-stage cascading scans (i.e., a scan triggers a CascadingScan, and then you're done). In this case, a single generic cascading scan definition is sufficient for multiple engagements. As soon as you have cascading scans that trigger additional cascading scans, it gets a bit more painful if you want to keep enforcing scope further down the chain. You'll need to write a custom cascading scan for each engagement after all, to specify the scope for further cascades in the ScanSpec, and you'll also need to start working with the hook selector features you recently contributed to avoid having cascading rules from different engagements trigger on the same scan, so at that point we're back to where we were before moving this to the Scan definition in terms of the complexity of setting things up. But since it is never worse than previously specified, and sometimes better, and it makes more intuitive sense, I think that moving it is a good thing. One place where this new behavior may be worse than specifying it on a per-hook basis is this: If I have some complex engagement rules that could only be modelled as a nested boolean formula ("(A AND B) OR (C AND D)"), this presumably cannot be represented with the syntax you are building (or can you have an How will this interact with inheritance on cascading scans? Standard inheritance behavior (turned off by default), or will this require anything more fancy? The new logic will be in addition to the old one (invasive/non-invasive etc.) and constraints from both will be combined, correct?
Since the definition for what you want to match is specified on a single scan, which has a single parser (which presumably will either always or never have a specific field in the results), how can a case appear where the field is not defined? If the field is set to
What do you mean with "independently supported"?
What happened to the domain-based operator ( |
|
Hello again 😄, For Secura, it makes sense to enforce scope throughout an entire engagement and thus force inherit the scope selector and not allow overriding it in cascading rules (i.e. no merge/perge issues). I think this tackles most of the points you discussed about moving the selector from hook to scan. Some comments below:
I'm not really sure what you mean here. We have a default set of cascading rules and use labels to match rules per customer or engagement.
Definitely. The labels are static matches using Kubernetes-native label selectors. These are evaluated while retrieving the rules. The annotation selectors introduced in this PR are evaluated in "runtime" and match on the scan's annotations instead of on just the findings.
The idea for
Nope, not sure if that would be possible to express in CRD.
Code is currently like below. To support more complex scenario's we could allow specifying if (scanAnnotationSelector.allOf !== undefined) return scanAnnotationSelector.allOf.every(validateRequirement);
if (scanAnnotationSelector.anyOf !== undefined) return scanAnnotationSelector.anyOf.some(validateRequirement);
if (scanAnnotationSelector.noneOf !== undefined) return !scanAnnotationSelector.noneOf.some(validateRequirement);
I'll implement it once you like the approach 😄. |
Hmm, I see. In cases where you can be sure that all scans that should trigger cascading scans will always return a hostname / IP that you can match on, this should work fine. And I guess there aren't any scanners that you would want to trigger additional network scans that will not return this. So, makes sense. However, the thing you describe (not allowing overriding) would make the inheritance behavior of the scope limiters different from that of the other inherited values... We had discussed that can of worms in #789. This may be a point where some input by @J12934 may be useful, as he is usually our "consistency evangelist" 😁. (Or am I misunderstanding you somewhere?)
tldr: Its another edge case that can show up, but its solvable with hook selectors and not necessary in 99% cases, so its fine the way you propose to do it. (You may notice that I think a lot about strange edge cases) Long version: I was still thinking about cascading rules that specify different scopes for their sub-scans - either without inheritance, or with further limitations being added down the line, like saying "You can scan all these IPs, but please leave the following ports alone for follow-up scans". Or you may have one scan that discovers hosts (e.g., based on DNS), followed by an nmap on in-scope systems, followed by a more detailed scanner that operates on specific ports, and only certain ports are in-scope. You cannot specify the ports-in-scope on the initial scan, since there is no port information anywhere in its output and so specifying the port requirements would break the cascade unless you play tricks with your "aliasing" + "ignore this if templating fails" logic. This may be a use case where you would need to specify new scope limiters in your cascading scans ScanSpec, which would mean that you need per-engagement custom cascading rules.
I see, so its aliasing that is used in combination with the inherited scope limiters. Makes sense!
Good, its a weird edge case anyway and not necessary. 😁
Combining all of them via AND may actually also resolve another problem I have with your code right now, which is that specifying all three operators is valid (in the sense that the cluster will accept a YAML file with them and not throw errors), but the code snippet you posted will just silently ignore most of them in favor of the first type it matches (i.e., if an allOf operator is present, anyOf and (more crucially) noneOf are ignored). ANDing them together would provide us with an intuitive and easy to document solution to this. |
Hahah yeah I get you. I'm down to implement it anyways, so let me know.
Yeah I was actually wondering how to specify mutual exclusiveness in CRD, but I don't think it's possible. I'll implement it with AND. |
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
|
Just talked to @J12934. He is fine with the proposed inheritance behavior. :) One other point he raised: He proposes |
|
Awesome. I'll take a look at annotation handling. Should |
|
Hmm. An argument could be made that it should be called If there isn't, and if you want to force inheritance on scope-related annotations no matter if other annotations are inherited, it probably makes sense to:
|
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
|
@malexmave implemented your proposal. See the test Still thinking about a better name for |
I would argue that "failing loudly" (stopping execution and printing an error message) would be the right move here, as silently discarding information will lead to impossible-to-track-down errors for users. |
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
…ppings to ScopeLimiterAliases Signed-off-by: Jop Zitman <jop.zitman@secura.com>
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
|
@malexmave @J12934 ready for review |
|
I will review this soon. Just a quick point so that we can avoid having the headache again: Can you make sure the helm docs are up to date so that we don't have the issue again where every new pull request runs the "Update helm docs" action? 😁 The resulting changes from the current state of the PR can be seen in 0b5c09b (I pushed it to a branch in our repo to run the CI). |
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
Signed-off-by: Max Maass <max.maass@iteratec.com>
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
Compatibility with NodeJS 14.X. Signed-off-by: Max Maass <max.maass@iteratec.com>
Signed-off-by: Max Maass <max.maass@iteratec.com>
Signed-off-by: Max Maass <max.maass@iteratec.com>
Signed-off-by: Max Maass <max.maass@iteratec.com>
Signed-off-by: Max Maass <max.maass@iteratec.com>
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
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.
After a fruitful and long set of discussions, debugging, testing and changes, this PR is finally ready to merge 🎉. Thanks again @EndPositive for the great work, long discussions and many changes you implemented.
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
Signed-off-by: Jop Zitman <jop.zitman@secura.com>
Signed-off-by: Jannik Hollenbach <jannik.hollenbach@iteratec.com>
Signed-off-by: Jannik Hollenbach <jannik.hollenbach@iteratec.com>
Signed-off-by: Jannik Hollenbach <jannik.hollenbach@iteratec.com>
|
Updated the branch & then resolved the merge issues in the unit tests. Seems to be working now. We should really tackle the code complexity in the cascading hook soon. The test file is already at 2800 lines of code 😬 |
Closes #761
Description
This PR introduces
ScopeLimiteronCascadeSpecso to match expressions can be added to enforce scope on an engagement. In #761, this field was thought to be added to theCascadingRuleSpec, but I've decided against it because the scope is usually defined on an engagement, instead of on a specific rule. This results in the following scan spec:This scan results in a finding with the hostname
136-144-234-6.colo.transip.net, which I don't want to scan, because my scope is only the domainsecura.com. With the PR, thescopeLimiterfield is evaluated and cascading scans would not be triggered.To ensure that you can define the selector independent of the finding format, I've added a new field
scopeLimiterAliasesin theParseDefinitionSpec. This field allows you to define aliases per scanner. This field should be addable throughvalues.yamlin each scanner (not yet implemented). The following alias could be added to nmap's parse definition.The scan definition would be:
Since a hostname might not be available for every parser, I've added the field
ValidOnMissingRenderso that an expression containing a mustache value which could not be rendered, resolves totrue. This behavior is disabled by default. The following expression would result totrue.The
allOf,anyOf, andnoneOfare independently supported. The following operator are supported:In,NotIn,Exists,DoesNotExist,Contains,DoesNotContain,InCIDR,NotInCIDR,SubdomainOf,NotSubdomainOf.I'd like some feedback on this particular approach 😄.
Todo
scanAnnotationSelectorselectorAttributeMappings.Checklist
npm testruns for the whole project.