git.schokokeks.org
Repositories
Help
Report an Issue
freewvs.git
Code
Commits
Branches
Tags
Suche
Strukturansicht:
5de1f3b
Branches
Tags
master
v0.1.1
v0.1.2
v0.1.3
v0.1.4
freewvs.git
freewvs
remove year so we don't have to update it
Hanno Böck
commited
5de1f3b
at 2019-12-08 15:06:44
freewvs
Blame
History
Raw
#!/usr/bin/python3 -O # freewvs 0.1 - the free web vulnerability scanner # # https://source.schokokeks.org/freewvs/ # # Written by schokokeks.org Hosting, https://schokokeks.org # # Contributions by # Hanno Boeck, https://hboeck.de/ # Fabian Fingerle, https://fabian-fingerle.de/ # Bernd Wurst, https://bwurst.org/ # # To the extent possible under law, the author(s) have dedicated all copyright # and related and neighboring rights to this software to the public domain # worldwide. This software is distributed without any warranty. # # You should have received a copy of the CC0 Public Domain Dedication along # with this software. If not, see # https://creativecommons.org/publicdomain/zero/1.0/ # Nevertheless, in case you use a significant part of this code, we ask (but # not require, see the license) that you keep the authors' names in place and # return your changes to the public. We would be especially happy if you tell # us what you're going to do with this code. import configparser import os import glob import pprint import re import optparse import sys import 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 True if int(find_version[i]) > int(safe_version[i]): return False return len(find_version) < len(safe_version) def vulnprint(appname, version, safeversion, vuln, vfilename, subdir, style=None): appdir = '/'.join(os.path.abspath(vfilename).split('/')[:-1 - subdir]) if not style: print("%(appname)s %(version)s (%(safeversion)s) %(vuln)s " "%(appdir)s" % vars()) elif style == 'fancy': print(_("Directory: %(appdir)s") % vars()) if safeversion != "ok": if safeversion != "": print(_("Vulnerable %(appname)s %(version)s found, please " "update to %(safeversion)s or above.") % vars()) else: print(_("Vulnerable %(appname)s %(version)s found, no fixed " "version available.") % vars()) if vuln[:3] == "CVE": print(_("https://cve.mitre.org/cgi-bin/cvename.cgi?name=" "%(vuln)s") % vars()) else: print(vuln) else: print(_("%(appname)s %(version)s found.") % vars()) print("") elif style == 'xml': state = 'vulnerable' if safeversion == 'ok': state = 'ok' print(' <app state="%s">' % state) print(' <appname>%s</appname>' % escape(appname)) print(' <version>%s</version>' % escape(version)) print(' <directory>%s</directory>' % escape(appdir)) if state == 'vulnerable': print(' <safeversion>%s</safeversion>' % escape(safeversion)) print(' <vulninfo>%s</vulninfo>' % escape(vuln)) print(' </app>') pp = pprint.PrettyPrinter(indent=4) # Command-line options parser = optparse.OptionParser(usage="usage: %prog [options] <path>" "[<path2> ...]") 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") parser.add_option("-3", "--thirdparty", action="store_true", dest="THIRDPARTY", help="Scan for third-party components like jquery") opts, args = parser.parse_args() # Parse vulnerability database config = configparser.ConfigParser() try: 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')) except configparser.MissingSectionHeaderError as err: print("Error parsing config files: %s" % err) vdb = [] for sect in config.sections(): item = {} if (config.getboolean(sect, 'thirdparty', fallback=False) and not opts.THIRDPARTY): continue # 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'] = re.compile(re.escape(config.get(sect, 'variable')) + r"[^0-9\n\r]*[.]*([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, 'extra_nomatch'): item['extra_nomatch'] = config.get(sect, 'extra_nomatch') else: item['extra_nomatch'] = False if config.has_option(sect, 'path_match'): item['path_match'] = config.get(sect, 'path_match') else: item['path_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('<?xml version="1.0" ?>') print('<freewvs>') # 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) try: file = open(mfile, errors='replace') except Exception: continue filestr = file.read() file.close() if ((item['extra_match'] and item['extra_match'] not in filestr) or (item['extra_nomatch'] and item['extra_nomatch'] not in filestr) or (item['path_match'] and not root.endswith(item['path_match']))): continue findversion = item['variable'].search(filestr) if not findversion: continue findversion=findversion.group(1) # 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) if opts.OUTPUT == 'xml': print('</freewvs>')