Ejemplo n.º 1
0
    def __load_alert_ids(self):
        """
        Parses each rule file to extract the relevant Identifiers, actions, headers and pre-build a matching string.

        :return rules: Dictionary containing parsed Snort rules from configured rules files.
        """
        rules = {}

        for i in self._config.rule_list:
            # uses IDS tools library to extract rules
            rule_file = rule.parse_file(i)
            for x in rule_file:
                if x.enabled:
                    rules[x.sid] = {}
                    rules[x.sid]['sid'] = x.sid
                    rules[x.sid]['gid'] = x.gid
                    rules[x.sid]['rev'] = x.rev
                    rules[x.sid]['logmatch'] = "{0}:{1}:{2}".format(
                        str(x.gid), str(x.sid), str(x.rev))
                    rules[x.sid]['action'] = x.action
                    rules[x.sid]['header'] = x.header

        self._logger.info(
            "Extracted {0} rules from the Snort configuration.".format(
                str(len(rules))))

        return rules
Ejemplo n.º 2
0
def test_signature_content(base_path):
    errors = []
    # Parse signature using idstools
    rule_files = glob(os.path.join(base_path, '*/*.rules'))
    rules = {}
    rule_ids = {}
    # Parse the rules:
    for rule_file in rule_files:
        try:
            parsed_rulefile = rule.parse_file(rule_file)
            if not parsed_rulefile:
                errors.append('Rule file %s failed to parse/is blank' %
                              rule_file)
                continue
            rules[rule_file] = parsed_rulefile
        except:
            errors.append('Parsing error on %s' % rule_file)
    for rname, ruleset in rules.items():
        for r in ruleset:
            # check if msg name contains MONA
            if not r.get('msg', '').startswith('MONA - '):
                errors.append('on %s msg doesn\'t start with MONA - ' % rname)
            if 'sid' not in r:
                errors.append('No SID defined on %s' % rname)
                r['sid'] = 0
            if not r['sid'] >= 8000000 and r['sid'] < 9000000:
                errors.append('Invalid signature id on %s' % rname)
            if r['sid'] in rule_ids:
                errors.append('Duplicate SID: %s on %s and %s' %
                              (r['sid'], rule_ids[r['sid']], rname))
            else:
                rule_ids[r['sid']] = rname
    return errors
Ejemplo n.º 3
0
def extract_groups_from(input_file, use_supercats, limit):
    rules = rule.parse_file(input_file)
    groups = GroupClassifier(use_supercats)
    count = 0

    for snort_rule in rules:
        if count > limit:
            break
        header = snort_rule.header.split(" ")
        if "pcre" not in snort_rule:
            # Don't care about the non regex rules.
            continue
        # This function reformats the PCRE
        pcre = is_valid_pcre(snort_rule.pcre)
        if not pcre:
            global not_valid
            not_valid += 1
            # Not a supported PCRE, don't translate
            continue

        if header[1] in SUPPORTED_PROTOCOLS:
            proto = header[1]
        else:
            print("Type " + header[1] + " not recognized")
            proto = "all"

        src_ips = header[2]
        src_ips_type = None
        if src_ips in SUPPORTED_IP_CLASSES:
            src_ips_type = src_ips
        else:
            print("Unrecognized src IPs type: " + src_ips)
            src_ips_type = "any"

        src_ports = header[3]
        dst_ports = header[6]

        if ":" in src_ports or ":" in dst_ports or "," in src_ports or "," in dst_ports or "[" in src_ports or "[" in dst_ports:
            continue

        # TODO --- Do something about ports, which generally
        # have a wider range...

        groups.add(proto, src_ips_type, src_ports, dst_ports,
                   format_pcre(pcre))
        count += 1

    print("Number of rules omitted due to unsupported features is" +
          str(not_valid))
    return groups
Ejemplo n.º 4
0
    def __load_alert_ids(self):
        """
        Parses each rule file to extract the relevant Identifiers, actions, headers and pre-build a matching string.

        :return rules: Dictionary containing parsed Snort rules from configured rules files.
        """
        rules = {}

        for i in self._config.rule_list:
            # uses IDS tools library to extract rules
            rule_file = rule.parse_file(i)
            for x in rule_file:
                if x.enabled:
                    rules[x.sid] = {}
                    rules[x.sid]['sid'] = x.sid
                    rules[x.sid]['gid'] = x.gid
                    rules[x.sid]['rev'] = x.rev
                    rules[x.sid]['logmatch'] = "{0}:{1}:{2}".format(str(x.gid), str(x.sid), str(x.rev))
                    rules[x.sid]['action'] = x.action
                    rules[x.sid]['header'] = x.header

        self._logger.info("Extracted {0} rules from the Snort configuration.".format(str(len(rules))))

        return rules
Ejemplo n.º 5
0
#! /usr/bin/env python
#
# Rule File Parsing Example

import sys

from idstools import rule

