Sign inSign up

danielfett/yesses

By danielfett

•Updated over 6 years ago

Image
0

253

danielfett/yesses repository overview

⁠yesses

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.

⁠TL;DR

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!

⁠Table of Contents

⁠Usage

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'

⁠Concepts

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
      (...)

⁠Configuration file

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
      
⁠data

data is self-explanatory given the example above: It contains keys and respective values that make up the initial global findings list.

⁠run

run 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:

  1. (no|some) [new] FINDINGS, otherwise alert (informative|medium|high|very high)
  2. (no|some|all) FINDINGS1 in FINDINGS2, otherwise alert (informative|medium|high|very high)
  3. FINDINGS1 [not] equals FINDINGS2, otherwise alert (informative|medium|high|very high)

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.

⁠output

output defines what yesses does with the created alerts. See below⁠ for a list of available modules and their usage.

⁠Discovery and Scanning Modules

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 Dnssec

Use 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.

⁠Examples
show example(s)
⁠Check DNSSEC configuration of dnssec-deployment.org

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: []

⁠Inputs
NameDescriptionRequired keys
domains (required)List of domain names to scan their DNSSEC configuration.domain
parallel_requestsNumber of parallel DNSSEC scan commands to run.
⁠Default for parallel_requests
10
⁠Outputs
NameDescriptionProvided keys
DNSSEC-Logs-DomainsLog messages for the verification process of each domain.domain, logs
DNSSEC-Warnings-DomainsWarning messages for the verification process of each domain.domain, warnings
DNSSEC-Errors-DomainsError messages for the verification process of each domain.domain, errors
DNSSEC-Summary-DomainsDNSSEC status (0=SECURE|1=INSECURE|2=BOGUS) and a note for the found RR sets.domain, status, note
DNSSEC-Other-Error-DomainsDomains that could not be scan because fo some error. error contains the error description.domain, error

⁠scan HeaderLeakage

This 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.

⁠Inputs
NameDescriptionRequired keys
pages (required)Required. URLs with headers to search for information leakage.url, header
⁠Outputs
NameDescriptionProvided keys
LeakagesPotential information leakages.url, header

⁠scan InformationLeakage

Scan 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.

⁠Examples
show example(s)
⁠Check example strings for information leakage

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

⁠Inputs
NameDescriptionRequired keys
pages (required)Required. Pages to search for information leakage.url, data
search_regexOwn regular expression to search in pages (will be added to the existing ones).type, regex
dir_listList with common directories to determine whether a string is a path.
file_ending_listList with common file endings to determine whether a string is a file name.
⁠Default for search_regex
{}
⁠Default for dir_list
assets/information_leakage/common-directories.txt
⁠Default for file_ending_list
assets/information_leakage/common-file-endings.txt
⁠Outputs
NameDescriptionProvided keys
LeakagesPotential information leakagesurl, type, found, finding

⁠scan Ports

Uses nmap to scan for open ports.

⁠Examples
show example(s)
⁠scan ports on Google DNS server

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):

SeverityRule#Findings
AlertSeverity.HIGHno Host-Ports, otherwise alert high1
⁠Inputs
NameDescriptionRequired keys
ips (required)Required. IP range to scan (e.g., use IPs).ip
protocolsList of protocols (udp, tcp,...) in nmap's notations to scan.
portsPort range in nmap notation (e.g., '22,80,443-445'); default (None): 1000 most common ports as defined by nmap.
named_portsA mapping of names to ports. This can be used to control the output of this module.name, port
protocol_argumentsCommand-line arguments to provide to nmap when scanning for a specific protocol.protocol, arguments
⁠Default for protocols
- tcp
⁠Default for ports
null
⁠Default for named_ports
- name: SSH
  port: 22
- name: HTTP
  port: 80
- name: HTTPS
  port: 443
⁠Default for protocol_arguments
- arguments: -sU
  protocol: udp
- arguments: -sT
  protocol: tcp
⁠Outputs
NameDescriptionProvided keys
Host-PortsEach open port on a scanned IP (with IP, protocol, and port).ip, protocol, port
*-PortsFor certain protocols (SSH, HTTP, HTTPS), a list of hosts that have this port open (with IP, protocol, and port).ip, protocol, port
Other-Port-IPsList of IPs that have any other ports open.

⁠scan TLSSettings

Uses the sslyze library to scan a webserver's TLS configuration and compare it to the Mozilla TLS configuration profiles.

⁠Examples
show example(s)
⁠Check TLS settings on badssl.com

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):

SeverityRule#Findings
AlertSeverity.MEDIUMsome TLS-Okay-Domains, otherwise alert medium0
⁠Inputs
NameDescriptionRequired keys
domains (required)List of domain names to scan.domain
tls_profileThe Mozilla TLS profile to test against (old, intermediate, or modern).
ca_filePath to a trusted custom root certificates

Tag summary

Content type

Image

Digest

Size

105.1 MB

Last updated

over 6 years ago

docker pull danielfett/yesses