├── .gitignore ├── QRadar-rules2csv.py ├── QRadar-rules2html.py └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .coverage.* 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | *,cover 45 | 46 | # Translations 47 | *.mo 48 | *.pot 49 | 50 | # Django stuff: 51 | *.log 52 | 53 | # Sphinx documentation 54 | docs/_build/ 55 | 56 | # PyBuilder 57 | target/ 58 | -------------------------------------------------------------------------------- /QRadar-rules2csv.py: -------------------------------------------------------------------------------- 1 | # python3 script 2 | import sys, os 3 | import json, time 4 | from xml.etree.ElementTree import ElementTree 5 | import xml.etree.ElementTree as ET 6 | import base64 7 | import lxml.etree as etree 8 | 9 | from array import array 10 | from types import * 11 | from html.parser import HTMLParser 12 | from optparse import OptionParser 13 | 14 | import pprint 15 | 16 | class MyHTMLParser(HTMLParser): 17 | 18 | def __init__(self): 19 | HTMLParser.__init__(self) 20 | self.recording = 0 21 | self.data = [] 22 | self.test = [] 23 | 24 | def handle_starttag(self, tag, attrs): 25 | self.recording = 1 26 | self.data='' 27 | 28 | def handle_endtag(self, tag): 29 | self.recording -= 1 30 | 31 | def handle_data(self, data): 32 | self.testArray.append([testSeq,self.recording,data]) 33 | 34 | def main(): 35 | tree = ET.parse(sys.argv[1]) 36 | root = tree.getroot() 37 | rule = [] 38 | htmlout=[] 39 | 40 | global testSeq 41 | 42 | for rule in root.findall('custom_rule'): 43 | fullTestArray=[] 44 | htmlTestArray=[] 45 | htmlRuleDef=[] 46 | parser = MyHTMLParser() 47 | htmlGroupArray=[] 48 | 49 | ruleUUID=rule.find('uuid').text 50 | ruleID=rule.find('id').text 51 | fgroupGet="fgroup_link[id='"+ruleID+"']" 52 | fgroupGet="fgroup_link" 53 | 54 | ruleOrigin=rule.find('origin').text 55 | 56 | 57 | for fgroup_link in root.findall('fgroup_link[item_id="'+ruleID+'"]'): 58 | if fgroup_link is None: print('Error') 59 | 60 | fgroup_link_fgroup_id = fgroup_link.find('fgroup_id').text 61 | fgroup_id = root.find('fgroup[id="'+fgroup_link_fgroup_id+'"]') 62 | fgroup_name = fgroup_id.find('description').text 63 | fgroup_parent_id = fgroup_id.find('parent_id') 64 | fgroup_level_id=0 65 | fgroup_level_id = fgroup_id.find('level_id').text 66 | level=">" 67 | 68 | htmlGroupArray.append('"'+level+str(fgroup_name)+'"') 69 | while not fgroup_parent_id is None: 70 | fgroup_id = root.find('fgroup[id="'+fgroup_parent_id.text+'"]') #find parent node 71 | fgroup_name = fgroup_id.find('description').text #find name 72 | fgroup_level_id=0 73 | fgroup_level_id = fgroup_id.find('level_id').text 74 | level=level+">" 75 | fgroup_parent_id=fgroup_id.find('parent_id') #check if new node has parent 76 | 77 | if not fgroup_parent_id is None: 78 | htmlGroupArray.append('"'+level+str(fgroup_name)+'"') 79 | 80 | detailedRuleData=base64.b64decode(rule.find('rule_data').text) 81 | x = etree.fromstring(detailedRuleData) 82 | m = etree.tostring(x, pretty_print = True) 83 | 84 | drdroot = ET.fromstring(detailedRuleData) 85 | 86 | ruleName=drdroot.find('name').text 87 | ruleType=drdroot.get('type') 88 | htmlRuleDef.append('"'+ruleName+'"') 89 | 90 | htmlRuleDef.append('"'+ruleOrigin+'"') 91 | htmlRuleDef.append('"'+ruleType+'"') 92 | 93 | ruleIsBB=drdroot.get('buildingBlock') 94 | if ruleIsBB is not None and ruleIsBB=='true': 95 | htmlRuleDef.append('"BB"') 96 | else: 97 | htmlRuleDef.append('"Rule"') 98 | 99 | ruleEnabled=drdroot.get('enabled') 100 | if ruleEnabled=='true': 101 | htmlruleEnabled='"Enabled"' 102 | else: 103 | htmlruleEnabled='"Disabled"' 104 | 105 | htmlRuleDef.append(htmlruleEnabled) 106 | htmlRuleDef.append('"'+ruleUUID+'"') 107 | 108 | 109 | # start of ruletest definition 110 | testDefinitions=drdroot.find('testDefinitions') 111 | 112 | negateTextA='' 113 | negateTextA=' [AND NOT] ' 114 | negateTextB='' 115 | testSeq=-1 116 | htmlTestArray=['"'] 117 | for elTests in testDefinitions.findall('test'): 118 | teteststSeq=testSeq+1 119 | testName=elTests.get('name') 120 | testUUID=elTests.get('uid') 121 | testNegate=str(elTests.get('negate')) 122 | ruleText=str(elTests.find('text').text) 123 | htmltest='' 124 | if testNegate=="true" and testNegate is not None: 125 | htmltest=''+negateTextA+'' 126 | else: 127 | htmltest=''+negateTextB+'' 128 | 129 | negateTextA=' [AND NOT] ' 130 | negateTextB=' [AND] ' 131 | 132 | if isinstance(ruleText, str): 133 | parser.close() 134 | parser.testArray=[] 135 | parse=str(parser.feed(ruleText)) 136 | 137 | oldx0=-1 138 | oldx1=-1 139 | for x in parser.testArray: 140 | fullTestArray.append(x) 141 | if str(x[0])!=oldx0: 142 | oldx0=str(x[0]) 143 | if str(x[1])!=oldx1: 144 | oldx1=int(x[1]) 145 | if oldx1==1: 146 | htmltest=''+htmltest+'' 147 | htmltest=htmltest+''+str(x[2])+'' 148 | 149 | htmlTestArray.append(htmltest) 150 | htmlTestArray.append('"') 151 | 152 | actionDefinitions=drdroot.find('actions') 153 | responsDefinitions=drdroot.find('responses') 154 | responsHTML=[] 155 | 156 | forceOffense='false' 157 | 158 | if responsDefinitions is not None: 159 | newevent=responsDefinitions.find('newevent') 160 | if newevent is not None: 161 | neweventqid = str(newevent.get('qid')) 162 | LLC=str('LLC:'+str(newevent.get('lowLevelCategory'))) 163 | CRS=str('CRS:'+str(newevent.get('credibility'))+str(newevent.get('relevance'))+str(newevent.get('severity'))) 164 | forceOffense=str(newevent.get('forceOffenseCreation')) 165 | if forceOffense is not None and forceOffense=='true': 166 | htmlforceOffense='Offense' 167 | else: 168 | htmlforceOffense='No-Offense' 169 | 170 | responsHTML.append(str('"QID:'+str(newevent.get('qid')))+'","'+htmlforceOffense+'","'+LLC+'","'+CRS+'"') 171 | else: 172 | responsHTML.append(str('"","","",""')) 173 | 174 | print(','.join(htmlRuleDef)+','+','.join(htmlTestArray)+','+','.join(responsHTML)+','+','.join(htmlGroupArray)) 175 | 176 | print('END') 177 | 178 | 179 | if __name__ == "__main__": 180 | main() 181 | 182 | -------------------------------------------------------------------------------- /QRadar-rules2html.py: -------------------------------------------------------------------------------- 1 | # python3 script 2 | import sys, os 3 | import json, time 4 | from xml.etree.ElementTree import ElementTree 5 | import xml.etree.ElementTree as ET 6 | import base64 7 | import lxml.etree as etree 8 | 9 | from array import array 10 | from types import * 11 | from html.parser import HTMLParser 12 | from optparse import OptionParser 13 | 14 | import pprint 15 | 16 | class MyHTMLParser(HTMLParser): 17 | 18 | def __init__(self): 19 | HTMLParser.__init__(self) 20 | self.recording = 0 21 | self.data = [] 22 | self.test = [] 23 | 24 | def handle_starttag(self, tag, attrs): 25 | self.recording = 1 26 | self.data='' 27 | 28 | def handle_endtag(self, tag): 29 | self.recording -= 1 30 | 31 | def handle_data(self, data): 32 | self.testArray.append([testSeq,self.recording,data]) 33 | 34 | def main(): 35 | tree = ET.parse(sys.argv[1]) 36 | root = tree.getroot() 37 | rule = [] 38 | htmlheader=['\ 164 | \ 165 |
Name | \ 168 |Rule | \ 169 |Respons | \ 170 |
---|