# For each rule in a rule file, print:
#     [GENERATOR_ID:SIGNATURE_ID:REVISION] RULE_MSG
for rule in rule.parse_file(sys.argv[1]):
    print("[%d:%d:%d] %s" % (
        rule.gid, rule.sid, rule.rev, rule.msg))
    
Ejemplo n.º 6
0
#! /usr/bin/env python
#
# Rule File Parsing Example

import sys

from idstools import rule

# For each rule in a rule file, print:
#     [GENERATOR_ID:SIGNATURE_ID:REVISION] RULE_MSG
for rule in rule.parse_file(sys.argv[1]):
    print("[%d:%d:%d] %s" % (rule.gid, rule.sid, rule.rev, rule.msg))
Ejemplo n.º 7
0
def main():

    module = AnsibleModule(argument_spec=dict(
        rule=dict(required=True, default=None),
        state=dict(choices=['present', 'absent'], required=True),
        rules_file=dict(required=False,
                        default='/etc/snort/rules/ansible_managed.rules'),
    ),
                           supports_check_mode=True)

    matched_rules = [
        snort_rule
        for snort_rule in rule.parse_file(module.params['rules_file'])
        if to_text(snort_rule) == to_text(rule.parse(module.params['rule']))
    ]
    rule_found = True if matched_rules else False

    if module.params['state'] == 'present' and rule_found:
        module.exit_json(
            msg="Rule '{}' already present in rules_file {}".format(
                module.params['rule'], module.params['rules_file']),
            changed=False)
    elif module.params['state'] == 'present' and not rule_found:
        if module.check_mode:
            module.exit_json(
                msg="Rule '{}' would be added to rules_file {}".format(
                    module.params['rule'], module.params['rules_file']),
                changed=True)

        with open(module.params['rules_file'], 'a') as rules_file:
            rules_file.write(to_text(rule.parse(module.params['rule'])))

        module.exit_json(msg="Rule '{}' added to rules_file {}".format(
            module.params['rule'], module.params['rules_file']),
                         changed=True)

    if module.params['state'] == 'absent' and not rule_found:
        module.exit_json(
            msg="Rule '{}' does not exist in rules_file {}".format(
                module.params['rule'], module.params['rules_file']),
            changed=False)
    elif module.params['state'] == 'absent' and rule_found:
        orig_file_contents = []
        with open(module.params['rules_file'], 'r') as rules_file:
            orig_file_contents = rules_file.readlines()

        new_file_contents = [
            line for line in orig_file_contents
            if rule.parse(module.params['rule']) != rule.parse(line)
        ]

        if module.check_mode:
            if len(orig_file_contents) != len(new_file_contents):
                module.exit_json(
                    msg="Rule '{}' would have been removed from rules_file {}".
                    format(module.params['rule'], module.params['rules_file']),
                    changed=True)

        with open(module.params['rules_file'], 'w') as rules_file:
            for line in new_file_contents:
                rules_file.write(line)

        module.exit_json(
            msg="Rule '{}' has been removed from rules_file {}".format(
                module.params['rule'], module.params['rules_file']),
            changed=True)
Ejemplo n.º 8
0
    for content in contents.split("|"):
        if len(content) == 0: continue
        m = re.match(r'(\d\d ?)+', content)
        if m: out_content.append({"t": "bytes", "c": m.group(0)})
        else:
            m = re.match(r'\d+', content)
            if m: out_content.append({"t": "decimal", "c": m.group(0)})
            else: out_content.append({"t": "string", "c": content})
    return out_content


def parse_addresses(r):
    m = re.match(r'\S+ \S+ (\S+) (\S+) (->|<-) (\S+) (\S+)', r.raw)
    if not m: return {}
    else:
        return {
            "local_network": m.group(1),
            "local_port": m.group(2),
            "remote_network": m.group(4),
            "remote_port": m.group(5)
        }


rules = []
for r in rule.parse_file(rules_file)[:10]:
    out_rule = {"msg": r.msg, "action": r.action, "content": parse_content(r)}
    out_rule.update(parse_addresses(r))
    rules.append(out_rule)

with open(output_file, "w") as f:
    json.dump({"rules": rules}, f)
Ejemplo n.º 9
0
# Author: Naveen Mukundan Ravindran

import sys

# Your system should have installed idstools from Python 3 packages. Check the description for how to install it.
from idstools import rule

# Download the latest snort rules from the website provided in the description
filename = "snort3-community.rules"

for rule in rule.parse_file(filename):

    # Print the Action of the rule
    print("Action: %s" % rule.action)

    # Print the Message Contents of the rule
    print("Message: %s" % rule.msg)

    # Print the Generator ID of the rule
    print("Generator id: %d" % rule.gid)

    # Print the Snort Rule ID of the rule
    print("Rule id: %d" % rule.sid)

    # Print the Revision Integer of the rule
    print("Revision Integer: %d" % rule.rev)

    # Print the Class type of the rule
    print("Class Type: %s" % rule.classtype)

    # Print the Priority Integer of the rule
