Simple tool to enumerate domains and IPs and test those domains and IPs for basic network and web security properties.
yesses provides a number of modules that each perform a certain task.
For example, the module discover Domains and IPs queries DNS servers
for IP addresses. Each module has a number of defined inputs (in this
case, for example, domain names) and outputs (e.g., IP addresses and
domain names expanded from CNAMEs). These outputs are called "findings".
Modules can be combined by feeding the findings of one module into the
input of another module. For example, the module discover Webservers
can use the domain names and IP addresses from discover Domains and IPs as inputs. This enables a dynamic scanning of infrastructures
without configuring every domain name, IP address, etc. manually.
After the execution of each module, alerts can be defined. Alerts can trigger when certain elements are contained (or are not contained) in the output of a module; alerts can also be triggered when — compared to the previous run of yesses — new elements appear in the output of a module.
Alerts are processed by one or more user-defined outputs. yesses comes with an HTML template output and Slack notification output.
Have a look at the example configuration file. yesses uses a fairly human-readable syntax; most things should be self-explanatory. If not, read on!
usage: run.py [-h] [--config [CONFIG]] [--verbose] [--resume] [--repeat N]
[--fresh] [--test] [--unittests] [--no-cache]
[--generate-readme [PATH]]
MODULE ...
Tool to scan for network and web security features
optional arguments:
-h, --help show this help message and exit
--config [CONFIG], -c [CONFIG]
Config file in yaml format. Required unless --test or
--generate-readme are used.
--verbose, -v Increase debug level to show debug messages.
--resume, -r Resume scanning from existing resumefile.
--repeat N Repeat last N steps of run (for debugging). Will
inhibit warnings of duplicate output variables.
--fresh, -f Do not use existing state files. Usage of this
required when datastructures in this application
changed.
--test Run a self-test. This executes the examples contained
in all modules.
--unittests Run all tests which are defined in /tests/test_cases.
--no-cache If '--unittests' is specified the test environment
will be rebuild from scratch.
--generate-readme [PATH]
Run a self-test (as above) and generate the file
README.md using the test results. Optional: path to
write file to, defaults to location of this script.
modules:
Run a module directly without configuration file. To get help on the usage
of a module, run this command with 'MODULE --help'. Remember that module
names must be in quotes or the space must be escaped.
MODULE Available modules: 'scan Dnssec', 'scan Header
Leakage', 'scan Information Leakage', 'scan Ports',
'scan TLS Settings', 'scan TLS Settings Qualys', 'scan
Web Security Settings', 'discover Domains And IPs',
'discover Error Paths', 'discover Hidden Paths',
'discover Linked Paths', 'discover TLS Certificates',
'discover Webservers'
A run of yesses consists of a call to one or more modules. A module, as described above, performs one or more checks. Each module accepts a custom set of input values and output values. The details for each module are described below.
There exists a global dictionary of facts, or findings which can
be used as input for other modules or to create alerts based on rules
on the findings. At the start of the run, the findings dictionary is
empty, but can be pre-filled with static data in the configuration
file, e.g., a list of domains to scan. When a module is called, input
values can be taken from the findings dictionary (using the use
keyword).
The module produces an output dictionary containing the module's own findings. Selected keys from this output dictionary can be merged into the global findings dictionary. (If necessary, the keys can be re-named before merging to avoid collisions.)
Rules can be defined on the new global findings dictionary to create alerts if necessary. Roughly speaking, these rules can check that (a) certain dictionary keys do or do not contain entries, (b) no values have been added or removed since the last run, or that (c) two lists of entries overlap fully or do not overlap at all.
When rules are violated, alerts can be created. Alerts can have four different severity levels. Alerts can then be used in the output of the run, either to create reports or for immediate notifications.
Data in the global findings list, and in inputs and outputs of
modules is loosely typed. This can be explained best using an example.
The following could be the global findings list after the discover Domains and IPs module was run:
DNS-Entries:
- domain: example.com
ip: 93.184.216.34
- domain: example.com
ip: 2606:2800:220:1:248:1893:25c8:1946
Domains:
- domain: example.com
IPs:
- ip: 93.184.216.34
- ip: 2606:2800:220:1:248:1893:25c8:1946
Under each key in the global findings list, a list of entries can be
found. Each entry contains one or more keys (domain and/or
ip). yesses expects that each member of a list contains the same
keys.
When a module expects an input having certain keys (which can be found
in the module description), inputs with additional keys can be used.
For example, the module scan Ports expects a range of IPs as input,
each entry having the key ip. Therefore, DNS-Entries or IPs
could be used as inputs for scan Ports. E.g., given the above global
findings list, the following would be valid:
- scan Ports:
ips: use DNS-Entries
(...)
An example for a configuration file can be found in docs/examples/example.yml.
yesses configuration files are YAML files (input and output values shown below and in the generated HTML files are shown in YAML syntax as well).
Configuration files should adhere to the following top-level structure:
data: # data: Predefined variables in the global findings list; can be used in the rest of the document
Variable-Name: # Custom variable name
- value: some-value # Custom variable values
- value: another-value
Another-Variable:
run: # run: List of steps to be run in each test
- discover Step Name: # Step names are documented below
step-specific: 42 # Variables here depend on the individual steps
find: # find: What output values to merge into the global findings list
- Finding1 as New-Var # rename output to something else before merging (avoid collisions)
- Finding2
expect: # expect: rules on the output to create alerts
- no New-Var, otherwise alert high
- some Finding2, otherwise alert medium
- scan Another Step:
some-value: use Finding2 and New-Var # re-use existing values from global findings
output: # output: one or more modules to create output
- Template: # output module name
filename: some-filename.html
template: templates/html/main.j2
datadata is self-explanatory given the example above: It contains keys
and respective values that make up the initial global findings list.
runrun contains the steps that are executed, in the order defined here,
within the yesses run. Each step is described using three keywords:
the step's identifier, find, and expect, as explained in the
following:
The step's identifier (like scan Ports or discover Domains and IPs). Valid keys can be found in the module description below. Under
this key, input values for the respective module are defined. The keys
that can be used here can be found in the module description. Each key
can either contain the literal input data (e.g.: protocols: ['tcp'],
see also the examples below) or a use-expression. These start with
the keyword use and contain on or more keys from the global findings
list (multiple keys are separated by "and"). Example: use DNS-Names and My-Arbitrary-Input.
find: This key defines which output names (see module
description) are merged into the global findings dictionary. Duplicate
names are not allowed, i.e., if a name already exists in the global
findings, an error message is shown. Keys can be renamed before
merging using an expression like Key-Name as New-Key-Name.
expect: This key defines the alerts triggered after the specific
step. Rules can refer to any entry in the global findings dictionary,
include the ones added by the step itself. Rules must adhere to one of the
following forms:
The first form checks if findings exist (or do not exist). With the
new keyword, it checks if, compared to the last run, additional
entries have been found. yesses does this by creating a file with the
extension .state that stores the findings of the last run. If this
file is deleted between runs, all findings will be reported as new.
The second form checks if there is some, no, or a complete overlap between the lists FINDINGS1 and FINDINGS2. Note that, if the entries in these list contain different set of keys, only keys common to both lists are matched.
The third form checks if the lists FINDINGS1 and FINDINGS2 contain the same elements (in any order) and no extra elements.
outputoutput defines what yesses does with the created alerts. See
below for a list of available modules
and their usage.
The following modules are currently provided by yesses. For each module, a short description in given plus a list of input and output fields. The field names can be used in the yaml configuration file.
scan DnssecUse the DNSSEC Scanner Python package to check the DNSSEC configuration of domain names. The DNSSEC Scanner provides log, warning and error messages for the DNSSEC validation process.
Configuration:
- scan Dnssec:
domains:
- domain: dnssec-deployment.org
find:
- DNSSEC-Logs-Domains
- DNSSEC-Warnings-Domains
- DNSSEC-Errors-Domains
- DNSSEC-Summary-Domains
- DNSSEC-Other-Error-Domains
Findings returned:
DNSSEC-Errors-Domains:
- domain: dnssec-deployment.org
errors: []
DNSSEC-Logs-Domains:
- domain: dnssec-deployment.org
logs:
- '. zone: KSK 20326 record validated, using DS 20326'
- '. zone: DNSKEY 20326,33853,48903 record validated, using KSK 20326'
- '. zone: org. DS 9795,9795 record validated, using ZSK 48903'
- 'org. zone: KSK 9795 record validated, using DS 9795'
- 'org. zone: DNSKEY 9795,17883,33209,37022 record validated, using KSK 9795'
- 'org. zone: DNSKEY 9795,17883,33209,37022 record validated, using KSK 17883'
- 'org. zone: DNSKEY 9795,17883,33209,37022 record validated, using ZSK 37022'
- 'org. zone: dnssec-deployment.org. DS 47809 record validated, using ZSK 37022'
- 'dnssec-deployment.org. zone: KSK 47809 record validated, using DS 47809'
- 'dnssec-deployment.org. zone: DNSKEY 25218,47809,50850 record validated, using
KSK 47809'
- 'dnssec-deployment.org. zone: dnssec-deployment.org. A record validated, using
ZSK 50850'
- 'dnssec-deployment.org. zone: dnssec-deployment.org. NS record validated, using
ZSK 50850'
- 'dnssec-deployment.org. zone: dnssec-deployment.org. SOA record validated, using
ZSK 50850'
- 'dnssec-deployment.org. zone: dnssec-deployment.org. MX record validated, using
ZSK 50850'
- 'dnssec-deployment.org. zone: dnssec-deployment.org. TXT record validated, using
ZSK 50850'
- 'dnssec-deployment.org. zone: dnssec-deployment.org. NSEC record validated, using
ZSK 50850'
- 'dnssec-deployment.org. zone: dnssec-deployment.org. AAAA record validated, using
ZSK 50850'
DNSSEC-Other-Error-Domains: []
DNSSEC-Summary-Domains:
- domain: dnssec-deployment.org
note: 'Found RR sets: A, NS, SOA, MX, TXT, NSEC, AAAA'
status: 0
DNSSEC-Warnings-Domains:
- domain: dnssec-deployment.org
warnings: []
| Name | Description | Required keys |
|---|---|---|
domains (required) | List of domain names to scan their DNSSEC configuration. | domain |
parallel_requests | Number of parallel DNSSEC scan commands to run. |
parallel_requests10
| Name | Description | Provided keys |
|---|---|---|
DNSSEC-Logs-Domains | Log messages for the verification process of each domain. | domain, logs |
DNSSEC-Warnings-Domains | Warning messages for the verification process of each domain. | domain, warnings |
DNSSEC-Errors-Domains | Error messages for the verification process of each domain. | domain, errors |
DNSSEC-Summary-Domains | DNSSEC status (0=SECURE|1=INSECURE|2=BOGUS) and a note for the found RR sets. | domain, status, note |
DNSSEC-Other-Error-Domains | Domains that could not be scan because fo some error. error contains the error description. | domain, error |
scan HeaderLeakageThis module searches for potentially sensitive much information in HTTP headers. It checks if the 'Server' attribute contains too much information and if the 'X-Powered-By' and/or the 'X-AspNet-Version' attribute is set.
| Name | Description | Required keys |
|---|---|---|
pages (required) | Required. URLs with headers to search for information leakage. | url, header |
| Name | Description | Provided keys |
|---|---|---|
Leakages | Potential information leakages. | url, header |
scan InformationLeakageScan HTML, JavaScript and CSS files for information leakages. This is done by a search with regular expressions for email and IP addresses and strings that look like paths in the visible text of a HTML site or in HTML, JavaScript and CSS comments. For paths, there is also a list of common directories to determine whether a path is a real path or not. Furthermore, there is a list with common file endings to check if a path ends with a file name or a string is a file name. All the regex expressions are searching only for strings that are either at the beginning or end of a line or which have whitespace before or after.
Configuration:
- scan Information Leakage:
pages:
- url: page0
data: "<!-- [email protected] /var/home/bla aaa --><html>
<head><script src='ajkldfjalk'></script></head>
<body>
<!-- This is a comment --><h1>Title</h1>
<!-- secret.txt
/1x23/ex234--><p>Text with path /home/user/secret/key.pub</p> <a href='/docs/'>Website</a> <label>192.168.2.196 /usr/share/docs/ajdlkf/adjfl</label>
<style> [email protected] </style>
</body>"
- url: page1
data: "<html><script>// This is a js comment192.256.170.128
function {return 'Hello World';}
</script><body><p>bla Gitea Version: 1.11.0+dev-180-gd5b1e6bc5</p></body><script>// Comment two with [email protected]
console.log('test')/* Comment over
several lines
*/</script></html>
"
- url: page2
data: "/*! modernizr 3.6.0 (Custom Build) | MIT *
* https://modernizr.com/download/?-svgclippaths-setclasses !*/
!function(e,n,s){function o(e) // Comment three
{var n=f.className,s=Modernizr._con /* Last
multi
line
comment */ flakjdlfjldjfl
"
search_regex:
- type: new_regex
regex: (^|\s)a{3}(\s|$)
find:
- Leakages
Findings returned:
Leakages:
- finding: 192.168.2.196
found: visible_text
type: ip
url: page0
- finding: /home/user/secret/key.pub
found: visible_text
type: path
url: page0
- finding: /usr/share/docs/ajdlkf/adjfl
found: visible_text
type: path
url: page0
- finding: [email protected]
found: html_comment
type: email
url: page0
- finding: /var/home/bla
found: html_comment
type: path
url: page0
- finding: aaa
found: html_comment
type: new_regex
url: page0
- finding: secret.txt
found: html_comment
type: file
url: page0
- finding: 'Version: 1.11.0'
found: visible_text
type: version-info
url: page1
| Name | Description | Required keys |
|---|---|---|
pages (required) | Required. Pages to search for information leakage. | url, data |
search_regex | Own regular expression to search in pages (will be added to the existing ones). | type, regex |
dir_list | List with common directories to determine whether a string is a path. | |
file_ending_list | List with common file endings to determine whether a string is a file name. |
search_regex{}
dir_listassets/information_leakage/common-directories.txt
file_ending_listassets/information_leakage/common-file-endings.txt
| Name | Description | Provided keys |
|---|---|---|
Leakages | Potential information leakages | url, type, found, finding |
scan PortsUses nmap to scan for open ports.
Configuration:
- scan Ports:
ips:
- ip: '8.8.8.8'
protocols: ['tcp']
find:
- Host-Ports
- HTTPS-Ports
- Other-Port-IPs
expect:
- no Host-Ports, otherwise alert high
Findings returned:
HTTPS-Ports:
- &id001
ip: 8.8.8.8
port: 443
protocol: tcp
Host-Ports:
- ip: 8.8.8.8
port: 53
protocol: tcp
- *id001
Other-Port-IPs:
- ip: 8.8.8.8
Alerts created (details hidden for brevity):
| Severity | Rule | #Findings |
|---|---|---|
| AlertSeverity.HIGH | no Host-Ports, otherwise alert high | 1 |
| Name | Description | Required keys |
|---|---|---|
ips (required) | Required. IP range to scan (e.g., use IPs). | ip |
protocols | List of protocols (udp, tcp,...) in nmap's notations to scan. | |
ports | Port range in nmap notation (e.g., '22,80,443-445'); default (None): 1000 most common ports as defined by nmap. | |
named_ports | A mapping of names to ports. This can be used to control the output of this module. | name, port |
protocol_arguments | Command-line arguments to provide to nmap when scanning for a specific protocol. | protocol, arguments |
protocols- tcp
portsnull
named_ports- name: SSH
port: 22
- name: HTTP
port: 80
- name: HTTPS
port: 443
protocol_arguments- arguments: -sU
protocol: udp
- arguments: -sT
protocol: tcp
| Name | Description | Provided keys |
|---|---|---|
Host-Ports | Each open port on a scanned IP (with IP, protocol, and port). | ip, protocol, port |
*-Ports | For certain protocols (SSH, HTTP, HTTPS), a list of hosts that have this port open (with IP, protocol, and port). | ip, protocol, port |
Other-Port-IPs | List of IPs that have any other ports open. |
scan TLSSettingsUses the sslyze library to scan a webserver's TLS configuration and compare it to the Mozilla TLS configuration profiles.
Configuration:
- scan TLS Settings:
domains:
- domain: mozilla-intermediate.badssl.com
tls_profile: intermediate
find:
- TLS-Profile-Mismatch-Domains
- TLS-Validation-Fail-Domains
- TLS-Certificate-Warnings-Domains
- TLS-Vulnerability-Domains
- TLS-Okay-Domains
- TLS-Other-Error-Domains
expect:
- some TLS-Okay-Domains, otherwise alert medium
Findings returned:
TLS-Certificate-Warnings-Domains: []
TLS-Okay-Domains: []
TLS-Other-Error-Domains: []
TLS-Profile-Mismatch-Domains:
- domain: mozilla-intermediate.badssl.com
errors:
- must not support TLSv1
- must not support TLSv1.1
- must support TLSv1.3
- client must choose the cipher suite, not the server (Protocol TLSv1)
- client must choose the cipher suite, not the server (Protocol TLSv1.1)
- client must choose the cipher suite, not the server (Protocol TLSv1.2)
- must not support ECDHE-RSA-AES128-SHA
- must not support AES256-SHA
- must not support AES256-GCM-SHA384
- must not support ECDHE-RSA-AES128-SHA256
- must not support DES-CBC3-SHA
- must not support ECDHE-RSA-DES-CBC3-SHA
- must not support DHE-RSA-AES128-SHA256
- must not support DHE-RSA-DES-CBC3-SHA
- must not support DHE-RSA-AES256-SHA
- must not support EDH-RSA-DES-CBC3-SHA
- must not support AES128-SHA256
- must not support AES128-GCM-SHA256
- must not support ECDHE-RSA-AES256-SHA
- must not support DHE-RSA-AES128-SHA
- must not support AES128-SHA
- must not support ECDHE-RSA-AES256-SHA384
- must not support AES256-SHA256
- must not support DHE-RSA-AES256-SHA256
- must support TLS_AES_128_GCM_SHA256
- must support ECDHE-RSA-CHACHA20-POLY1305
- must support TLS_AES_256_GCM_SHA384
- must support TLS_CHACHA20_POLY1305_SHA256
- HSTS header not set
- certificate lifespan too long (is 785, should be less than 730)
- OCSP stapling must be supported
TLS-Validation-Fail-Domains: []
TLS-Vulnerability-Domains: []
Alerts created (details hidden for brevity):
| Severity | Rule | #Findings |
|---|---|---|
| AlertSeverity.MEDIUM | some TLS-Okay-Domains, otherwise alert medium | 0 |
| Name | Description | Required keys |
|---|---|---|
domains (required) | List of domain names to scan. | domain |
tls_profile | The Mozilla TLS profile to test against (old, intermediate, or modern). | |
ca_file | Path to a trusted custom root certificates |
Content type
Image
Digest
Size
105.1 MB
Last updated
over 6 years ago
docker pull danielfett/yesses