#!/usr/bin/python -tO # freewvs 0.1 - the free web vulnerability scanner # # http://source.schokokeks.org/freewvs/ # # Copyright 2007 Hanno Boeck, schokokeks.org # # Contributions by # Fabian Fingerle # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import ConfigParser, os, glob, pprint, re, optparse, sys, gettext from xml.sax.saxutils import escape gettext.textdomain('freewvs') _ = gettext.gettext def versioncompare(safe_version, find_version): if safe_version == [""]: return True for i in range(min(len(find_version), len(safe_version))): if int(find_version[i])int(safe_version[i]): return False return (len(find_version)' % state print ' %s' % escape(appname) print ' %s' % escape(version) print ' %s' % escape(appdir) if state == 'vulnerable': print ' %s' % escape(safeversion) print ' %s' % escape(vuln) print ' ' pp = pprint.PrettyPrinter(indent=4) # Command-line options parser = optparse.OptionParser() parser.add_option("-a", "--all", action="store_true", dest="ALL", help="Show all webapps found, not just vulnerable") parser.add_option("-d", "--debug", action="store_true", dest="DEBUG", help="Show lots of debugging output, mainly useful"+ \ "for development") parser.add_option("-f", "--fancy", action="store_const", dest="OUTPUT", const="fancy", help="Show more fancy output") parser.add_option("-x", "--xml", action="store_const", dest="OUTPUT", const="xml", help="Output results as XML") opts, args = parser.parse_args() # Parse vulnerability database config = ConfigParser.ConfigParser() config.read(glob.glob('/usr/share/freewvs/*.freewvs')) config.read(glob.glob('/usr/local/share/freewvs/*.freewvs')) config.read(glob.glob(os.path.dirname(sys.argv[0])+'/freewvsdb/*.freewvs')) vdb = [] for sect in config.sections(): item = {} # base options item['name'] = sect item['safe'] = config.get(sect, 'safe') item['file'] = config.get(sect, 'file') item['vuln'] = config.get(sect, 'vuln') item['subdir'] = int(config.get(sect, 'subdir')) # match magic item['variable'] = [] for var in config.get(sect,'variable').split(","): item['variable'].append(re.compile(re.escape(var)+ r"[^0-9.]*[.]*([0-9.]*[0-9])[^0-9.]")) # optional options if config.has_option(sect,'extra_match'): item['extra_match'] = config.get(sect,'extra_match') else: item['extra_match'] = False if config.has_option(sect,'add_minor'): item['add_minor'] = config.get(sect,'add_minor') else: item['add_minor'] = False if config.has_option(sect,'old_safe'): item['old_safe'] = config.get(sect,'old_safe').split(",") else: item['old_safe'] = [] vdb.append(item) if opts.DEBUG: pp.pprint(vdb) if opts.OUTPUT == 'xml': print '' print '' # start the search for fdir in args: for root, NULL, files in os.walk(fdir): for filename in files: for item in vdb: if filename == item['file']: mfile = os.path.join(root, filename) file = open(mfile) filestr = file.read() file.close() if item['extra_match']: ematch = (filestr.find(item['extra_match']) != -1) else: ematch = True findversion = [] for var in item['variable']: var = var.search(filestr) if not var: findversion = False break else: findversion.append(var.group(1)) if findversion and ematch: findversion = '.'.join(findversion) # Very ugly phpbb workaround if item['add_minor']: findversion = findversion.split('.') findversion[-1] = str(int(findversion[-1])+ int(item['add_minor'])) findversion = '.'.join(findversion) if not (versioncompare(item['safe'].split('.'), \ findversion.split('.'))) or \ item['old_safe'].count(findversion)>0: if opts.ALL: if opts.DEBUG: print "File "+mfile vulnprint(item['name'], findversion, \ "ok", "", mfile, item['subdir'], \ opts.OUTPUT) else: if opts.DEBUG: print "File "+mfile safev="9999" for ver in item['old_safe']: if (versioncompare(ver.split('.'), \ findversion.split('.') ) and \ not versioncompare(ver.split('.'), \ safev.split('.')) ): safev=ver if safev=="9999": safev=item['safe'] vulnprint (item['name'], findversion, \ safev, item['vuln'], \ mfile, item['subdir'], opts.OUTPUT) else: if opts.DEBUG: print "regexp failed for " + \ item['name'] + " on " + mfile if opts.OUTPUT == 'xml': print ''