#!/usr/bin/env python import re, os, sys, locale from xml.sax import * # Need PyXML [http://pyxml.sourceforge.net/] """ Regular Expression Filter Fuzzer (CC) by nEUrOO http://rgaucher.info/beta/RegFuzzer v0.1: First version, only HTML/JavaScript filters """ html_header = """ """ html_footer = """ """ html_stream = None # list of patterns patterns = {} type_listOfType = ['client','sql','file','server', 'all'] type_AllType = 'all' type_ErrorType = 'error' def encodeHTML(s): s = s.replace("&", "&") s = s.replace("<", "<") s = s.replace(">", ">") s = s.replace("\"",""") return s def normalize_whitespace(text): return ' '.join(text.split()) def clear_whitespace(text): return text.replace(' ','') # Handle the XML file with a SAX Parser class InputHandler(ContentHandler): def __init__(self): self.inConf = False self.inInput = False self.inRegex = False self.inType = False self.inName = False self.string = "" self.curName = "" self.curReg = "" self.curType= "" def startElement(self, name, attrs): localName = name.lower() self.string = "" if name == 'reg-fuzzer': self.inConf = True elif name == 'input' and self.inConf: self.inInput = True self.curName = "" self.curReg = "" self.curType= "" elif name == 'name' and self.inInput: self.inName = True elif name == 'regex' and self.inInput: self.inRegex = True elif name == 'type' and self.inInput: self.inType = True def characters(self, ch): if self.inInput: self.string = self.string + ch def endElement(self, name): global patterns if name == 'input' and self.inInput: self.inInput = False # Include in the patterns if self.curName == '': import time self.curName = "test_date_" + str(time.clock()) else: if self.curType not in type_listOfType: self.curType = type_AllType if self.curName not in patterns: patterns[self.curName] = [self.curReg, self.curType] else: raise NameError, "The name of the input [%s] is already defined, this defintion will be skipped" % self.curName if name == 'name' and self.inName: self.inName = False self.curName = normalize_whitespace(self.string) if name == 'regex' and self.inRegex: self.inRegex = False self.curReg = normalize_whitespace(self.string) if name == 'type' and self.inType: self.inType = False self.curType = normalize_whitespace(self.string).lower() possibleCharsets_Client=["Hex-Url","Hex-Html","Latin1","UTF-8","UTF-7","UTF-16"] quotes = ["'", '"'] bracket_e = ">" bracket_s = "<" scripts = ['script', 'script','\0script','scri\0pt','scri\npt','*script'] dicoAttack = { 'client' : [ '_QUOTE__BRACKET_E__BRACKET_S__SCRIPT__BRACKET_E_alert(1);_BRACKET_S_/_SCRIPT__BRACKET_E_', '_QUOTE_ onmouseover=_QUOTE_alert(1)_QUOTE_', '_QUOTE_ style=_QUOTE_-moz-binding:url(http://tinyurl/fake)_QUOTE_' ] } """ def launchEncodings(iStr): import textencoder for c in possibleCharsets_Client: iStr = unicode(iStr) oStr = textencoder.convert(iStr, 'Latin1', c) language, output_encoding = locale.getdefaultlocale() print oStr.encode(output_encoding) """ def testRegExp(injStr, compRegExp): if not compRegExp.match(injStr): return injStr else: return None def fuzz_ClientSide(name, compRegExp): # print "\n# Pattern Name: ", name html_stream.write (("

Pattern name: %s

\n") % name) l = [] for a in dicoAttack['client']: for q in quotes: if '_SCRIPT_' in a: for s in scripts: injStr = a injStr = injStr.replace(u'_SCRIPT_', s) injStr = injStr.replace(u'_QUOTE_', q) injStr = injStr.replace(u'_BRACKET_E_', bracket_e) injStr = injStr.replace(u'_BRACKET_S_', bracket_s) #launchEncodings(injStr) s = testRegExp(injStr, compRegExp) if s: l.append(s) else: injStr = a injStr = injStr.replace(u'_QUOTE_', q) injStr = injStr.replace(u'_BRACKET_E_', bracket_e) injStr = injStr.replace(u'_BRACKET_S_', bracket_s) #launchEncodings(injStr) s = testRegExp(injStr, compRegExp) if s: l.append(s) if len(l) > 0: html_stream.write("
    \n") for iStr in l: html_stream.write("\t
  1. %s
  2. \n" % encodeHTML(iStr)) html_stream.write("
\n") """ Main function """ if __name__ == '__main__': # get the number of parameters fileName = "foo.bar" if len(sys.argv) != 3: print "Error of usage" print "regFuzzer,py <--test-regexp,-t|--fuzz,-f> " sys.exit(1) else: try: fileName = sys.argv[2] parser = make_parser() input_handler = InputHandler() # Tell the parser to use our handler parser.setContentHandler(input_handler) parser.parse(fileName) except NameError, e: print "Unexpected error in input file:", e if sys.argv[1].lower() in ('--test-regexp', '-t'): print "# Start the evaluation of the regexps" for k in patterns: try: re.compile(patterns[k][0], re.I) except: print k,'\t| ',patterns[k][1],'\t| ',patterns[k][0],'\t| ',"ERROR" else: print k,'\t| ',patterns[k][1],'\t| ',patterns[k][0],'\t| ',"OK" print "# End of evaluation" elif sys.argv[1].lower() in ('--fuzz', '-f'): print "# Compile the regular expressions" try: html_stream = open("reg-fuzzer-output.html", "wb") html_stream.write(html_header) for k in patterns: try: re.compile(patterns[k][0], re.I) except: print "Error in the regular expression [name = \"%s\"]" % k print "Use: \"regFuzzer.py --test-regexp %s\" to test your input regexp" % fileName sys.exit(1) print "# Fuzz the regexps" for k in patterns: if patterns[k][1].lower() == 'client': fuzz_ClientSide(k, re.compile(patterns[k][0])) print "# End of the regexp fuzzer" html_stream.close() except IOError: print "Cannot write the HTML file reg-fuzzer-output.html"