Skip to content

Known_Vulnerability_Rules

Johannes vom Dorp edited this page Jan 4, 2019 · 7 revisions

Known Vulnerability Rules

The known_vulnerabilities plugin is intended as a meta plugin to combine arbitrary analysis results into vulnerability definitions.

Combining two or more analysis results

As an example: Say we have a plugin to parse config files and find out we have a running ssh server with root login permission. Now another plugin finds that the root password is hardcoded an the hash was cracked. In combination this leads to a trivial root login backdoor, but in general the plugins don't share their results.

Pseudo code for such a vulnerability rule would look something like (config_plugin.ssh_root == open) && (password_plugin.passwords.root.exists). A similar rule can be created using the known_vulnerabilities plugin given the two plugins exist and create useable results.

🐍 The vulnerability definition works in python. The relevant file is the rulebook.py in the internal folder inside the plugin file tree.

Defining a vulnerability consists of two steps:

  1. Defining the rule, using results of other analysis plugins
  2. Adding meta information to the rule to describe the vulnerability

Step 1 can make use of three classes SingleRule, MetaRule and SubPathRule.

SingleRule

SingleRule is used to specify a condition regarding exactly one value. In the example above that would be either the config_plugin.ssh_root == open condition or the password_plugin.passwords.root.exists condition. SingleRules are initialized with three parameters:

  • value_path (config_plugin.ssh_root)
  • relation (equals)
  • comparison (open)

The suppported relations are: exists, equals, is, gt, lt, in, reverse_in and intersection. More on all relations can be read at the bottom.

The value_path is a dot separated path to an analysis result. Compare the advanced_search page for an insight into building a proper path. Note that the leading processed_analysis, which would be found in a database query is not considered here.

The comparison value specified the value, which is considered vulnerable or critical. For the relations in and intersection the value should be an iterable. In case relation is exists, the comparison value may be empty.

MetaRule

A MetaRule is used to combine two or more SingleRules. The instantiation requires two values: A list of SingleRule objects and a relation. The only applicable relations are any and all, directly corresponding to the python built-in functions of same name and meaning.

SubPathRule

The idea behind the SubPathRule is the occurrence of analysis results with dictionaries nested inside lists. SubPathRules are instantiated with two parameters, base_path and meta_rule. Consider this example, loosely based on how the ip_and_uri_finder plugin stores its data:

{
    'ip_plugin': {
        'timestamp': 1000000,
        'ip_v4': [
            {
                'address': '192.168.1.2',
                'location': [12345, -13131]
            },
            {
                'address': '192.168.178.1',
                'location': [51442, 31337]
            }
        ]
    }
}

Since the value of ip_v4 is a list, the address and location values cannot be addressed using the dot separated value paths. The SubPathRule allows to give a base path, in this case ip_plugin.ip_v4 combined with a SingleRule or MetaRule to then match inside the target field. Given the SingleRule ("address", "equals", "192.168.178.1"), each element in the ip results list is considered, evaluating to true on the second element.

Use yara pattern for detection

Alternatively you can simply write a yara rule for a given vulnerability if that's possible. The syntax is as follows:

rule NAME_OF_RULE
{
    meta:
        description = "short description"
        reliability = "range(0, 101)"
        score = "low / medium / high"
        link = "http://link.to.vulnerability.description/ or empty string"
    strings:
        $a = /REGULAR_EXPRESSION/ nocase ascii wide
    condition:
        $a
}

You can add a new rule by simply adding it to the vulnerabilities.yara file in the signatures folder inside the known_vulnerabilities plugin (src/plugins/analysis/known_vulnerabilities/signatures/vulnerabilities.yara).

⚠️ Note that if you don't intend to run the install script after adding a yara rule, you have to at least run the src/compile_yara_signatures.py script to update the compiled signatures. Otherwise changes or new rules will not take effect.

Relations

Some of the relations are self explanatory like gt (greater than), lt (less than), exists or intersection. For gt and lt note that the comparison is the second operand. I.e. ("ssl_version", "gt", 1) is true if the value of "ssl_version" is at least float(1.1). Intersection is true if there is an intersection between the target value and the comparison iterable. The rule checker will convert both iterable to a set.

Relations is and equals look equal but are not actually. In python the is operator will check on object equality by reference, not value. This means a string comparison of "hello world" is "hello world" would fail, as the operands describe two different objects with the same value. Using the equals, python == operator solves this issue. Here the value of two objects are compared, thus "hello world" == "hello world" resolves to true.

Finally in and reverse_in can be used when either a single value should be compared with a list of possible targets or the other way around. Consider ("found_cves", "in", "CVE-2018-00001"). This will be true if the iterable stored as result of "found_cves" contains "CVE-2018-00001". In reverse, consider ("software.lighttp.version", "reverse_in", ["vulnerable.version.1", "vulnerable.version.2"]). Now this will be true if the software analysis found lighttp in one of the two specified versions.