ADR-0003: How can we introduce a mechanism to start specialized scans on the results of previous scans?
Status: | ACCEPTED |
Date: | 2020-05-20 |
Author(s): | Jannik Hollenbach Jannik.Hollenbach@iteratec.com, Robert Seedorff Robert.Seedorff@iteratec.com, Sven Strittmatter Sven.Strittmatter@iteratec.com |
Context
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.
Decision
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](https://github.com/janl/mustache.js) templating language can be used to reference fields of the finding.
apiVersion: "cascading.securecodebox.io/v1"
kind: CascadingRule
metadata:
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.
securecodebox.io/invasive: 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
securecodebox.io/intensive: light
spec:
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 rules
apiVersion: "execution.securecodebox.io/v1"
kind: Scan
metadata:
name: "portscan-berlin-wifi"
label:
office: berlin
vlan: wifi
spec:
name: "nmap"
parameters: ["-sV", "10.42.0.0/16"]
To enable cascading rules you need to specify a label selector to select the cascading rules you’d like
apiVersion: "execution.securecodebox.io/v1"
kind: Scan
metadata:
name: "portscan-berlin-wifi"
label:
office: berlin
vlan: wifi
spec:
cascades:
matchLabels:
# Uses all CascadingRules in the namespace which are labelled as "non-invasive" and a intensiveness level of "light"
securecodebox.io/invasive: non-invasive
securecodebox.io/intensive: light
name: "nmap"
parameters: ["-sV", "10.42.0.0/16"]
To implicitly enable all cascading rules (not-recommended) a empty label selector can be used
apiVersion: "execution.securecodebox.io/v1"
kind: Scan
metadata:
name: "portscan-berlin-wifi"
label:
office: berlin
vlan: wifi
spec:
cascades:
# Uses all `CascadingRules` in the namespace
matchLabels: {}
name: "nmap"
parameters: ["-sV", "10.42.0.0/16"]
The label selectors also allow the more powerful matchExpression selectors:
apiVersion: "execution.securecodebox.io/v1"
kind: Scan
metadata:
name: "example.com"
spec:
scanType: nmap
parameters:
- -p22,80,443
- example.com
cascades:
# Using matchExpression instead of matchLabels
matchExpression:
key: "securecodebox.io/intensive"
operator: In
# This select both light and medium intensity rules
values: [light, medium]