Advertisement
opexxx

blackpattern.py

Mar 15th, 2014
292
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.35 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. #  Copyright (c) 2003-2010, Emerging Threats
  4. #  All rights reserved.
  5. #  
  6. #  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
  7. #  following conditions are met:
  8. #  
  9. #  * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
  10. #    disclaimer.
  11. #  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
  12. #    following disclaimer in the documentation and/or other materials provided with the distribution.
  13. #  * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived
  14. #    from this software without specific prior written permission.
  15. #  
  16. #  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES,
  17. #  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. #  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  19. #  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  20. #  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  21. #  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  22. #  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23.  
  24. import re
  25. import os
  26. import sys
  27. import glob
  28. from optparse import OptionParser
  29.  
  30. #read our redirected snort output into one long string
  31. def parse_snort_output(snort_output):
  32.     if os.path.exists(snort_output):
  33.         try:
  34.             snortout = open(snort_output)
  35.             snortoutput = snortout.read()
  36.             if snortoutput == "":
  37.                 print "snort output was parsed but is empty bailing"
  38.                 sys.exit(1)
  39.             return snortoutput
  40.         except:
  41.             print "failed to open and read snort output file %s" % (snort_output)
  42.             sys.exit(1)
  43.     else:
  44.         print "failed to find snort output file %s" % (snort_output)
  45.         sys.exit(1)
  46.  
  47. #parse the blacklist careful no validation garbage in garbage out.
  48. def parse_blacklist(black_list_file):
  49.     if os.path.exists(black_list_file):
  50.         try:
  51.             blfile = open(black_list_file)
  52.             blacklist = blfile.readlines()
  53.             if blacklist == []:
  54.                 print "blacklist file was parsed but is empty bailing"
  55.                 sys.exit(1)
  56.             print blacklist
  57.             return blacklist
  58.         except:
  59.             print "failed to open and read blacklist pattern file %s" % (black_list_file)
  60.             sys.exit(1)
  61.     else:
  62.         print "failed to find blacklist pattern file %s" % (black_list_file)
  63.         sys.exit(1)
  64.  
  65. #parse the blacklist careful no validation garbage in garbage out.
  66. def parse_snort_rules(rulesglob):
  67.     rule_file_list = glob.glob(rulesglob)
  68.     rule_list_all = []
  69.     if rule_file_list:
  70.         for rule_file in rule_file_list:
  71.             try:
  72.                 f = open(rule_file)
  73.                 for line in f:
  74.                     rule_list_all.append(line)
  75.             except:
  76.                 print "failed to open and parse %s" % (rule_file)
  77.                 sys.exit(1)
  78.         if not rule_list_all:
  79.             print "snort rule list is empty %s used glo" % (rulesglob)
  80.             sys.exit(1)
  81.         else:
  82.             return rule_list_all
  83.     else:
  84.         print "snort rule glob came up empty using glob" % (rulesglob)
  85.         sys.exit(1)
  86.  
  87. #do the regex matching and field extraction and compare the black list to the final pattern
  88. def fast_pattern_blacklist(snortoutput,blacklist,nocase,ruleslist):
  89.     #one long nasty regex.. most people would put an \n in here somewhere but I'm not most men.
  90.     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)
  91.    
  92.     for match in fpdebug_regex.finditer(snortoutput):
  93.         for blmatch in blacklist:
  94.             blmatch = blmatch.strip()
  95.  
  96.             #this is stupid lazy this belongs in another function
  97.             havematch = "no"
  98.  
  99.             if nocase == True:
  100.                 if match.group("fpfinal").lower() == blmatch.lower():
  101.                      print "Match of case insensitive Blacklist Entry:%s" % (blmatch)
  102.                      print match.group(0)
  103.                      havematch = "yes"
  104.             else:  
  105.                 if match.group("fpfinal") == blmatch:
  106.                      print "Match of Blacklist Entry:%s" % (blmatch)
  107.                      print match.group(0)
  108.                      havematch = "yes"
  109.  
  110.             if ruleslist and havematch == "yes":
  111.                for line in ruleslist:
  112.                    matchre = ".+\;\s*sid\:\s*%s\s*\;" % (match.group("sid"))
  113.                    m = re.match(matchre,line)
  114.                    if m is not None:
  115.                        print "rules matching sid %s\n" % (match.group("sid"))
  116.                        print line
  117.  
  118. if __name__ == "__main__":
  119.          
  120.     #my code isn't pretty stop looking at me swan!
  121.     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\
  122.    2. Run snort redirecting output to a file  snort -c snort-vrt.conf -l ./ -r empty.pcap >output.txt 2>&1\n\
  123.    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"
  124.  
  125.     parser = OptionParser(usage=usage)
  126.     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")
  127.     parser.add_option("-b", "--blfile", dest="blfile", help="file containing blacklist patterns one per line")
  128.     parser.add_option("-i", "--nocase", action="store_true", dest="nocase", default=False, help="make the matches on the patterns case insensitive")
  129.     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")
  130.  
  131.     (options, args) = parser.parse_args()
  132.  
  133.     #make sure we have required options
  134.     if not options.snortout or not options.blfile:
  135.         print usage
  136.         sys.exit(1)
  137.  
  138.     #read in the snort input
  139.     snortoutput=parse_snort_output(options.snortout)
  140.  
  141.     #read in the black list
  142.     blacklist=parse_blacklist(options.blfile)
  143.    
  144.     #if we have a rules glob parse it...Warning lines are read in without additional regex.. We should do this.
  145.     if options.rulesglob:
  146.        ruleslist = parse_snort_rules(options.rulesglob)    
  147.     else:
  148.        ruleslist = None
  149.  
  150.     fast_pattern_blacklist(snortoutput,blacklist,options.nocase,ruleslist)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement