forked from fzipi/secrules-parser
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmodsec.py
executable file
·88 lines (71 loc) · 2.9 KB
/
modsec.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#!/usr/bin/env python
""""
ModSecurity CRS Parser
-----------------------------------------------
Copyright (C) 2017 Felipe Zipitria <[email protected]>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License, either
version 3, or (at your option), any later version.
"""
import os
import glob
import pprint
import argparse
from textx.metamodel import metamodel_from_file
from textx.exceptions import TextXSyntaxError
import yaml
import jsonpickle
import json
# Parse Arguments
cmdline = argparse.ArgumentParser(description='ModSecurity CRS parser script.')
cmdline.add_argument('-v', '--verbose', help='Print verbose messages', action="store_true")
cmdline.add_argument('-d', '--debug', help='You don\'t want to do this!', action="store_true")
cmdline.add_argument('-f', '--files', type=str, help='Parse these files')
args = cmdline.parse_args()
def secrule_id_processor(rule):
""" Processor for each rule, if neeeded """
# print "secrule_id_processor_called"
# print(rule)
def debug_rule(rule):
""" Don't use this unless you want to wait and read too much """
serialized = jsonpickle.encode(rule)
print yaml.dump(yaml.load(serialized), indent=2)
def get_rule_id(rule):
""" Gets rule ID. Only for SecAction or SecRule """
if rule.__class__.__name__ == "SecRule" or rule.__class__.__name__ == "SecAction":
for action in rule.actions:
if action.id:
return action.id
return 0
def print_rule(rule):
""" This is just for printing something until we see the real capabilities of this parser """
if rule.__class__.__name__ == "SecRule":
for variable in rule.variables:
if variable.collection == "TX" and variable.collectionArg == "PARANOIA_LEVEL":
print "[One-liner Paranoia level Rule, id {}]".format(get_rule_id(rule))
for action in rule.actions:
if action.id:
print "* Rule id = {}".format(action.id)
if action.chain:
print "* > This is a chained rule from the above.".format(action.id)
# Load Meta-Model
modsec_mm = metamodel_from_file('modsec.tx', memoization=True)
# Register test processor
modsec_mm.register_obj_processors({'SecRule': secrule_id_processor})
# files is a glob pattern
files = args.files if args.files else 'owasp-modsecurity-crs/rules/*.conf'
for rules in glob.glob(files):
if args.verbose:
print 'Processing file %s:' % rules
try:
model = modsec_mm.model_from_file(rules)
if args.verbose:
for rule in model.rules:
print_rule(rule)
if args.debug:
for rule in model.rules:
debug_rule(rule)
if model.rules:
print "Syntax OK: {}".format(rules)
except TextXSyntaxError as e:
print "Syntax error in line {}, col {}: {}".format(e.line, e.col, e.message)