Skip to main content


ADR-0003: How can we introduce a mechanism to start specialized scans on the results of previous scans?

Author(s):Jannik Hollenbach, Robert Seedorff, Sven Strittmatter


Status Quo#

Currently scans by the secureCodeBox are single focused on a specific tool. Combining multiple scans requires manual or scripting by the user to use the results of a scan (e.g. Nmap) as a input for another scanner (e.g. SSLyze)

Problem and Question#

How can the results of a scan be used to automatically configure subsequent specialized scans for identified targets.

In general we want to describe cascading scans like:

+--------+             +--------+             +--------+| scan 1 |-- result -->| scan 2 |-- result -->| scan 3 |+--------+             +--------+       |     +--------+                                        |                                        |     +--------+                                        +---->| scan 4 |                                              +--------+

A concrete example:

+----------------+         +-----------------+               +-----------+|    <<nmap>>    |         |     <<nmap>>    |               |  <<SSL>>  || find all hosts |-- IP -->| find open ports |-- port 443 -->| check TLS |+----------------+         +-----------------+      |        +-----------+                                                    |                                                    |        +-------------+                                                    |        |  <<nikto>>  |                                                    +------->| check HTTPd |                                                             +-------------+

The solution should fulfill the following criteria:

  • The "rules" used to describe which subsequent scans can be executed should be modular, so that they can be packaged together with the scan types.
  • It should be possible for a user to select which scan rules should be applied
  • Protections should be in place to ensure that the clusters are not completely overwhelmed by these automatically created scans. Especially circular structures which create a infinite number of scans should be prevented.


It was decided to implement these rules as Custom Resource Definitions (CRDs) in Kubernetes. This allows the Helm Charts of the scanners to package related rules for the scanner together with their ScanTypes.

Defining CascadingRule#

The so called "CascadingRules" consist of a "matches" section which contains one or multiple rules which are compared against findings. When a finding matches a rule the "scanSpec" section will then be used to create a new scan. To customize the scan to match the finding, the [mustache]( templating language can be used to reference fields of the finding.

apiVersion: ""kind: CascadingRulemetadata:  name: "tls-scans"  labels:    # Described how "invasive" the scan is.    # Possible values: "invasive" or "non-invasive"    # CascadingRules are considered "invasive" when the Scan they start actively sends out packages with attack payloads. non-invasive    # Described the intensiveness level on a scanning and computational resource level.    # Possible values: "ligh", "medium", "intense"    # CascadingRules are considered more "intensive" when the Scan they start consumes lots of computational resources like RAM, CPU, or Network lightspec:  matches:    # CascadingRule triggers if a finding matches at least one of the anyOf matchers    # With the first version of this implementation only anyOf would be supported.    # If this turns out to be lacking and other operators (like `allOf` can be introduced without breaking changes)    anyOf:      # define an explicit "port" as finding and a given port number      - category: "Open Port"        attributes:          port: 443          service: "https"      # define an "port service" finding (any port)      - category: "Open Port"        attributes:          service: "https"  scanSpec:    name: "sslyze"    parameters: ["--regular", "{{attributes.hostname}}"]

Using CascadingRules#

By default no cascading Rules will be used.

# Nmap Scan without cascading rulesapiVersion: ""kind: Scanmetadata:  name: "portscan-berlin-wifi"  label:    office: berlin    vlan: wifispec:  name: "nmap"  parameters: ["-sV", ""]

To enable cascading rules you need to specify a label selector to select the cascading rules youโ€™d like

apiVersion: ""kind: Scanmetadata:  name: "portscan-berlin-wifi"  label:    office: berlin    vlan: wifispec:  cascades:    matchLabels:      # Uses all CascadingRules in the namespace which are labelled as "non-invasive" and a intensiveness level of "light" non-invasive light  name: "nmap"  parameters: ["-sV", ""]

To implicitly enable all cascading rules (not-recommended) a empty label selector can be used

apiVersion: ""kind: Scanmetadata:  name: "portscan-berlin-wifi"  label:    office: berlin    vlan: wifispec:  cascades:    # Uses all `CascadingRules` in the namespace    matchLabels: {}  name: "nmap"  parameters: ["-sV", ""]

The label selectors also allow the more powerful matchExpression selectors:

apiVersion: ""kind: Scanmetadata:  name: ""spec:  scanType: nmap  parameters:    - -p22,80,443    -  cascades:    # Using matchExpression instead of matchLabels    matchExpression:      key: ""      operator: In      # This select both light and medium intensity rules      values: [light, medium]