Ejemplo n.º 10
0
def main():

    module = AnsibleModule(argument_spec=dict(
        rule=dict(required=True, default=None),
        state=dict(choices=['present', 'absent'], required=True),
        rules_file=dict(required=False,
                        default='/etc/snort/rules/ansible_managed.rules'),
    ),
                           supports_check_mode=True)

    if not HAS_IDSTOOLS:
        module.fail_json(
            msg=
            "Python module idstools not found on host, but is required for snort_rule Ansible module"
        )

    try:
        matched_rules = [
            snort_rule
            for snort_rule in rule.parse_file(module.params['rules_file']) if
            to_text(snort_rule) == to_text(rule.parse(module.params['rule']))
        ]
    except IOError:
        module.fail_json(
            msg=
            "rule file {} not found or permission was denied attempting access it"
            .format(module.params['rules_file']))
    rule_found = True if matched_rules else False

    sigmap = maps.SignatureMap()
    try:
        sigmap.load_generator_map(open(GENMAP_FILE, 'r'))
    except IOError:
        module.fail_json(
            msg=
            "generator file {} not found or permission was denied attempting to access it"
            .format(GENMAP_FILE))
    try:
        sigmap.load_signature_map(open(SIGMAP_FILE, 'r'))
    except IOError:
        module.fail_json(
            msg=
            "signature file {} not found or permission was denied attempting to access it"
            .format(SIGMAP_FILE))

    if module.params['state'] == 'present' and rule_found:
        module.exit_json(
            msg="Rule '{}' already present in rules_file {}".format(
                module.params['rule'], module.params['rules_file']),
            changed=False)
    elif module.params['state'] == 'present' and not rule_found:
        if module.check_mode:
            module.exit_json(
                msg="Rule '{}' would be added to rules_file {}".format(
                    module.params['rule'], module.params['rules_file']),
                changed=True)

        new_snort_rule = rule.parse(module.params['rule'])

        with open(module.params['rules_file'], 'a') as rules_file:
            rules_file.write(to_text("\n{}".format(new_snort_rule)))

        with open(SIGMAP_FILE, 'a') as sigmap_file:
            if "ref" in new_snort_rule and len(new_snort_rule["ref"]) > 0:
                sigmap_file.write(
                    to_text("\n{} || {} || {}".format(
                        new_snort_rule['sid'], new_snort_rule['msg'],
                        " || ".join(new_snort_rule['ref']))))
            else:
                sigmap_file.write(
                    to_text("\n{} || {}".format(new_snort_rule['sid'],
                                                new_snort_rule['msg'])))

        module.exit_json(msg="Rule '{}' added to rules_file {}".format(
            module.params['rule'], module.params['rules_file']),
                         changed=True)

    if module.params['state'] == 'absent' and not rule_found:
        module.exit_json(
            msg="Rule '{}' does not exist in rules_file {}".format(
                module.params['rule'], module.params['rules_file']),
            changed=False)
    elif module.params['state'] == 'absent' and rule_found:
        new_snort_rule = rule.parse(module.params['rule'])

        changed = False

        orig_rulefile_contents = []
        orig_sigmapfile_contents = []
        new_rulefile_contents = []
        new_sigmapfile_contents = []
        with open(module.params['rules_file'], 'r') as rules_file:
            orig_rulefile_contents = rules_file.readlines()
        with open(SIGMAP_FILE, 'r') as sigmap_file:
            orig_sigmapfile_contents = sigmap_file.readlines()

        new_rulefile_contents = [
            line for line in orig_rulefile_contents
            if new_snort_rule != rule.parse(line)
        ]

        if "ref" in new_snort_rule and len(new_snort_rule["ref"]) > 0:
            new_sigmapfile_contents = [
                line for line in orig_sigmapfile_contents
                if "{} || {} || {}".format(
                    new_snort_rule['sid'], new_snort_rule['msg'], ' || '.join(
                        new_snort_rule['ref'])) != line.strip()
            ]
        else:
            new_sigmapfile_contents = [
                line for line in orig_sigmapfile_contents
                if "{} || {}".format(new_snort_rule['sid'],
                                     new_snort_rule['msg']) != line.strip()
            ]

        if module.check_mode:
            if len(orig_rulefile_contents) != len(new_rulefile_contents):
                module.exit_json(
                    msg="Rule '{}' would have been removed from rules_file {}".
                    format(module.params['rule'], module.params['rules_file']),
                    changed=True)

        if len(orig_rulefile_contents) != len(new_rulefile_contents):
            changed = True
            with open(module.params['rules_file'], 'w') as rules_file:
                for line in new_rulefile_contents:
                    rules_file.write(line)

        if new_sigmapfile_contents and (len(orig_sigmapfile_contents) !=
                                        len(new_sigmapfile_contents)):
            changed = True
            with open(SIGMAP_FILE, 'w') as sigmap_file:
                for line in new_sigmapfile_contents:
                    sigmap_file.write(line)

        module.exit_json(
            msg="Rule '{}' has been removed from rules_file {}".format(
                module.params['rule'], module.params['rules_file']),
            changed=changed)