From da96eca5ae57b255b55caef40e453381eaf937ce Mon Sep 17 00:00:00 2001 From: Jop Zitman Date: Wed, 17 Nov 2021 18:37:34 +0100 Subject: [PATCH 01/13] Update CRD documentation and add HowTo for scope limiting Signed-off-by: Jop Zitman --- docs/api/crds/parse-definition.md | 12 +- docs/api/crds/scan.md | 44 ++++- .../integrating-a-scanner/values.yaml.md | 6 + docs/how-tos/scope.md | 185 ++++++++++++++++++ scripts/utils/config.js | 1 + 5 files changed, 246 insertions(+), 2 deletions(-) create mode 100644 docs/how-tos/scope.md diff --git a/docs/api/crds/parse-definition.md b/docs/api/crds/parse-definition.md index 537b0d6a..b38f7773 100644 --- a/docs/api/crds/parse-definition.md +++ b/docs/api/crds/parse-definition.md @@ -29,6 +29,14 @@ This uses the kubernetes default [imagePullSecrets structure](https://kubernetes `ttlSecondsAfterFinished` can be used to automatically delete the completed Kubernetes job used to run the parser. This sets the `ttlSecondsAfterFinished` field on the created job. This requires your cluster to have the [TTLAfterFinished](https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/) feature gate enabled in your cluster. +### ScopeLimiterAliases (Optional) + +`scopeLimiterAliases` can be used in combination with `scopeLimiter` to create aliases for fields in findings. +The goal of this field is to ensure that the `scopeSelector` can always select an alias, regardless of the underlying representation of the data in a finding. +This field supports Mustache templating and has access to the finding object. + +See the [Scope HowTo](/docs/how-tos/scope) for more information. + ## Example ```yaml @@ -41,6 +49,8 @@ spec: imagePullSecrets: - name: dockerhub-token ttlSecondsAfterFinished: 60 + scopeLimiterAliases: + domain: "{{attributes.host}}" ``` The Parse definition is different when integrating a new scanner. We use specific conventions when adding new ParseDefinitions to the secureCodeBox repository. -More information can be found on the [templates folder documentation page for integrating new scanners](/docs/contributing/integrating-a-scanner/templates-dir) \ No newline at end of file +More information can be found on the [templates folder documentation page for integrating new scanners](/docs/contributing/integrating-a-scanner/templates-dir) diff --git a/docs/api/crds/scan.md b/docs/api/crds/scan.md index 36da6737..e52b2ad1 100644 --- a/docs/api/crds/scan.md +++ b/docs/api/crds/scan.md @@ -116,9 +116,38 @@ The cascades config in the scans spec contains [Kubernetes Label Selectors](http Furthermore, in the cascade config you can specify whether cascading scan should inherit the parent's labels (`inheritLabels`) and annotations (`inheritAnnotations`). If not specified, the options will be considered as `true`. To use cascades you'll need to have the [CombinedScan hook](https://docs.securecodebox.io/docs/hooks/cascading-scans) installed. - +like this: For an example on how they can be used see the [Scanning Networks HowTo](https://docs.securecodebox.io/docs/how-tos/scanning-networks) +#### ScopeLimiter (Optional) + +`scopeLimiter` allows you to define certain rules to which cascading scans must comply before they may cascade. +For example, you can define that you can only cascade on a host, if the found ip address is within your predefined ip range. +You can use Mustache templating in order to select certain properties from findings. + +Under `scopeLimiter`, you may specify `anyOf`, `noneOf`, and `allOf` with a selector to limit your scope. +If you specify multiple fields, all the rules must pass. + +A selector looks similar to the [Kubernetes Label Selectors](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#labelselector-v1-meta). + +```yaml +anyOf: + - key: "scope.cascading.securecodebox.io/cidr" + operator: "InCIDR" + values: ["{{attributes.ip}}"] +``` + +The `key` references one of the annotations defined on your scan. +The annotation name _must_ start with `scope.cascading.securecodebox.io/`. +These annotations can only be added on the initial scan and are inherited by default. +Specifying a scope annotation in [`scanAnnotations`](/docs/api/crds/cascading-rule#scanlabels--scanannotations-optional) is not allowed. + +`operator` is one of `In`, `NotIn`, `Exists`, `DoesNotExist`, `Contains`, `DoesNotContain`, `InCIDR`, `NotInCIDR`, `SubdomainOf`, `NotSubdomainOf`. + +`values` is a list of values for which the selector should pass. + +See the [Scope HowTo](/docs/how-tos/scope) for more information. + ## Metadata Metadata is a standard field on Kubernetes resources. It contains multiple relevant fields, e.g. the name of the resource, its namespace and a `creationTimestamp` of the resource. See more on the [Kubernetes Docs]https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/) and the [Kubernetes API Reference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#objectmeta-v1-meta)) @@ -146,6 +175,9 @@ kind: Scan status: # Set during runtime. Do not edit via values.yaml etc. metadata: name: "nmap-scanme.nmap.org" + annotations: + scope.cascading.securecodebox.io/cidr: "10.10.0.0/16" + scope.cascading.securecodebox.io/domain: "example.com" spec: scanType: "nmap" parameters: @@ -169,4 +201,14 @@ spec: key: "securecodebox.io/invasive" operator: In values: [non-invasive, invasive] + scopeLimiter: + validOnMissingRender: true + allOf: + - key: "scope.cascading.securecodebox.io/cidr" + operator: "InCIDR" + values: ["{{attributes.ip}}"] + noneOf: + - key: "scope.cascading.securecodebox.io/domain" + operator: "SubdomainOf" + values: ["{{attributes.hostname}}"] ``` diff --git a/docs/contributing/integrating-a-scanner/values.yaml.md b/docs/contributing/integrating-a-scanner/values.yaml.md index 2153f2c2..5d6ea23b 100644 --- a/docs/contributing/integrating-a-scanner/values.yaml.md +++ b/docs/contributing/integrating-a-scanner/values.yaml.md @@ -28,6 +28,9 @@ parser: # parser.env -- Optional environment variables mapped into each parseJob (see: https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/) env: [] + # parser.scopeLimiterAliases -- Optional finding aliases to be used in the scopeLimiter. + scopeLimiterAliases: {} + # Do the same for the scanner containers scanner: image: @@ -141,6 +144,9 @@ Optional additional Containers started with the job (see: [Init Containers | Kub Optional securityContext set on the container (see: [Configure a Security Context for a Pod or Container | Kubernetes](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)). +### scopeLimiterAliases + +Optional scopeLimiterAliases set on the parse definition (see [ScopeLimiterAliases](/docs/api/crds/parse-definition#scopelimiteraliases-optional)) ## Using local images diff --git a/docs/how-tos/scope.md b/docs/how-tos/scope.md new file mode 100644 index 00000000..f5fac290 --- /dev/null +++ b/docs/how-tos/scope.md @@ -0,0 +1,185 @@ +--- +# SPDX-FileCopyrightText: 2021 iteratec GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Enforcing engagement scope" +--- + +## Introduction + +In this step-by-step tutorial, we will go through all the required stages to set up engagement scope enforcement with secureCodeBox. +In this example, we are going to set up Amass and Nmap and run a scan with rules set-up so that we don't scan domains which are out-of-scope. + +## Setup + +For the sake of the tutorial, we assume that you have your Kubernetes cluster already up and running and that we can work in your default namespace. +If not, check out the [installation](/docs/getting-started/installation/) for more information. + +We will start by installing Amass and Nmap: +```bash +helm upgrade --install amass secureCodeBox/amass +Release "amass" does not exist. Installing it now. +[...] +helm upgrade --install nmap secureCodeBox/nmap +Release "nmap" does not exist. Installing it now. +[...] +``` + +## Start scan with scope limit + +Next, we can start creating our scan definition. +Let's assume that we would like amass to scan `nmap.org` for subdomains, but we would only like to run nmap on `scanme.nmap.org`. +In the example below, we only cascade if our `scope.cascading.securecodebox.io/domain` equals `{{attributes.name}}`. + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "amass-scan" + annotations: + scope.cascading.securecodebox.io/domain: "scanme.nmap.org" +spec: + cascades: + scopeLimiter: + allOf: + - key: "scope.cascading.securecodebox.io/domain" + operator: "In" + values: ["{{attributes.name}}"] + scanType: "amass" + parameters: + - "-d" + - "nmap.org" +``` + +:::info +See the [CRD specification](/docs/api/crds/scan#scopelimiter-optional) for the specific syntax and allowed values. +::: + +Running this scan results in the following state: + +```shell +$ kubectl get scans +amass-scan amass Done 65 +nmap-scan-nmap-hostscan-86f2m nmap Done 6 +$ kubectl get pods +cascading-scans-amass-scan-8cssx--1-hh2w6 0/1 Completed 0 2m51s +cascading-scans-nmap-scan-nmap-hostscan-86f2m-4mljv--1-7zgm2 0/1 Completed 0 2m23s +parse-amass-scan-zfhxg--1-shwkj 0/1 Completed 0 2m54s +parse-nmap-scan-nmap-hostscan-86f2m-d6jh6--1-ztgls 0/1 Completed 0 2m26s +scan-amass-scan-79h5f--1-vk7v5 0/2 Completed 0 4m22s +scan-nmap-scan-nmap-hostscan-86f2m-54pkd--1-pfpp6 0/2 Completed 0 2m48s +``` + +As you can see, amass found 65 domain names, but only a single nmap scan was created. +In the cascading scans logs, you will see that lot's of rules were not triggered as the domain was out of scope. + +```shell +$ k +Starting hook for Scan "amass-scan" +Fetched 65 findings from the file storage +Fetching CascadingScans using LabelSelector: "" +Fetched 2 CascadingRules +Cascading Rule nmap-hostscan not triggered as scope limiter did not pass +[...] +``` + +## Handle differences in finding formats + +In many cases, you are cascading to more than one scanner. +Unfortunately, not every scanner has the same finding format, making a scope as defined above more tricky. + +As an example, let's say you want to set up Nikto as a scanner. +This scanner cascades on Nmap's open port finding and uses `$.hostOrIp` to start the scan. +In some cases, nmap can return a hostname different to the original hostname, thus with scope rules we want to check for this. +Preferably, we would like to use the same rule as above. +Unfortunately, nmap gives its hostname in `attributes.hostname` instead of the defined `attributes.name` (Amass finding). +This results in the scope rule failing, and prevents Nikto from getting cascaded. + +To solve this situation, you have two options: + +### Option 1: enable `validOnMissingRender` + +Enabling this option causes all defined rules which contain unresolved mustache templates to result in `true`. You can use this if you're sure that Nmap returns the valid hostname. + +Example: + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "amass-scan" + annotations: + scope.cascading.securecodebox.io/domain: "scanme.nmap.org" +spec: + cascades: + // highlight-next-line + validOnMissingRender: true + scopeLimiter: + allOf: + - key: "scope.cascading.securecodebox.io/domain" + operator: "In" + values: ["{{attributes.name}}"] + scanType: "amass" + parameters: + - "-d" + - "nmap.org" +``` + +### Option 2: create a hostname alias for all deployed scanners + +A more fool-proof solution is to ensure that the hostname field is available in the same place for each scanner. +When deploying your scanner, you can define `scopeLimiterAliases`. + +```shell +$ helm upgrade --install amass secureCodeBox/amass \ + --set parser.scopeLimiterAliases.hostname="{{attributes.name}}" +Release "amass" has been upgraded. Happy Helming! +[...] +$ helm upgrade --install nmap secureCodeBox/nmap \ + --set parser.scopeLimiterAliases.hostname="{{attributes.hostname}}" +Release "nmap" has been upgraded. Happy Helming! +[...] +``` + +The aliases are added to the scanner's parse definition: + +```yaml +apiVersion: execution.securecodebox.io/v1 +kind: ParseDefinition +metadata: + name: amass-jsonl + namespace: default +spec: + env: [] + image: docker.io/securecodebox/parser-amass:3.5.0 + imagePullPolicy: IfNotPresent + scopeLimiterAliases: + hostname: "{{attributes.name}}" + ttlSecondsAfterFinished: null +``` + +To use your custom alias, you reference it with `$.hostname` in `scopeLimiter` in your scan definition. + +```yaml +scopeLimiter: + allOf: + - key: "scope.cascading.securecodebox.io/domain" + operator: "In" + values: ["{{$.hostname}}"] +``` + +Running this scan inside the cluster runs Amass, Nmap, and Nikto as expected. + +```shell +$ kubectl get scans +NAME TYPE STATE FINDINGS +amass-scan amass Done 65 +nikto-scan-nmap-hostscan-rhhqz-nikto-http-ps8cl nikto Done 6 +nmap-scan-nmap-hostscan-rhhqz nmap Done 6 +``` + +:::caution +The scope limiter only applies to cascading scans. +If your initial scan is out-of-scope, it will still run. +::: diff --git a/scripts/utils/config.js b/scripts/utils/config.js index 30724113..2e72364a 100644 --- a/scripts/utils/config.js +++ b/scripts/utils/config.js @@ -51,6 +51,7 @@ const docsConfig = { "how-tos/automatically-repeating-scans", "how-tos/scanning-networks", "how-tos/scanning-web-applications", + "how-tos/scope", ], }, sidebarEnd: { From 635011132a1c35af105804ac05b60c941a6e30fe Mon Sep 17 00:00:00 2001 From: Jop Zitman Date: Wed, 17 Nov 2021 18:45:54 +0100 Subject: [PATCH 02/13] Add cascading scans note. Signed-off-by: Jop Zitman --- docs/how-tos/scope.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/how-tos/scope.md b/docs/how-tos/scope.md index f5fac290..e120c3b1 100644 --- a/docs/how-tos/scope.md +++ b/docs/how-tos/scope.md @@ -15,6 +15,7 @@ In this example, we are going to set up Amass and Nmap and run a scan with rules For the sake of the tutorial, we assume that you have your Kubernetes cluster already up and running and that we can work in your default namespace. If not, check out the [installation](/docs/getting-started/installation/) for more information. +We also assume that you have the latest version of cascading scans installed. We will start by installing Amass and Nmap: ```bash From 36019f26e0866b5577382a44ed7d9db350fba365 Mon Sep 17 00:00:00 2001 From: Jop Zitman Date: Thu, 18 Nov 2021 18:07:33 +0100 Subject: [PATCH 03/13] Apply suggestions from code review Co-authored-by: Max Maass <1688580+malexmave@users.noreply.github.com> Signed-off-by: Jop Zitman --- docs/api/crds/scan.md | 7 +++---- docs/how-tos/scope.md | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/api/crds/scan.md b/docs/api/crds/scan.md index e52b2ad1..d7bc3a1d 100644 --- a/docs/api/crds/scan.md +++ b/docs/api/crds/scan.md @@ -115,14 +115,14 @@ The cascades config in the scans spec contains [Kubernetes Label Selectors](http Furthermore, in the cascade config you can specify whether cascading scan should inherit the parent's labels (`inheritLabels`) and annotations (`inheritAnnotations`). If not specified, the options will be considered as `true`. -To use cascades you'll need to have the [CombinedScan hook](https://docs.securecodebox.io/docs/hooks/cascading-scans) installed. +To use cascades you'll need to have the [CascadingScan hook](https://docs.securecodebox.io/docs/hooks/cascading-scans) installed. like this: For an example on how they can be used see the [Scanning Networks HowTo](https://docs.securecodebox.io/docs/how-tos/scanning-networks) #### ScopeLimiter (Optional) `scopeLimiter` allows you to define certain rules to which cascading scans must comply before they may cascade. -For example, you can define that you can only cascade on a host, if the found ip address is within your predefined ip range. +For example, you can define that you can only trigger a follow-up scan against a host if its IP address is within your predefined IP range. You can use Mustache templating in order to select certain properties from findings. Under `scopeLimiter`, you may specify `anyOf`, `noneOf`, and `allOf` with a selector to limit your scope. @@ -139,8 +139,7 @@ anyOf: The `key` references one of the annotations defined on your scan. The annotation name _must_ start with `scope.cascading.securecodebox.io/`. -These annotations can only be added on the initial scan and are inherited by default. -Specifying a scope annotation in [`scanAnnotations`](/docs/api/crds/cascading-rule#scanlabels--scanannotations-optional) is not allowed. +These annotations can only be added on the initial scan (i.e., they cannot be modified using the [`scanAnnotations`](/docs/api/crds/cascading-rule#scanlabels--scanannotations-optional) field of the cascading scan rules) and are inherited by default. `operator` is one of `In`, `NotIn`, `Exists`, `DoesNotExist`, `Contains`, `DoesNotContain`, `InCIDR`, `NotInCIDR`, `SubdomainOf`, `NotSubdomainOf`. diff --git a/docs/how-tos/scope.md b/docs/how-tos/scope.md index e120c3b1..674e1c71 100644 --- a/docs/how-tos/scope.md +++ b/docs/how-tos/scope.md @@ -73,7 +73,7 @@ scan-nmap-scan-nmap-hostscan-86f2m-54pkd--1-pfpp6 0/2 Completed ``` As you can see, amass found 65 domain names, but only a single nmap scan was created. -In the cascading scans logs, you will see that lot's of rules were not triggered as the domain was out of scope. +In the cascading scans logs, you will see that lots of rules were not triggered as the domain was out of scope. ```shell $ k From ff6edc2ea2369fe233099cab3e4909c8657e4318 Mon Sep 17 00:00:00 2001 From: Jop Zitman Date: Thu, 18 Nov 2021 18:10:12 +0100 Subject: [PATCH 04/13] Small fixes Signed-off-by: Jop Zitman --- docs/api/crds/scan.md | 1 - docs/how-tos/scope.md | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/api/crds/scan.md b/docs/api/crds/scan.md index d7bc3a1d..39171a64 100644 --- a/docs/api/crds/scan.md +++ b/docs/api/crds/scan.md @@ -116,7 +116,6 @@ The cascades config in the scans spec contains [Kubernetes Label Selectors](http Furthermore, in the cascade config you can specify whether cascading scan should inherit the parent's labels (`inheritLabels`) and annotations (`inheritAnnotations`). If not specified, the options will be considered as `true`. To use cascades you'll need to have the [CascadingScan hook](https://docs.securecodebox.io/docs/hooks/cascading-scans) installed. -like this: For an example on how they can be used see the [Scanning Networks HowTo](https://docs.securecodebox.io/docs/how-tos/scanning-networks) #### ScopeLimiter (Optional) diff --git a/docs/how-tos/scope.md b/docs/how-tos/scope.md index 674e1c71..1e934fd7 100644 --- a/docs/how-tos/scope.md +++ b/docs/how-tos/scope.md @@ -76,7 +76,7 @@ As you can see, amass found 65 domain names, but only a single nmap scan was cre In the cascading scans logs, you will see that lots of rules were not triggered as the domain was out of scope. ```shell -$ k +$ kubectl logs cascading-scans-amass-scan-8cssx--1-hh2w6 Starting hook for Scan "amass-scan" Fetched 65 findings from the file storage Fetching CascadingScans using LabelSelector: "" From a869ff523973aab95f18c2791c8d5377a92772f4 Mon Sep 17 00:00:00 2001 From: Jop Zitman Date: Thu, 18 Nov 2021 18:57:49 +0100 Subject: [PATCH 05/13] Add documentation for each scope limiter operator type Signed-off-by: Jop Zitman --- docs/api/crds/scan.md | 55 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/docs/api/crds/scan.md b/docs/api/crds/scan.md index 39171a64..5e4505fd 100644 --- a/docs/api/crds/scan.md +++ b/docs/api/crds/scan.md @@ -144,6 +144,61 @@ These annotations can only be added on the initial scan (i.e., they cannot be mo `values` is a list of values for which the selector should pass. +##### Operators + +`In` & `NotIn`: The scope annotation value exists in one of `values`. Matching example: +```yaml +annotations: + scope.cascading.securecodebox.io/domain: "example.com" +... +key: "scope.cascading.securecodebox.io/domain" +operator: "In" +values: ["example.com", "subdomain.example.com"] +``` + +`Exists` & `DoesNotExist`: The scope annotation exists. Matching example: +```yaml +annotations: + scope.cascading.securecodebox.io/domain: "example.com" +... +key: "scope.cascading.securecodebox.io/domain" +operator: "Exists" +``` + +:::note +Specifying `values` together with the operator `Exists` is considered a syntax error. +::: + +`Contains` & `DoesNotContain`: The scope annotation value is considered a comma-seperated list and checks if every `values` is in that list. Matching example: +```yaml +annotations: + scope.cascading.securecodebox.io/domain: "example.com,subdomain.example.com,other.example.com" +... +key: "scope.cascading.securecodebox.io/domain" +operator: "Contains" +values: ["example.com", "subdomain.example.com"] +``` + +`InCIDR` & `NotInCIDR`: The scope annotation value is considered [CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) and checks if every `values` is within the subnet of that CIDR. Matching example: +```yaml +annotations: + scope.cascading.securecodebox.io/cidr: "10.10.0.0/16" +... +key: "scope.cascading.securecodebox.io/cidr" +operator: "InCIDR" +values: ["10.10.1.2", "10.10.1.3"] +``` + +`SubdomainOf` & `NotSubdomainOf`: Checks if every `values` is a subdomain of the scope annotation value (inclusive; i.e. example.com is a subdomain of example.com). Matching example: +```yaml +annotations: + scope.cascading.securecodebox.io/domain: "example.com" +... +key: "scope.cascading.securecodebox.io/domain" +operator: "SubdomainOf" +values: ["subdomain.example.com", "example.com"] +``` + See the [Scope HowTo](/docs/how-tos/scope) for more information. ## Metadata From 65b3d1fb6957f1dced12bdec12cfc55ddaaca820 Mon Sep 17 00:00:00 2001 From: Jop Zitman Date: Fri, 19 Nov 2021 11:01:37 +0100 Subject: [PATCH 06/13] Get rid of redundant operators Signed-off-by: Jop Zitman --- docs/api/crds/scan.md | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/docs/api/crds/scan.md b/docs/api/crds/scan.md index 5e4505fd..8585c9d5 100644 --- a/docs/api/crds/scan.md +++ b/docs/api/crds/scan.md @@ -156,19 +156,6 @@ operator: "In" values: ["example.com", "subdomain.example.com"] ``` -`Exists` & `DoesNotExist`: The scope annotation exists. Matching example: -```yaml -annotations: - scope.cascading.securecodebox.io/domain: "example.com" -... -key: "scope.cascading.securecodebox.io/domain" -operator: "Exists" -``` - -:::note -Specifying `values` together with the operator `Exists` is considered a syntax error. -::: - `Contains` & `DoesNotContain`: The scope annotation value is considered a comma-seperated list and checks if every `values` is in that list. Matching example: ```yaml annotations: From a31310e1e1f430d9bed8dd57c31434099d2a9dfe Mon Sep 17 00:00:00 2001 From: Jop Zitman Date: Thu, 25 Nov 2021 14:01:09 +0100 Subject: [PATCH 07/13] Add IPv6 support to InCIDR Signed-off-by: Jop Zitman --- docs/api/crds/scan.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/crds/scan.md b/docs/api/crds/scan.md index 8585c9d5..6e956224 100644 --- a/docs/api/crds/scan.md +++ b/docs/api/crds/scan.md @@ -166,14 +166,14 @@ operator: "Contains" values: ["example.com", "subdomain.example.com"] ``` -`InCIDR` & `NotInCIDR`: The scope annotation value is considered [CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) and checks if every `values` is within the subnet of that CIDR. Matching example: +`InCIDR` & `NotInCIDR`: The scope annotation value is considered [CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) and checks if every `values` is within the subnet of that CIDR. Supports both IPv4 and IPv6. If the scope is defined in IPv4, will only validate IPv4 IPs in the finding values. Vice-versa for IPv6 defined in scope and IPv4 found in values. Note that all IPs in finding values must be valid addresses, regardless of whether IPv4 or IPv6 was used in the scope definition. Matching example: ```yaml annotations: scope.cascading.securecodebox.io/cidr: "10.10.0.0/16" ... key: "scope.cascading.securecodebox.io/cidr" operator: "InCIDR" -values: ["10.10.1.2", "10.10.1.3"] +values: ["10.10.1.2", "10.10.1.3", "2001:0:ce49:7601:e866:efff:62c3:fffe"] ``` `SubdomainOf` & `NotSubdomainOf`: Checks if every `values` is a subdomain of the scope annotation value (inclusive; i.e. example.com is a subdomain of example.com). Matching example: From a37dc21ef86efc4d113167ef46bfdbf319a81923 Mon Sep 17 00:00:00 2001 From: Jop Zitman Date: Fri, 26 Nov 2021 12:22:12 +0100 Subject: [PATCH 08/13] Add list selection to docs Signed-off-by: Jop Zitman --- docs/api/crds/scan.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/api/crds/scan.md b/docs/api/crds/scan.md index 6e956224..c56b39d1 100644 --- a/docs/api/crds/scan.md +++ b/docs/api/crds/scan.md @@ -144,6 +144,33 @@ These annotations can only be added on the initial scan (i.e., they cannot be mo `values` is a list of values for which the selector should pass. +##### Selecting lists + +A custom rendering function has been provided to select attributes in findings that are in a list. An example finding: + +```json title="Finding" +{ + name: "Subdomains found", + category: "Subdomain" + attributes: { + domains: ["example.com", "subdomain.example.com"], + } +} +``` + +To select the domains data in this finding, use the notation as shown below. + +```yaml +annotations: + scope.cascading.securecodebox.io/domain: "example.com" +... +key: "scope.cascading.securecodebox.io/domain" +operator: "In" +values: ["{{#list}}{{attributes.domains}}{{/list}}"] +``` + +The values will render to: `["example.com", "subdomain.example.com"]`. + ##### Operators `In` & `NotIn`: The scope annotation value exists in one of `values`. Matching example: From cffd0dd7c194d3f52178553eb35608cecf81c176 Mon Sep 17 00:00:00 2001 From: Jop Zitman Date: Mon, 29 Nov 2021 15:47:55 +0100 Subject: [PATCH 09/13] Remove Exists from docs Signed-off-by: Jop Zitman --- docs/api/crds/scan.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/crds/scan.md b/docs/api/crds/scan.md index c56b39d1..1090f589 100644 --- a/docs/api/crds/scan.md +++ b/docs/api/crds/scan.md @@ -140,7 +140,7 @@ The `key` references one of the annotations defined on your scan. The annotation name _must_ start with `scope.cascading.securecodebox.io/`. These annotations can only be added on the initial scan (i.e., they cannot be modified using the [`scanAnnotations`](/docs/api/crds/cascading-rule#scanlabels--scanannotations-optional) field of the cascading scan rules) and are inherited by default. -`operator` is one of `In`, `NotIn`, `Exists`, `DoesNotExist`, `Contains`, `DoesNotContain`, `InCIDR`, `NotInCIDR`, `SubdomainOf`, `NotSubdomainOf`. +`operator` is one of `In`, `NotIn`, `Contains`, `DoesNotContain`, `InCIDR`, `NotInCIDR`, `SubdomainOf`, `NotSubdomainOf`. `values` is a list of values for which the selector should pass. From d59d90c48f84f273ddc6a0c8eb21f2c4458920cb Mon Sep 17 00:00:00 2001 From: Jop Zitman Date: Mon, 29 Nov 2021 15:48:12 +0100 Subject: [PATCH 10/13] Add examples for selecting lists Signed-off-by: Jop Zitman --- docs/api/crds/scan.md | 59 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/docs/api/crds/scan.md b/docs/api/crds/scan.md index 1090f589..8836a883 100644 --- a/docs/api/crds/scan.md +++ b/docs/api/crds/scan.md @@ -158,7 +158,7 @@ A custom rendering function has been provided to select attributes in findings t } ``` -To select the domains data in this finding, use the notation as shown below. +To select the domains data in this finding, use the `asList` notation as shown below. ```yaml annotations: @@ -166,11 +166,66 @@ annotations: ... key: "scope.cascading.securecodebox.io/domain" operator: "In" -values: ["{{#list}}{{attributes.domains}}{{/list}}"] +values: ["{{#asList}}{{attributes.domains}}{{/asList}}"] ``` The values will render to: `["example.com", "subdomain.example.com"]`. +Some findings have data in lists of objects, such as the following: + +```json title="Finding" +{ + name: "Subdomains found", + category: "Subdomain" + attributes: { + addresses: [ + { + domain: "example.com", + ip: "127.0.0.1", + }, + { + domain: "subdomain.example.com", + ip: "127.0.0.2", + } + ] + } +} +``` + +To select the domains data in this finding, use the `pickValues` notation as shown below. + +```yaml +annotations: + scope.cascading.securecodebox.io/domain: "example.com" +... +key: "scope.cascading.securecodebox.io/domain" +operator: "In" +values: ["{{#pickValues}}{{attributes.addresses.domain}}{{/pickValues}}"] +``` + +You can also manually split values from findings manually if your finding is like so: + +```json title="Finding" +{ + name: "Subdomains found", + category: "Subdomain" + attributes: { + domains: "example.com,subdomain.example.com", + } +} +``` + +To select the domains data in this finding, use the `split` notation as shown below. + +```yaml +annotations: + scope.cascading.securecodebox.io/domain: "example.com" +... +key: "scope.cascading.securecodebox.io/domain" +operator: "In" +values: ["{{#split}}{{attributes.domains}}{{/split}}"] +``` + ##### Operators `In` & `NotIn`: The scope annotation value exists in one of `values`. Matching example: From 7b6c3eb775056d13331a129caea23b6896351ccc Mon Sep 17 00:00:00 2001 From: Max Maass Date: Tue, 30 Nov 2021 17:08:02 +0100 Subject: [PATCH 11/13] Rename pickValues => getValues in documentation Signed-off-by: Max Maass --- docs/api/crds/scan.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/crds/scan.md b/docs/api/crds/scan.md index 3d0dc730..dc6477eb 100644 --- a/docs/api/crds/scan.md +++ b/docs/api/crds/scan.md @@ -208,7 +208,7 @@ Some findings have data in lists of objects, such as the following: } ``` -To select the domains data in this finding, use the `pickValues` notation as shown below. +To select the domains data in this finding, use the `getValues` notation as shown below. ```yaml annotations: @@ -216,7 +216,7 @@ annotations: ... key: "scope.cascading.securecodebox.io/domain" operator: "In" -values: ["{{#pickValues}}{{attributes.addresses.domain}}{{/pickValues}}"] +values: ["{{#getValues}}{{attributes.addresses.domain}}{{/getValues}}"] ``` You can also manually split values from findings manually if your finding is like so: From 923df867c55250a478eb1d4977a9c9f1e08f5587 Mon Sep 17 00:00:00 2001 From: Max Maass Date: Tue, 30 Nov 2021 18:13:50 +0100 Subject: [PATCH 12/13] Fix small mistakes in documentation Signed-off-by: Max Maass --- docs/api/crds/scan.md | 7 ++++--- docs/how-tos/scope.md | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/api/crds/scan.md b/docs/api/crds/scan.md index dc6477eb..3ecfaeb6 100644 --- a/docs/api/crds/scan.md +++ b/docs/api/crds/scan.md @@ -216,10 +216,11 @@ annotations: ... key: "scope.cascading.securecodebox.io/domain" operator: "In" -values: ["{{#getValues}}{{attributes.addresses.domain}}{{/getValues}}"] +# Note that the parameter is *not* set inside curly braces! +values: ["{{#getValues}}attributes.addresses.domain{{/getValues}}"] ``` -You can also manually split values from findings manually if your finding is like so: +You can also manually split values from findings if your finding is like so: ```json title="Finding" { @@ -264,7 +265,7 @@ operator: "Contains" values: ["example.com", "subdomain.example.com"] ``` -`InCIDR` & `NotInCIDR`: The scope annotation value is considered [CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) and checks if every `values` is within the subnet of that CIDR. Supports both IPv4 and IPv6. If the scope is defined in IPv4, will only validate IPv4 IPs in the finding values. Vice-versa for IPv6 defined in scope and IPv4 found in values. Note that all IPs in finding values must be valid addresses, regardless of whether IPv4 or IPv6 was used in the scope definition. Matching example: +`InCIDR` & `NotInCIDR`: The scope annotation value is considered a [CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) and checks if every `values` is within the subnet of that CIDR. Supports both IPv4 and IPv6. If the scope is defined in IPv4, will only validate IPv4 IPs in the finding values. Vice-versa for IPv6 defined in scope and IPv4 found in values. Note that all IPs in finding values must be valid addresses, regardless of whether IPv4 or IPv6 was used in the scope definition. Matching example: ```yaml annotations: scope.cascading.securecodebox.io/cidr: "10.10.0.0/16" diff --git a/docs/how-tos/scope.md b/docs/how-tos/scope.md index 1e934fd7..ca093201 100644 --- a/docs/how-tos/scope.md +++ b/docs/how-tos/scope.md @@ -134,11 +134,11 @@ When deploying your scanner, you can define `scopeLimiterAliases`. ```shell $ helm upgrade --install amass secureCodeBox/amass \ - --set parser.scopeLimiterAliases.hostname="{{attributes.name}}" + --set="parser.scopeLimiterAliases.hostname=\{\{attributes.name\}\}" Release "amass" has been upgraded. Happy Helming! [...] $ helm upgrade --install nmap secureCodeBox/nmap \ - --set parser.scopeLimiterAliases.hostname="{{attributes.hostname}}" + --set="parser.scopeLimiterAliases.hostname=\{\{attributes.hostname\}\}" Release "nmap" has been upgraded. Happy Helming! [...] ``` From c58b6951383187952dd134554ce71ec37d6a3743 Mon Sep 17 00:00:00 2001 From: Max Maass Date: Tue, 30 Nov 2021 18:25:06 +0100 Subject: [PATCH 13/13] Put howto titles in title case Signed-off-by: Max Maass --- docs/how-tos/scope.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/how-tos/scope.md b/docs/how-tos/scope.md index ca093201..9a978c6e 100644 --- a/docs/how-tos/scope.md +++ b/docs/how-tos/scope.md @@ -3,7 +3,7 @@ # # SPDX-License-Identifier: Apache-2.0 -title: "Enforcing engagement scope" +title: "Enforcing Engagement Scope" --- ## Introduction @@ -27,7 +27,7 @@ Release "nmap" does not exist. Installing it now. [...] ``` -## Start scan with scope limit +## Start Scan With Scope Limit Next, we can start creating our scan definition. Let's assume that we would like amass to scan `nmap.org` for subdomains, but we would only like to run nmap on `scanme.nmap.org`. @@ -85,7 +85,7 @@ Cascading Rule nmap-hostscan not triggered as scope limiter did not pass [...] ``` -## Handle differences in finding formats +## Handle Differences in Finding Formats In many cases, you are cascading to more than one scanner. Unfortunately, not every scanner has the same finding format, making a scope as defined above more tricky. @@ -99,7 +99,7 @@ This results in the scope rule failing, and prevents Nikto from getting cascaded To solve this situation, you have two options: -### Option 1: enable `validOnMissingRender` +### Option 1: Enable `validOnMissingRender` Enabling this option causes all defined rules which contain unresolved mustache templates to result in `true`. You can use this if you're sure that Nmap returns the valid hostname. @@ -127,7 +127,7 @@ spec: - "nmap.org" ``` -### Option 2: create a hostname alias for all deployed scanners +### Option 2: Create a Hostname Alias for All Deployed Scanners A more fool-proof solution is to ensure that the hostname field is available in the same place for each scanner. When deploying your scanner, you can define `scopeLimiterAliases`.