Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- # Copyright (c) 2003-2010, Emerging Threats
- # All rights reserved.
- #
- # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
- # following conditions are met:
- #
- # * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
- # disclaimer.
- # * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
- # following disclaimer in the documentation and/or other materials provided with the distribution.
- # * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived
- # from this software without specific prior written permission.
- #
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES,
- # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- import re
- import os
- import sys
- import glob
- from optparse import OptionParser
- #read our redirected snort output into one long string
- def parse_snort_output(snort_output):
- if os.path.exists(snort_output):
- try:
- snortout = open(snort_output)
- snortoutput = snortout.read()
- if snortoutput == "":
- print "snort output was parsed but is empty bailing"
- sys.exit(1)
- return snortoutput
- except:
- print "failed to open and read snort output file %s" % (snort_output)
- sys.exit(1)
- else:
- print "failed to find snort output file %s" % (snort_output)
- sys.exit(1)
- #parse the blacklist careful no validation garbage in garbage out.
- def parse_blacklist(black_list_file):
- if os.path.exists(black_list_file):
- try:
- blfile = open(black_list_file)
- blacklist = blfile.readlines()
- if blacklist == []:
- print "blacklist file was parsed but is empty bailing"
- sys.exit(1)
- print blacklist
- return blacklist
- except:
- print "failed to open and read blacklist pattern file %s" % (black_list_file)
- sys.exit(1)
- else:
- print "failed to find blacklist pattern file %s" % (black_list_file)
- sys.exit(1)
- #parse the blacklist careful no validation garbage in garbage out.
- def parse_snort_rules(rulesglob):
- rule_file_list = glob.glob(rulesglob)
- rule_list_all = []
- if rule_file_list:
- for rule_file in rule_file_list:
- try:
- f = open(rule_file)
- for line in f:
- rule_list_all.append(line)
- except:
- print "failed to open and parse %s" % (rule_file)
- sys.exit(1)
- if not rule_list_all:
- print "snort rule list is empty %s used glo" % (rulesglob)
- sys.exit(1)
- else:
- return rule_list_all
- else:
- print "snort rule glob came up empty using glob" % (rulesglob)
- sys.exit(1)
- #do the regex matching and field extraction and compare the black list to the final pattern
- def fast_pattern_blacklist(snortoutput,blacklist,nocase,ruleslist):
- #one long nasty regex.. most people would put an \n in here somewhere but I'm not most men.
- fpdebug_regex = re.compile(r"(?P<gid>\d)\:(?P<sid>\d+)\n\s+Fast pattern matcher\:\s+(?P<fmatcher>[^\n]+)\n\s+Fast pattern set\:\s+(?P<fpset>[^\n]+)\n\s+Fast pattern only\:\s+(?P<fponly>[^\n]+)\n\s+Negated\:\s+(?P<fpnegate>[^\n]+)\n\s+Pattern offset\,length\:\s+(?P<fpoffset>[^\n]+)\n\s+Pattern truncated\:\s+(?P<fptruncated>[^\n]+)\n\s+Original pattern\n\s+\x22(?P<fporiginal>[^\x22]+)\x22\n\s+Final pattern\n\s+\x22(?P<fpfinal>[^\x22]+)\x22\n", re.IGNORECASE)
- for match in fpdebug_regex.finditer(snortoutput):
- for blmatch in blacklist:
- blmatch = blmatch.strip()
- #this is stupid lazy this belongs in another function
- havematch = "no"
- if nocase == True:
- if match.group("fpfinal").lower() == blmatch.lower():
- print "Match of case insensitive Blacklist Entry:%s" % (blmatch)
- print match.group(0)
- havematch = "yes"
- else:
- if match.group("fpfinal") == blmatch:
- print "Match of Blacklist Entry:%s" % (blmatch)
- print match.group(0)
- havematch = "yes"
- if ruleslist and havematch == "yes":
- for line in ruleslist:
- matchre = ".+\;\s*sid\:\s*%s\s*\;" % (match.group("sid"))
- m = re.match(matchre,line)
- if m is not None:
- print "rules matching sid %s\n" % (match.group("sid"))
- print line
- if __name__ == "__main__":
- #my code isn't pretty stop looking at me swan!
- usage = "1. Enable fast patterh debug in your snort.conf on the config detection line \"config detection: search-method ac-split search-optimize max-pattern-len 20 debug-print-fast-pattern\"\n\
- 2. Run snort redirecting output to a file snort -c snort-vrt.conf -l ./ -r empty.pcap >output.txt 2>&1\n\
- 3. Run the script\n usage: %prog -s <snort output file> -b <file containing blacklist patterns one per line> -r <optional rules glob> -i <optional case insensitive blacklist matches>\n"
- parser = OptionParser(usage=usage)
- parser.add_option("-s", "--snortout", dest="snortout", help="output from snort perhaps try snort -c snort-vrt.conf -l ./ -r empty.pcap >output.txt 2>&1")
- parser.add_option("-b", "--blfile", dest="blfile", help="file containing blacklist patterns one per line")
- parser.add_option("-i", "--nocase", action="store_true", dest="nocase", default=False, help="make the matches on the patterns case insensitive")
- parser.add_option("-r", "--rulesglob", dest="rulesglob", help="glob of snort rules like /etc/snort/rules/*.rules. We will grep the list of display a matching rule when we encounter a blacklisted pattern")
- (options, args) = parser.parse_args()
- #make sure we have required options
- if not options.snortout or not options.blfile:
- print usage
- sys.exit(1)
- #read in the snort input
- snortoutput=parse_snort_output(options.snortout)
- #read in the black list
- blacklist=parse_blacklist(options.blfile)
- #if we have a rules glob parse it...Warning lines are read in without additional regex.. We should do this.
- if options.rulesglob:
- ruleslist = parse_snort_rules(options.rulesglob)
- else:
- ruleslist = None
- fast_pattern_blacklist(snortoutput,blacklist,options.nocase,ruleslist)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement