├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── bin ├── cve_doc.py ├── cve_refs.py ├── db_dump.py ├── dump_last.py ├── search.py ├── search_cpe.py ├── search_fulltext.py ├── search_irc.py └── search_xmpp.py ├── doc ├── html │ ├── Installation.html │ ├── Structure.html │ ├── Webcomponent.html │ └── css │ │ └── style.css └── markdown │ ├── api.md │ ├── installation.md │ ├── structure.md │ └── webcomponent.md ├── etc ├── auth.txt.sample ├── configuration.ini.sample ├── plugins.txt.sample └── sources.ini.sample ├── lib ├── Authentication.py ├── CVEs.py ├── Config.py ├── DatabaseLayer.py ├── PluginManager.py ├── Plugins.py ├── ProgressBar.py ├── Query.py ├── Singleton.py ├── Toolkit.py ├── User.py ├── __init__.py ├── authenticationMethods │ └── readme.md └── cpelist.py ├── requirements.txt ├── sbin ├── db_blacklist.py ├── db_cpe_browser.py ├── db_fulltext.py ├── db_mgmt.py ├── db_mgmt_admin.py ├── db_mgmt_capec.py ├── db_mgmt_cpe_dictionary.py ├── db_mgmt_cpe_other_dictionary.py ├── db_mgmt_create_index.py ├── db_mgmt_cwe.py ├── db_mgmt_ref.py ├── db_mgmt_vendorstatements.py ├── db_notification.py ├── db_ranking.py ├── db_updater.py └── db_whitelist.py ├── test └── test.py └── web ├── advanced_api.py ├── api.py ├── index.py ├── minimal.py ├── static ├── css │ ├── bootstrap.min.css │ ├── custom │ │ ├── admin.css │ │ ├── cve.css │ │ └── filter.css │ ├── sidebar.css │ └── style.css ├── flash │ └── ZeroClipboard.swf ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 ├── img │ └── favicon.ico └── js │ ├── ZeroClipboard.min.js │ ├── ZeroClipboard.swf │ ├── bootstrap.min.js │ ├── custom │ ├── admin.js │ ├── autoload.js │ ├── cve.js │ ├── filter.js │ ├── list.js │ ├── listmanagement.js │ ├── pager.js │ ├── scripts.js │ ├── sidebar.js │ └── statusses.js │ ├── html5shiv.js │ └── jquery-1.11.2.min.js └── templates ├── 404.html ├── admin.html ├── api.html ├── bookmarked.html ├── browse.html ├── capec.html ├── cve.html ├── cwe.html ├── documentation ├── api │ ├── blacklist │ ├── blacklist_add │ ├── blacklist_drop │ ├── blacklist_export │ ├── blacklist_import │ ├── blacklist_remove │ ├── browse │ ├── capec │ ├── cpe22 │ ├── cpe23 │ ├── cve │ ├── cvefor │ ├── cwe │ ├── dbInfo │ ├── dbupdate │ ├── last │ ├── link │ ├── query │ ├── search │ ├── whitelist │ ├── whitelist_add │ ├── whitelist_drop │ ├── whitelist_export │ ├── whitelist_import │ └── whitelist_remove └── status_codes │ ├── authentication_failed │ ├── authentication_needed │ ├── authorization_method_not_allowed │ ├── internal_server_error │ ├── limit_must_be_int │ ├── malformed_authentication_string │ ├── not_found │ ├── resource_unavailable │ ├── skip_must_be_int │ ├── success │ └── unknown_content-type ├── error.html ├── index-minimal.html ├── index.html ├── layouts ├── api-accordion-child ├── master-page └── status_code_accordion-child ├── linked.html ├── list.html ├── listmanagement.html ├── login.html ├── requiresAuth.html ├── search.html └── subpages ├── filters.html ├── menu-minimal.html ├── menu.html ├── pager.html └── table.html /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | bin/__pycache__/ 3 | lib/__pycache__/ 4 | sbin/__pycache__/ 5 | 6 | log/ 7 | ssl/ 8 | tmp/ 9 | plugins/ 10 | indexdir/ 11 | web/templates/plugins/ 12 | 13 | etc/configuration.ini 14 | etc/plugins.ini 15 | etc/plugins.txt 16 | 17 | .gitignore 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | python: 4 | #- "3.2" 5 | - "3.3" 6 | - "3.4" 7 | - "3.5" 8 | - "nightly" 9 | 10 | cache: pip 11 | 12 | services: 13 | - redis-server 14 | - mongodb 15 | 16 | install: 17 | - pip install -q -U pip 18 | - pip install -q -r requirements.txt 19 | - pushd sbin 20 | - ./db_mgmt.py -p 21 | # Avoid creating a log > 4mb and making travis unhappy. 22 | - ./db_mgmt_cpe_dictionary.py | cat & 23 | - PID=$! 24 | - while sleep 60; do kill -0 $PID && echo 'Still running' || break; done 25 | - popd 26 | #- pushd web 27 | #- python minimal-web.py & 28 | #- popd 29 | 30 | script: 31 | - pushd bin 32 | - ./search.py -p cisco:ios:12.4 > /dev/null 33 | - ./search.py -p cisco:ios:12.4 -o json > /dev/null 34 | - ./search.py -p microsoft:windows_7 -o html > /dev/null 35 | - ./search.py -c CVE-2010-3333 > /dev/null 36 | - ./dump_last.py -f atom -l 2 > /dev/null 37 | - popd 38 | 39 | notifications: 40 | email: 41 | on_success: change 42 | on_failure: change 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | cve-search is free software and licensed under 3-Clause BSD License - "New BSD License" or "Modified BSD License". 2 | 3 | Copyright (c) 2012 Wim Remes - https://github.com/wimremes/ 4 | Copyright (c) 2012-2016 Alexandre Dulaunoy - https://github.com/adulau/ 5 | Copyright (c) 2015-2016 Pieter-Jan Moreels - https://github.com/pidgeyl/ 6 | 7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 10 | 11 | 2. 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. 12 | 13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 14 | 15 | 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 HOLDER 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. 16 | 17 | -------------------------------------------------------------------------------- /bin/cve_doc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # cve_doc converts CVE to asciidoc 4 | # 5 | # Software is free software released under the "Modified BSD license" 6 | # 7 | # Copyright (c) 2015 Alexandre Dulaunoy - a@foo.be 8 | 9 | 10 | import os 11 | import sys 12 | runPath = os.path.dirname(os.path.realpath(__file__)) 13 | sys.path.append(os.path.join(runPath, "..")) 14 | 15 | import json 16 | import re 17 | 18 | from optparse import OptionParser 19 | 20 | from lib.Query import apigetcve 21 | 22 | optp = OptionParser() 23 | optp.add_option('-c', '--cve', dest='cve', default='CVE-2015-0001', help='CVE id to convert') 24 | optp.add_option('-f', '--format', dest='format', default='asciidoc', help='output format : asciidoc') 25 | optp.add_option('-a', '--api', dest='api', default='http://cve.circl.lu/', help='HTTP API url (default: http://cve.circl.lu)') 26 | (opts, args) = optp.parse_args() 27 | 28 | 29 | cve = json.loads(apigetcve(opts.api, cveid=opts.cve)) 30 | 31 | if not cve: 32 | sys.exit(10) 33 | 34 | print ("= Common Vulnerabilities and Exposures - {}".format(cve['id'])) 35 | print ("cve-search <{}/cve/{}>".format(opts.api,cve['id'])) 36 | print ("{},{}".format(cve['id'],cve['Modified'])) 37 | print (":toc:") 38 | print ("== {} Summary".format(cve['id'])) 39 | print ("\n"+cve['summary']) 40 | 41 | print ("\n== Vulnerable configurations\n") 42 | for vul in cve['vulnerable_configuration']: 43 | print ("* {}".format(re.sub(r'\n', '-', vul['title']))) 44 | if cve.get('cvss'): 45 | print ("\n== Common Vulnerability Scoring System") 46 | print ("CVSS value:: {}".format(cve['cvss'])) 47 | if cve.get('impact'): 48 | print ("\n== Impact Metrics") 49 | print ("\n[cols=\"1,2\"]") 50 | print ("|===") 51 | types = ['availability', 'confidentiality', 'integrity'] 52 | for t in types: 53 | print ("|{}".format(t.title())) 54 | print ("|{}".format(cve['impact'][t])) 55 | print ("|===") 56 | if cve.get('access'): 57 | print ("\n== Access to the vulnerability") 58 | print ("\n[cols=\"1,2\"]") 59 | print ("|===") 60 | types = ['authentication', 'complexity', 'vector'] 61 | for t in types: 62 | print ("|{}".format(t.title())) 63 | print ("|{}".format(cve['access'][t])) 64 | print ("|===") 65 | if cve.get('references'): 66 | print ("\n== References") 67 | if len(cve['references']) > 1: 68 | for ref in cve['references']: 69 | print ("* {}".format(ref)) 70 | elif len(cve['references']) == 1: 71 | ref = cve['references'][0] 72 | print ("* {}".format(ref)) 73 | -------------------------------------------------------------------------------- /bin/cve_refs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Lookup NIST CVE Reference Key/Maps from a CVE 5 | # 6 | # This file is part of the cve-search project. 7 | # 8 | # Software is free software released under the "Modified BSD license" 9 | # 10 | # Copyright (c) 2015-2016 Alexandre Dulaunoy - a@foo.be 11 | 12 | 13 | import os 14 | import sys 15 | import argparse 16 | runPath = os.path.dirname(os.path.realpath(__file__)) 17 | sys.path.append(os.path.join(runPath, "..")) 18 | 19 | 20 | from lib.Config import Configuration 21 | 22 | try: 23 | 24 | r = Configuration.getRedisRefConnection() 25 | except: 26 | sys.exit(1) 27 | 28 | argparser = argparse.ArgumentParser(description='Lookup the NIST ref database') 29 | argparser.add_argument('-c', help='CVE id to lookup', default=False) 30 | argparser.add_argument('-u', action='store_true', help='Enable URL expansion', default=False) 31 | argparser.add_argument('-v', action='store_true', help='verbose output', default=False) 32 | args = argparser.parse_args() 33 | 34 | if not args.c: 35 | sys.exit("CVE id missing") 36 | 37 | ref_urls = {"MS": "https://technet.microsoft.com/library/security/", 38 | "SECUNIA": "http://secunia.com/advisories/", 39 | "SREASON": "http://securityreason.com/security_alert", 40 | "CERT": "http://www.cert.org/advisories", 41 | "BID": "http://www.securityfocus.com/bid/", 42 | "AIXAPART": "", 43 | "ALLAIRE": "", 44 | "APPLE": "", 45 | "ASCEND": "", 46 | "ATSTAKE": "", 47 | "AUSCERT": "", 48 | "BEA": "", 49 | "BINDVIEW": "", 50 | "SECTRACK": "http://www.securitytracker.com/id/", 51 | "MANDRIVA": "http://www.mandriva.com/security/advisories?name="} 52 | 53 | refs = r.smembers(args.c) 54 | 55 | if not refs: 56 | sys.exit("{} has no NIST references".format(args.c)) 57 | 58 | for ref in refs: 59 | if args.u: 60 | (provider, refid) = ref.split(":", 1) 61 | if provider in ref_urls.keys(): 62 | print ("{}{}".format(ref_urls[provider], refid)) 63 | elif provider == 'CONFIRM': 64 | print ("{}".format(refid)) 65 | else: 66 | print (ref) 67 | else: 68 | print (ref) 69 | -------------------------------------------------------------------------------- /bin/db_dump.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Tool to dump in JSON the database along with the associated ranking 5 | # 6 | # Software is free software released under the "Modified BSD license" 7 | # 8 | # Copyright (c) 2012-2015 Alexandre Dulaunoy - a@foo.be 9 | # Copyright (c) 2015 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 10 | import os 11 | import sys 12 | runPath = os.path.dirname(os.path.realpath(__file__)) 13 | sys.path.append(os.path.join(runPath, "..")) 14 | 15 | import argparse 16 | import json 17 | from bson import json_util 18 | 19 | import lib.CVEs as cves 20 | import lib.DatabaseLayer as db 21 | 22 | argParser = argparse.ArgumentParser(description='Dump database in JSON format') 23 | argParser.add_argument('-r', default=False, action='store_true', help='Include ranking value') 24 | argParser.add_argument('-v', default=False, action='store_true', help='Include via4 map') 25 | argParser.add_argument('-c', default=False, action='store_true', help='Include CAPEC information') 26 | argParser.add_argument('-l', default=False, type=int, help='Limit output to n elements (default: unlimited)') 27 | args = argParser.parse_args() 28 | 29 | rankinglookup = args.r 30 | via4lookup = args.v 31 | capeclookup = args.c 32 | 33 | l = cves.last(rankinglookup=rankinglookup, via4lookup=via4lookup, capeclookup=capeclookup) 34 | 35 | for cveid in db.getCVEIDs(limit=args.l): 36 | item = l.getcve(cveid=cveid) 37 | if 'cvss' in item: 38 | if type(item['cvss']) == str: 39 | item['cvss'] = float(item['cvss']) 40 | date_fields = ['cvss-time', 'Modified', 'Published'] 41 | for field in date_fields: 42 | if field in item: 43 | item[field] = str(item[field]) 44 | print(json.dumps(item, sort_keys=True, default=json_util.default)) 45 | -------------------------------------------------------------------------------- /bin/dump_last.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Dump last CVE entries in RSS 1,RSS 2 or Atom format. 5 | # 6 | # Software is free software released under the "Modified BSD license" 7 | # 8 | # Copyright (c) 2012-2015 Alexandre Dulaunoy - a@foo.be 9 | # Copyright (c) 2015 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 10 | 11 | # Imports 12 | import os 13 | import sys 14 | runPath = os.path.dirname(os.path.realpath(__file__)) 15 | sys.path.append(os.path.join(runPath, "..")) 16 | 17 | import time 18 | import datetime 19 | import argparse 20 | 21 | import lib.CVEs as cves 22 | 23 | argParser = argparse.ArgumentParser(description='Dump last CVE entries in RSS/Atom format or in HTML tables') 24 | argParser.add_argument('-f', type=str, help='Output format (rss1,rss2,atom,html)', default='rss1') 25 | argParser.add_argument('-l', type=int, help='Last n items (default:10)', default=10) 26 | argParser.add_argument('-n', action='store_false', help='Disable lookup CPE name (default is True)') 27 | argParser.add_argument('-r', action='store_true', help='Enable CVE ranking (default is False) and only print entries with ranking') 28 | argParser.add_argument('-c', default=False, action='store_true', help='Display CAPEC values') 29 | 30 | args = argParser.parse_args() 31 | 32 | if args.l: 33 | last = args.l 34 | else: 35 | last = 10 36 | 37 | ref = "http://adulau.github.com/cve-search/" 38 | cvelist = cves.last(rankinglookup=args.r, namelookup=args.n, capeclookup=args.c) 39 | 40 | if not(args.f == "html"): 41 | from feedformatter import Feed 42 | feed = Feed() 43 | 44 | feed.feed['title'] = "cve-search Last " + str(last) + " CVE entries generated on " + str(datetime.datetime.now()) 45 | feed.feed['link'] = "http://adulau.github.com/cve-search/" 46 | feed.feed['author'] = "Generated with cve-search available at http://adulau.github.com/cve-search/" 47 | feed.feed['description'] = "" 48 | else: 49 | print ("") 50 | print ("") 51 | print ("Last " + str(args.l) + " CVE entries") 52 | print ("") 53 | for x in cvelist.get(limit=last): 54 | if not(args.f == "html"): 55 | item = {} 56 | item['title'] = str(x['id']) + " " + x['summary'][:90] + "..." 57 | item['description'] = x['summary'] 58 | if args.r and x.get('ranking'): 59 | item['description'] = item['description'] + " Ranking:" + str(x['ranking']) 60 | item['pubDate'] = time.localtime() 61 | item['guid'] = x['id'] 62 | if x['references']: 63 | item["link"] = str(x['references'][0]) 64 | else: 65 | item["link"] = "http://web.nvd.nist.gov/view/vuln/detail?vulnId=" + x['id'] 66 | feed.items.append(item) 67 | else: 68 | print ("
") 69 | print ("") 70 | print ("") 71 | print ("") 72 | print ("") 73 | print ("") 74 | print ("") 75 | print ("") 76 | print ("") 77 | print ("") 81 | if x.get('ranking'): 82 | print ("") 83 | print ("") 84 | print ("") 88 | print ("
" + str(x['id']) + " - " + x['summary'][:90] + "...
CVSS: " + str(x['cvss']) + " Published: " + str(x['Published']) + "
Summary: " + x['summary'] + "
Vulnerable configuration:
    ") 78 | for v in x['vulnerable_configuration']: 79 | sys.stdout.write("
  • " + cvelist.getcpe(v) + "
  • ") 80 | print ("
Ranking:" + str(x['ranking']) + "
References:
    ") 85 | for r in x['references']: 86 | sys.stdout.write("
  • " + str(r) + "
  • ") 87 | print ("

") 89 | if args.f == "rss1": 90 | print (feed.format_rss1_string()) 91 | elif args.f == "atom": 92 | print (feed.format_atom_string()) 93 | elif args.f == "html": 94 | print ("Generated with cve-search at " + str(datetime.datetime.today()) + ".") 95 | print ("") 96 | else: 97 | print (feed.format_rss2_string()) 98 | -------------------------------------------------------------------------------- /bin/search_cpe.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Software is free software released under the "Modified BSD license" 5 | # 6 | # Copyright (c) 2014 psychedelys 7 | # Copyright (c) 2015 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 8 | # Copyright (c) 2015 Alexandre Dulaunoy - a@foo.be 9 | 10 | # Imports 11 | import os 12 | import sys 13 | runPath = os.path.dirname(os.path.realpath(__file__)) 14 | sys.path.append(os.path.join(runPath, "..")) 15 | 16 | import re 17 | import argparse 18 | import json 19 | import urllib.parse 20 | 21 | import lib.DatabaseLayer as db 22 | 23 | runPath = os.path.dirname(os.path.realpath(__file__)) 24 | 25 | vOutput = "" 26 | 27 | argParser = argparse.ArgumentParser(description='Search for CPE with a pattern') 28 | argParser.add_argument('-s', type=str, required=True, help='search in cpe list') 29 | argParser.add_argument('-o', type=str, default='expanded' ,help='O = output format [expanded, compact, json] (default: expanded)') 30 | argParser.add_argument('-f', action='store_true', help='Enlarge the CPE search to all CPE indexed. Need the cpeother activated.', default=False) 31 | 32 | args = argParser.parse_args() 33 | cpeSearch = args.s 34 | vOutput = args.o 35 | 36 | 37 | def search(cpe): 38 | res = db.getCPEMatching(re.compile(cpe, re.IGNORECASE), args.f) 39 | 40 | if vOutput == "compact": 41 | for item in res: 42 | print(item['id']) 43 | elif vOutput == "expanded": 44 | for item in res: 45 | print(item['id'] + " " + item['title']) 46 | elif vOutput == "json": 47 | o = [] 48 | for item in res: 49 | x = {} 50 | x['id'] = item['id'] 51 | x['title'] = item['title'] 52 | o.append(x) 53 | print(json.dumps(o, sort_keys=True, indent=4)) 54 | 55 | 56 | 57 | # replace special characters in cpeSearch with encoded version. 58 | cpeSearch = urllib.parse.quote(cpeSearch) 59 | 60 | search(cpeSearch) 61 | -------------------------------------------------------------------------------- /bin/search_fulltext.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Search the CVE full text database 5 | # 6 | # Software is free software released under the "Modified BSD license" 7 | # 8 | # Copyright (c) 2012-2015 Alexandre Dulaunoy - a@foo.be 9 | # Copyright (c) 2015 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 10 | 11 | import os 12 | 13 | from whoosh import index, qparser 14 | from whoosh.fields import Schema, TEXT, ID 15 | from whoosh.qparser import QueryParser 16 | 17 | import sys 18 | import argparse 19 | import json 20 | from bson import json_util 21 | 22 | runPath = os.path.dirname(os.path.realpath(__file__)) 23 | sys.path.append(os.path.join(runPath, "..")) 24 | from lib.Config import Configuration 25 | 26 | indexpath = Configuration.getIndexdir() 27 | 28 | #basepath = os.path.join(os.sep, *os.path.dirname(os.path.realpath(__file__)).rsplit('/')[:-1]) 29 | #print (os.path.split(os.path.join(basepath,indexpath))) 30 | schema = Schema(title=TEXT(stored=True), path=ID(stored=True), content=TEXT) 31 | 32 | ix = index.open_dir(indexpath) 33 | 34 | argParser = argparse.ArgumentParser(description='Full text search for cve-search') 35 | argParser.add_argument('-q', action='append', help='query to lookup (one or more)') 36 | argParser.add_argument('-o', action='store_true', help='OR of the query to lookup (default is AND') 37 | argParser.add_argument('-t', action='store_true', help='output title of the match CVE(s)') 38 | argParser.add_argument('-f', action='store_true', help='output matching CVE(s) in JSON') 39 | argParser.add_argument('-m', type=int, default=False, help='most frequent terms in CVE description (m is top-m values)') 40 | argParser.add_argument('-l', action='store_true', default=False, help='dump all terms encountered in CVE description') 41 | argParser.add_argument('-g', action='store_true', default=False, help='graph of most frequent terms with each matching CVE (JSON output)') 42 | argParser.add_argument('-s', action='store_true', default=False, help='enable stemming on graph JSON output (default is False)') 43 | argParser.add_argument('-n', action='store_true', help='lookup complete cpe (Common Platform Enumeration) name for vulnerable configuration') 44 | argParser.add_argument('-r', action='store_true', help='lookup ranking of vulnerable configuration') 45 | args = argParser.parse_args() 46 | 47 | if not args.q and not args.l and not args.g and not args.m: 48 | argParser.print_help() 49 | exit(1) 50 | 51 | if args.f or args.t: 52 | from lib import CVEs 53 | cves = CVEs.last(rankinglookup=args.r, namelookup=args.n) 54 | 55 | if args.q: 56 | with ix.searcher() as searcher: 57 | if not args.o: 58 | query = QueryParser("content", ix.schema).parse(" ".join(args.q)) 59 | else: 60 | query = QueryParser("content", schema=ix.schema, group=qparser.OrGroup).parse(" ".join(args.q)) 61 | 62 | results = searcher.search(query, limit=None) 63 | for x in results: 64 | if not args.f: 65 | print (x['path']) 66 | else: 67 | print(json.dumps(cves.getcve(x['path']), sort_keys=True, default=json_util.default)) 68 | if args.t and not args.f: 69 | print (" -- " + x['title']) 70 | elif args.m: 71 | xr = ix.searcher().reader() 72 | for x in xr.most_frequent_terms("content", number=args.m): 73 | sys.stdout.write(str(int(x[0]))) 74 | sys.stdout.write(",") 75 | sys.stdout.write(x[1].decode('utf-8')) 76 | sys.stdout.write("\n") 77 | elif args.l and not args.g: 78 | xr = ix.searcher().reader() 79 | for x in xr.lexicon("content"): 80 | print (x) 81 | elif args.g: 82 | import json 83 | if args.s: 84 | from nltk.stem.wordnet import WordNetLemmatizer 85 | from nltk.corpus import stopwords 86 | lmtzr = WordNetLemmatizer() 87 | xr = ix.searcher().reader() 88 | s = {"name": 'cve-search', "children": []} 89 | d = {} 90 | for x in xr.most_frequent_terms("content", 3000): 91 | query = QueryParser("content", ix.schema).parse(x[1]) 92 | if args.s: 93 | term = lmtzr.lemmatize(x[1].decode('utf-8'), 'v') 94 | if term in stopwords.words('english'): 95 | continue 96 | else: 97 | term = x[1] 98 | term = term.decode('utf-8') 99 | if term in d: 100 | d[term]['size'] = d[term]['size'] + int(x[0]) 101 | else: 102 | d[term] = {} 103 | d[term]['size'] = int(x[0]) 104 | for k in sorted(d.keys(), key=lambda y: (d[y]['size']), reverse=True): 105 | v = {} 106 | v["name"] = k 107 | v["size"] = d[k]['size'] 108 | s['children'].append(v) 109 | print (json.dumps(s, indent=4)) 110 | else: 111 | argParser.print_help() 112 | exit(1) 113 | -------------------------------------------------------------------------------- /bin/search_irc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Simple IRC bot to query for the last entries in the CVE database 5 | # 6 | # current command supported is: 7 | # 8 | # last 9 | # cvetweet 10 | # browse 11 | # search \ 12 | # get 13 | # 14 | # You need to connect the IRC bot to the IRC Server you want to access it from. 15 | # 16 | # Software is free software released under the "Modified BSD license" 17 | # 18 | # Copyright (c) 2015 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 19 | 20 | # Imports 21 | import argparse 22 | import irc.bot 23 | import irc.strings 24 | import json 25 | import os 26 | import signal 27 | import ssl 28 | import sys 29 | runPath = os.path.dirname(os.path.realpath(__file__)) 30 | sys.path.append(os.path.join(runPath, "..")) 31 | 32 | # BSON MongoDB include ugly stuff that needs to be processed for standard JSON 33 | from bson import json_util 34 | 35 | from web.api import API 36 | 37 | argParser = argparse.ArgumentParser(description='IRC bot to query cve-search') 38 | argParser.add_argument('-s', type=str, help='server ip', default='localhost') 39 | argParser.add_argument('-p', type=int, help='server port)', default=6667) 40 | argParser.add_argument('-n', type=str, help='nickname', default='cve-search') 41 | argParser.add_argument('-w', type=str, help='password') 42 | argParser.add_argument('-u', type=str, help='username', default='cve-search') 43 | argParser.add_argument('-c', nargs="*", help='channel list', default=['cve-search']) 44 | argParser.add_argument('-t', type=str, help='trigger prefix', default='.') 45 | argParser.add_argument('-v', action='store_true', help='channel list', default=['cve-search']) 46 | argParser.add_argument('-m', type=int, help='maximum query amount', default=20) 47 | argParser.add_argument('--ssl', action='store_true', help='Use SSL') 48 | args = argParser.parse_args() 49 | 50 | class IRCBot(irc.bot.SingleServerIRCBot): 51 | def __init__(self, channel, nickname, server, port, password=None, username=None, **kwargs): 52 | if not username: 53 | username=nickname 54 | irc.bot.SingleServerIRCBot.__init__(self, [(server, port)], nickname, username, **kwargs) 55 | self.channel = channel 56 | self.api = API() 57 | 58 | def on_nicknameinuse(self, c, e): 59 | c.nick(c.get_nickname() + "_") 60 | 61 | def on_welcome(self, c, e): 62 | if args.v: 63 | print("Server welcomed us") 64 | for chan in self.channel: 65 | if not chan.startswith('#'):chan=("#%s"%chan) 66 | if args.v: 67 | print("joining %s"%chan) 68 | c.join(chan) 69 | 70 | def on_privmsg(self, c, e): 71 | self.do_command(e, e.arguments[0]) 72 | 73 | def on_pubmsg(self, c, e): 74 | line = e.arguments[0] 75 | if line.startswith(args.t): 76 | self.do_command(e, line[len(args.t):]) 77 | return 78 | 79 | def reply(self, e, reply): 80 | if type(reply) in [dict, list]: 81 | #reply = json.dumps(reply, sort_keys=True, indent=4, default=json_util.default, ensure_ascii=True) 82 | reply = json.dumps(reply, sort_keys=True, ensure_ascii=True, default=json_util.default) 83 | else: 84 | reply = str(reply) 85 | 86 | if e.target == self.connection.nickname: 87 | target=e.source.nick 88 | else: 89 | target=e.target 90 | _list = reply.split('\n') 91 | chunk_size = 512 - 12 - len(e.target) # 512 - len("PRIVMSG") - len(" :") - CR/LF - target 92 | 93 | _list = [[x[i:i+chunk_size] for i in range(0, len(x), chunk_size)] for x in _list] 94 | _list = [item for sublist in _list for item in sublist] # flatten list 95 | for r in _list[:4]: 96 | self.connection.privmsg(target, r) 97 | 98 | def do_command(self, e, cmd): 99 | def last(option): 100 | limit = int(option) if option else 10 101 | if limit > args.m or limit < 1: 102 | self.reply(e, "Request not in range 0-%d" % args.m) 103 | self.reply(e, self.api.api_last(limit)) 104 | def cve(option): 105 | if option is None: 106 | return "A cve-id must be specified" 107 | return self.api.api_cve(option) 108 | 109 | if not cmd: pass 110 | parts = cmd.split(' ', 1) 111 | cmd = parts[0] 112 | option = parts[1] if len(parts) == 2 else None 113 | 114 | if cmd == "die": self.die() 115 | elif cmd in ["last", "recent"]: self.reply(e, last(option)) 116 | elif cmd in ["get", "cve"]: self.reply(e, cve(option)) 117 | elif cmd in ["browse", "vendor"]: self.reply(e, self.api.api_browse(option)) 118 | elif cmd in ["search", "product"]: 119 | parts = option.split() 120 | if len(parts) < 2: 121 | return self.reply(e, "Usage: search ") 122 | return self.reply(e, self.api.api_search(parts[0], parts[1])) 123 | elif cmd in ["cvetweet", "tweet"]: 124 | text = "" 125 | cves = [] 126 | if option.lower().startswith("cve-"): cves.append(cve(option)) 127 | else: cves = last(option) 128 | for t in cves: 129 | text += str(t['id']) + " , " + str(t['summary']) + " " + " , ".join(t['references']) + "\n" 130 | return self.reply(e, text) 131 | else: 132 | self.reply(e, "Not understood: " + cmd) 133 | 134 | # signal handlers 135 | def sig_handler(sig, frame): 136 | print('Caught signal: %s\nShutting down' % sig) 137 | bot.die() 138 | 139 | def main(): 140 | server = args.s 141 | port = args.p 142 | nick = args.n 143 | password = args.w 144 | user = args.u 145 | chans = args.c 146 | global bot 147 | 148 | if args.ssl: 149 | print("using ssl") 150 | ssl_factory = irc.connection.Factory(wrapper=ssl.wrap_socket) 151 | bot=IRCBot(chans, nick, server, port, password=password,username=user, connect_factory=ssl_factory) 152 | else: 153 | bot=IRCBot(chans, nick, server, port, password=password,username=user) 154 | signal.signal(signal.SIGTERM, sig_handler) 155 | signal.signal(signal.SIGINT, sig_handler) 156 | if args.v: 157 | print("Connecting to server") 158 | bot.start() 159 | 160 | if __name__ == "__main__": 161 | main() 162 | -------------------------------------------------------------------------------- /doc/html/Structure.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CVE-Search structure - CVE-Search 5 | 6 | 7 | 8 | 9 | 10 | 11 |

CVE-Search Structure

12 |

Mongo Database Structure

13 |

14 | This section describes the structure of the Mongo database. There are two types of collections, data and management. 15 | The data collections, which are listed below, are the collections that are filled by the sources CVE-Search uses. 16 | By default, these are the official sources.
17 |
18 | These are the data collections: 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
Collection Source Description
cves NVD NIST All the official vulnerabilities, released by NIST. Items in this collection have all info related to each CVE
cpe NVD NIST All the official products, released by NIST. Some of these have a human readable title.
cpeother CVE-Search CVE-Search has a script to fill this database, using the original CPE's and generating titles for them.
cwe NVD NIST Information about Common Weaknesses, as published by NIST
d2sec d2sec.com Information about CVE's, as released by d2sec
vendor NVD NIST Vendor statements, released by NIST
info CVE-Search Information about the Mongo Database updates.
31 |
32 | These are the management collections: 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
Collection Description
ranking Self-set ranking for specific CPE's that are more important to specific groups
mgmt_blacklist List of CPE's that have to be excluded from the web view. More about this here
mgmt_whitelist List of CPE's that have to be marked in the web view. More about this here
mgmt_users List of users who have access to the administrative panel. More about this here
42 |
43 | By default, the Mongo database name is cvedb. This connection for the database is made on localhost, port 27017. 44 |

45 | 46 |

Redis Cache Database

47 |

48 | The Redis Caching server is used to speed up the searches in the web component. It is also used for the notifications script.
49 | By default, The database used for speeding up the searches is database number 10, and the vendor database is database 11.
50 | The vendor database (database 10) contains four collections. These are: 51 |

    52 |
  • prefix
  • 53 |
  • types
  • 54 |
  • vendors
  • 55 |
  • Products
  • 56 |
57 | These lists get filled by the db_cpe_browser.py script, and create "links" to each other. 58 | Feel free to take a look at db_cpe_browser.py to learn how it works.
59 |
60 | The notifications cache has a structure where it keeps track of: 61 |
    62 |
  • Organisations
  • 63 |
  • CPE's
  • 64 |
  • MailTo destination
  • 65 |
66 | Feel free to take a look at db_notifications.py to learn how it works.
67 |

68 | 69 | 70 | -------------------------------------------------------------------------------- /doc/html/css/style.css: -------------------------------------------------------------------------------- 1 | body{ 2 | margin-left: auto; 3 | margin-right: auto; 4 | width: 80%; 5 | background-color: #FDEAD7; 6 | } 7 | table{ 8 | border-collapse: collapse; 9 | } 10 | thead{ 11 | font-weight: bold; 12 | } 13 | table, th, td{ 14 | padding: 7px; 15 | border: solid 1px black; 16 | } 17 | span{ 18 | border-bottom: 1px solid; 19 | } 20 | .code{ 21 | border-bottom: none; 22 | color: #123212; 23 | font-family: Courier; 24 | font-weight: bold; 25 | } 26 | .highlight{ 27 | color: #B30000; 28 | } 29 | .example{ 30 | border-bottom: none; 31 | font-style: italic; 32 | } 33 | -------------------------------------------------------------------------------- /doc/markdown/api.md: -------------------------------------------------------------------------------- 1 | ## cve-search HTTP API 2 | 3 | The HTTP API outputs JSON. The API accessible if you run at least minimal-web.py. 4 | 5 | 6 | ### Browse vendor and product 7 | 8 | 9 | To get a JSON with all the vendors: 10 | 11 | ~~~ 12 | curl http:///api/browse 13 | ~~~ 14 | 15 | To get a JSON with all the products associated to a vendor: 16 | 17 | ~~~ 18 | curl http:///api/browse/microsoft 19 | ~~~ 20 | 21 | ### Browse CVEs per vendor/product 22 | 23 | To get a JSON with all the vulnerabilities per vendor and a specific product: 24 | 25 | ~~~ 26 | curl http:///api/search/microsoft/office 27 | ~~~ 28 | 29 | ### Get CVE per CVE-ID 30 | 31 | To get a JSON of a specific CVE ID: 32 | 33 | ~~~ 34 | curl http:///api/cve/CVE-2010-3333 35 | ~~~ 36 | 37 | ### Get the last updated CVEs 38 | 39 | To get a JSON of the last 30 CVEs including CAPEC, CWE and CPE expansions: 40 | 41 | ~~~ 42 | curl http:///api/last 43 | ~~~ 44 | 45 | ### Get more information about the current CVE database 46 | 47 | To get more information about the current databases in use and when it was updated: 48 | 49 | ~~~ 50 | curl http:///api/dbInfo 51 | ~~~ 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /doc/markdown/structure.md: -------------------------------------------------------------------------------- 1 | # CVE-Search structure 2 | ## Mongo Database Structure 3 | This section describes the structure of the Mongo database. There are 4 | two types of collections, data and management. 5 | The data collections, which are listed below, are the collections that 6 | are filled by the sources CVE-Search uses. 7 | By default, these are the official sources. 8 | 9 | **These are the data collections:** 10 | 11 | | Collection | Source | Description | 12 | | :--- | :--- | :--- | 13 | | cves | NVD NIST | All the official vulnerabilities, released by NIST. Items in this collection have all info related to each CVE | 14 | | cpe | NVD NIST | All the official products, released by NIST. Some of these have a human readable title. | 15 | | cpeother | CVE-Search | CVE-Search has a script to fill this database, using the original CPE's and generating titles for them. | 16 | | cwe | NVD NIST | Information about Common Weaknesses, as published by NIST | 17 | | d2sec | d2sec.com | Information about CVE's, as released by d2sec | 18 | | vendor | NVD NIST | Vendor statements, released by NIST | 19 | | info | CVE-Search | Information about the Mongo Database updates. | 20 | 21 | **These are the management collections:** 22 | 23 | | Collection | Description | 24 | | :--- | :--- | 25 | | ranking | Self-set ranking for specific CPE's that are more important to specific groups | 26 | | mgmt_blacklist | List of CPE's that have to be excluded from the web view. More about this [here](./webcomponent.md) | 27 | | mgmt_whitelist | List of CPE's that have to be marked in the web view. More about this [here](./webcomponent.md)> | 28 | | mgmt_users | List of users who have access to the administrative panel. More about this [here](./webcomponent.md) | 29 | 30 | By default, the Mongo database name is cvedb. This connection for the 31 | database is made on localhost, port 27017. 32 | 33 | ##Redis Cache Database 34 | The Redis Caching server is used to speed up the searches in the web 35 | component. It is also used for the notifications script.
36 | By default, The database used for speeding up the searches is database 37 | number 10, and the vendor database is database 11.
38 | The vendor database (database 10) contains four collections. These are: 39 | 40 | * prefix 41 | * types 42 | * vendors 43 | * Products 44 | 45 | These lists get filled by the *db_cpe_browser.py* script, and create 46 | "links" to each other. Feel free to take a look at *db_cpe_browser.py* 47 | to learn how it works.

48 | The notifications cache has a structure where it keeps track of: 49 | 50 | * Organisations 51 | * CPEs 52 | * MailTo destination 53 | 54 | Feel free to take a look at *db_notifications.py* to learn how it works. 55 | -------------------------------------------------------------------------------- /etc/auth.txt.sample: -------------------------------------------------------------------------------- 1 | # Module required/sufficient args 2 | #LDAP required domain=example server=server.example.internal sync=True 3 | -------------------------------------------------------------------------------- /etc/configuration.ini.sample: -------------------------------------------------------------------------------- 1 | [Redis] 2 | Host: localhost 3 | Port: 6379 4 | VendorsDB: 10 5 | NotificationsDB: 11 6 | RefDB: 12 7 | [Mongo] 8 | Host: localhost 9 | Port: 27017 10 | DB: cvedb 11 | [dbmgt] 12 | Tmpdir: ./tmp/ 13 | [FulltextIndex] 14 | Indexdir: ./indexdir/ 15 | [Webserver] 16 | Host: 127.0.0.1 17 | Port: 5000 18 | Debug: True 19 | PageLength: 50 20 | LoginRequired: False 21 | SSL: True 22 | Certificate: ssl/cve-search.crt 23 | Key: ssl/cve-search.key 24 | [Logging] 25 | Logging: True 26 | Logfile: log/cve-search.log 27 | MaxSize: 150MB 28 | Backlog: 5 29 | [CVE] 30 | DefaultCVSS: 5 31 | StartYear: 2002 32 | -------------------------------------------------------------------------------- /etc/plugins.txt.sample: -------------------------------------------------------------------------------- 1 | # Plugin Location load/default/pass 2 | # path/to/plugin setting 3 | -------------------------------------------------------------------------------- /etc/sources.ini.sample: -------------------------------------------------------------------------------- 1 | [Sources] 2 | CVE: https://static.nvd.nist.gov/feeds/xml/cve/ 3 | CPE: https://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.2.xml.zip 4 | CWE: http://cwe.mitre.org/data/xml/cwec_v2.8.xml.zip 5 | Vendor: https://nvd.nist.gov/download/vendorstatements.xml.gz 6 | CAPEC: http://capec.mitre.org/data/xml/capec_v2.6.xml 7 | VIA4: http://www.cve-search.org/feeds/via4.json 8 | -------------------------------------------------------------------------------- /lib/Authentication.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Plugin manager 5 | # 6 | # Software is free software released under the "Modified BSD license" 7 | # 8 | # Copyright (c) 2016 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 9 | 10 | # Imports 11 | import datetime 12 | import importlib 13 | import os 14 | import sys 15 | import uuid 16 | 17 | runPath = os.path.dirname(os.path.realpath(__file__)) 18 | sys.path.append(os.path.join(runPath, "..")) 19 | 20 | import lib.DatabaseLayer as db 21 | from lib.Config import Configuration as conf 22 | from lib.Singleton import Singleton 23 | 24 | # Constants 25 | UNREACHABLE = -1 26 | WRONG_CREDS = 0 27 | AUTHENTICATED = 1 28 | 29 | class AuthenticationMethod: 30 | # Force users to override this 31 | def validateUser(self, user, pwd): 32 | return WRONG_CREDS 33 | 34 | class AuthenticationHandler(metaclass=Singleton): 35 | def __init__(self, **kwargs): 36 | self.methods = [] 37 | self._load_methods() 38 | self.api_sessions = {} 39 | 40 | def _load_methods(self): 41 | self.methods = [] 42 | if not os.path.exists(conf.getAuthLoadSettings()): 43 | print("[!] Could not find auth loader file!") 44 | return 45 | # Read and parse plugin file 46 | data = open(conf.getAuthLoadSettings(), "r").read() 47 | data = [x.split(maxsplit=2) for x in data.splitlines() if not x.startswith("#") and x] 48 | for x in [x for x in data if len(x) in [2, 3]]: 49 | try: 50 | x.extend(['']*(3-len(x))) # add empty args if none exist 51 | method, authType, args = x 52 | if authType.lower() not in ["required", "sufficient"]: # Skip if authType not known 53 | continue 54 | # Create object 55 | args = {y.split("=")[0]: y.split("=")[1] for y in args.split()} 56 | i = importlib.import_module("lib.authenticationMethods.%s"%method) 57 | authMethod = getattr(i, method.split("/")[-1])(**args) 58 | # Add object to list 59 | self.methods.append((method, authType.lower(), authMethod)) 60 | print("[+] Loaded Auth Method %s"%x[0]) 61 | except Exception as e: 62 | print("[!] Failed to load Auth Method %s: "%x[0]) 63 | print("[!] -> %s"%e) 64 | 65 | def isCVESearchUser(self, user): 66 | return db.userExists(user) 67 | 68 | def validateUser(self, user, password): 69 | user_obj = db.getUser(user) 70 | if not user_obj: return False 71 | # 'local_only' users bypass other auth methods. If the user is not, 72 | # we try the other auth methods first 73 | if (not "local_only" in user_obj.keys() 74 | or user_obj["local_only"] is False): 75 | for name, authType, method in self.methods: 76 | try: 77 | result = method.validateUser(user, password) 78 | if result is UNREACHABLE: continue # Skip to next 79 | if result is AUTHENTICATED: return True # Successful 80 | if (authType == "required" and result is WRONG_CREDS): return False 81 | if (authType == "sufficient" and result is WRONG_CREDS): continue 82 | except Exception as e: 83 | print("[!] Exception trying to authenticate user: %s: "%name) 84 | print("[!] -> %s"%e) 85 | # If we reach here, all methods (if any) failed to authenticate the user 86 | # so we check the user against the local database. 87 | return db.verifyUser(user, password) 88 | 89 | def new_api_session(self, user): 90 | self.api_sessions[user] = (uuid.uuid4().hex, datetime.datetime.now()) 91 | return self.api_sessions[user][0] 92 | 93 | def get_api_session(self, user, extend=True): 94 | return self.api_sessions.get(user) 95 | -------------------------------------------------------------------------------- /lib/CVEs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Minimal class to get the last entries from the CVE database. 5 | # 6 | # Ranking and CPE lookup are optional. 7 | # 8 | # Software is free software released under the "Modified BSD license" 9 | # 10 | # Copyright (c) 2012-2015 Alexandre Dulaunoy - a@foo.be 11 | # Copyright (c) 2015-2016 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 12 | 13 | # Imports 14 | import os 15 | import sys 16 | runPath = os.path.dirname(os.path.realpath(__file__)) 17 | sys.path.append(os.path.join(runPath, "..")) 18 | 19 | import itertools 20 | import math 21 | 22 | from lib.Config import Configuration 23 | from lib.Toolkit import exploitabilityScore,impactScore 24 | import lib.DatabaseLayer as db 25 | 26 | class last(): 27 | def __init__(self, collection="cves", rankinglookup=False, 28 | namelookup=False, capeclookup=False, via4lookup=False, 29 | subscorelookup=False): 30 | 31 | self.collectionname = collection 32 | self.rankinglookup = rankinglookup 33 | self.namelookup = namelookup 34 | self.capeclookup = capeclookup 35 | self.subscorelookup = subscorelookup 36 | self.via4lookup = via4lookup 37 | 38 | self.collection = collection 39 | 40 | def getcapec(self, cweid=None): 41 | if cweid is None or not self.capeclookup: 42 | return False 43 | e = db.getCAPECFor(cweid) 44 | capec = [] 45 | for f in e: 46 | capec.append(f) 47 | return capec 48 | 49 | def getcpe(self, cpeid=None): 50 | if not(self.namelookup): 51 | return cpeid 52 | e = db.getCPE(cpeid) 53 | if e is None: 54 | e = db.getAlternativeCPE(cpeid) 55 | if e is None: 56 | return cpeid 57 | if 'id' in e: 58 | return e['title'] 59 | 60 | def getVIA4(self, cveid=None): 61 | if not(self.via4lookup): 62 | return cveid 63 | e = db.getVIA4(cveid) 64 | return e if e else cveid 65 | 66 | def getcve(self, cveid=None): 67 | if cveid is not None: 68 | e = db.getCVE(cveid, collection=self.collection) 69 | if e is None: 70 | return None 71 | if "cwe" in e and self.capeclookup: 72 | if e['cwe'].lower() != 'unknown': 73 | e['capec'] = self.getcapec(cweid=(e['cwe'].split('-')[1])) 74 | if "vulnerable_configuration" in e: 75 | vulconf = [] 76 | ranking = [] 77 | for conf in e['vulnerable_configuration']: 78 | vulconf.append({'id': conf, 'title': self.getcpe(cpeid=conf)}) 79 | if self.rankinglookup: 80 | rank = self.getranking(cpeid=conf) 81 | if rank and rank not in ranking: 82 | ranking.append(rank) 83 | e['vulnerable_configuration'] = vulconf 84 | if self.rankinglookup and len(ranking) > 0: 85 | e['ranking'] = ranking 86 | if self.via4lookup: 87 | f = self.getVIA4(cveid) 88 | if isinstance(f, dict): 89 | e = dict(itertools.chain(e.items(), f.items())) 90 | if self.subscorelookup: 91 | exploitCVSS=exploitabilityScore(e) 92 | impactCVSS =impactScore(e) 93 | e['exploitCVSS']=(math.ceil(exploitCVSS*10)/10) if type(exploitCVSS) is not str else exploitCVSS 94 | e['impactCVSS']=(math.ceil(impactCVSS*10)/10) if type(impactCVSS) is not str else impactCVSS 95 | else: 96 | e = None 97 | 98 | return e 99 | 100 | def getranking(self, cpeid=None, loosy=True): 101 | 102 | if cpeid is None: 103 | return False 104 | 105 | result = False 106 | 107 | if loosy: 108 | for x in cpeid.split(':'): 109 | if x is not '': 110 | i = db.findRanking(x, regex=True) 111 | if i is None: 112 | continue 113 | if 'rank' in i: 114 | result = i['rank'] 115 | else: 116 | i = db.findRanking(cpeid, regex=True) 117 | if i is None: 118 | return result 119 | if 'rank' in i: 120 | result = i['rank'] 121 | 122 | return result 123 | 124 | def get(self, limit=5, skip=0): 125 | entries = [] 126 | for item in db.getCVEs(limit=limit, skip=skip, collection=self.collection): 127 | if not(self.namelookup) and not(self.rankinglookup): 128 | entries.append(item) 129 | elif self.namelookup or self.rankinglookup: 130 | if "vulnerable_configuration" in item: 131 | vulconf = [] 132 | ranking = [] 133 | for conf in item['vulnerable_configuration']: 134 | vulconf.append(self.getcpe(cpeid=conf)) 135 | if self.rankinglookup: 136 | rank = self.getranking(cpeid=conf) 137 | if rank and rank not in ranking: 138 | ranking.append(rank) 139 | item['vulnerable_configuration'] = vulconf 140 | if self.rankinglookup: 141 | item['ranking'] = ranking 142 | if "ranking" in item: 143 | if len(item['ranking']) == 0: 144 | del(item['ranking']) 145 | if "cwe" in item and self.capeclookup: 146 | if item['cwe'].lower() != 'unknown': 147 | item['capec'] = self.getcapec(cweid=(item['cwe'].split('-')[1])) 148 | entries.append(item) 149 | 150 | return (entries) 151 | 152 | def __exit__(self, type, value, traceback): 153 | self.dbname.disconnect() 154 | -------------------------------------------------------------------------------- /lib/Plugins.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Plugin Classes 5 | # Classes for all plug-ins to be based on 6 | # 7 | # Software is free software released under the "Modified BSD license" 8 | # 9 | # Copyright (c) 2016 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 10 | 11 | class Plugin(): 12 | def __init__(self): 13 | self.name = None 14 | self.uid = None 15 | self.requiresAuth = False 16 | self.loadstate = "default" 17 | 18 | # Get 19 | def getName(self): return self.name 20 | def getUID(self): return self.uid 21 | def getLoadState(self): return self.loadstate 22 | # Set 23 | def setUID(self, uid): self.uid = uid 24 | def setLoadState(self, state): self.loadstate = state 25 | # Don't override 26 | def isWebPlugin(self): return False 27 | # To override without returns 28 | def loadSettings(self, reader): pass 29 | def onDatabaseUpdate(self): pass 30 | # To override with returns 31 | def search(self, text, **args): pass 32 | 33 | 34 | class WebPlugin(Plugin): 35 | # Don't override 36 | def isWebPlugin(self): return True 37 | # To override with returns 38 | def getPage(self, **args): return (None, None) 39 | def getSubpage(self, page, **args): return (None, None) 40 | def getCVEActions(self, cve, **args): return [] 41 | def getFilters(self, **args): return [] 42 | def doFilter(self, filters, **args): return [] 43 | def cvePluginInfo(self, cve, **args): pass 44 | def mark(self, cve, **args): return (None, None) 45 | # To override without returns 46 | def onCVEAction(self, cve, action, **args): pass 47 | def onCVEOpen(self, cve, **args): pass 48 | -------------------------------------------------------------------------------- /lib/ProgressBar.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Progress bar by Michael Grünewald 5 | # 6 | # Software is free software released under the "Modified BSD license" 7 | # 8 | # Copyright (c) 2015 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 9 | 10 | import sys 11 | 12 | 13 | def progressbar(it, prefix="Preparing ", size=50): 14 | count = len(it) 15 | 16 | def _show(_i): 17 | if count != 0 and sys.stdout.isatty(): 18 | x = int(size * _i / count) 19 | sys.stdout.write("%s[%s%s] %i/%i\r" % (prefix, "#" * x, " " * (size - x), _i, count)) 20 | sys.stdout.flush() 21 | 22 | _show(0) 23 | for i, item in enumerate(it): 24 | yield item 25 | _show(i + 1) 26 | sys.stdout.write("\n") 27 | sys.stdout.flush() 28 | -------------------------------------------------------------------------------- /lib/Query.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Query tools 5 | # 6 | # Software is free software released under the "Modified BSD license" 7 | # 8 | # Copyright (c) 2014-2015 Alexandre Dulaunoy - a@foo.be 9 | # Copyright (c) 2014-2015 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 10 | 11 | import urllib.parse 12 | import requests 13 | 14 | import os 15 | import sys 16 | runPath = os.path.dirname(os.path.realpath(__file__)) 17 | sys.path.append(os.path.join(runPath, "..")) 18 | 19 | import lib.CVEs as cves 20 | import lib.DatabaseLayer as db 21 | import lib.Toolkit as tk 22 | 23 | from lib.Config import Configuration 24 | 25 | rankinglookup = True 26 | redisdb = Configuration.getRedisVendorConnection() 27 | 28 | def findranking(cpe=None, loosy=True): 29 | if cpe is None: 30 | return False 31 | result = False 32 | if loosy: 33 | for x in cpe.split(':'): 34 | if x is not '': 35 | i = db.findRanking(cpe, regex=True) 36 | if i is None: 37 | continue 38 | if 'rank' in i: 39 | result = i['rank'] 40 | else: 41 | i = db.findRanking(cpe, regex=True) 42 | print (cpe) 43 | if i is None: 44 | return result 45 | if 'rank' in i: 46 | result = i['rank'] 47 | return result 48 | 49 | def lookupcpe(cpeid=None): 50 | e = db.getCPE(cpeid) 51 | if e is None: 52 | return cpeid 53 | if 'id' in e: 54 | return e['title'] 55 | 56 | 57 | def lastentries(limit=5, namelookup=False, rankinglookup=True): 58 | entries = [] 59 | for item in db.getCVEs(limit): 60 | if not namelookup and rankinglookup is not True: 61 | entries.append(item) 62 | else: 63 | if "vulnerable_configuration" in item: 64 | vulconf = [] 65 | ranking = [] 66 | for conf in item['vulnerable_configuration']: 67 | if namelookup: 68 | vulconf.append(lookupcpe(cpeid=conf)) 69 | else: 70 | vulconf.append(conf) 71 | if rankinglookup: 72 | rank = findranking(cpe=conf) 73 | if rank and rank not in ranking: 74 | ranking.append(rank) 75 | item['vulnerable_configuration'] = vulconf 76 | if rankinglookup and len(ranking) > 0: 77 | item['ranking'] = ranking 78 | entries.append(item) 79 | return entries 80 | 81 | def apigetcve(api, cveid=None): 82 | if cveid is None: 83 | return False 84 | url = urllib.parse.urljoin(api, "api/cve/"+cveid) 85 | urltoget = urllib.parse.urljoin(url, cveid) 86 | r = requests.get(urltoget) 87 | if r.status_code is 200: 88 | return r.text 89 | else: 90 | return False 91 | 92 | def apibrowse(api, vendor=None): 93 | url = urllib.parse.urljoin(api, "api/browse") 94 | if vendor is None: 95 | r = requests.get(url) 96 | else: 97 | urlvendor = url + "/" + vendor 98 | r = requests.get(urlvendor) 99 | 100 | if r.status_code is 200: 101 | return r.text 102 | else: 103 | return False 104 | 105 | def apisearch(api, query=None): 106 | if query is None: 107 | return False 108 | url = urllib.parse.urljoin(api, "api/search/") 109 | url = url+query 110 | 111 | r = requests.get(url) 112 | if r.status_code is 200: 113 | return r.text 114 | else: 115 | return False 116 | 117 | 118 | 119 | # Lastly added 120 | def cvesForCPE(cpe): 121 | cpe = tk.toStringFormattedCPE(cpe) 122 | data = [] 123 | if cpe: 124 | cvesp = cves.last(rankinglookup=False, namelookup=False, via4lookup=True, capeclookup=False) 125 | for x in db.cvesForCPE(cpe): 126 | data.append(cvesp.getcve(x['id'])) 127 | return data 128 | 129 | def getBrowseList(vendor): 130 | result = {} 131 | if (vendor is None) or type(vendor) == list: 132 | v1 = redisdb.smembers("t:/o") 133 | v2 = redisdb.smembers("t:/a") 134 | v3 = redisdb.smembers("t:/h") 135 | vendor = sorted(list(set(list(v1) + list(v2) + list(v3)))) 136 | cpe = None 137 | else: 138 | cpenum = redisdb.scard("v:" + vendor) 139 | if cpenum < 1: 140 | return None 141 | p = redisdb.smembers("v:" + vendor) 142 | cpe = sorted(list(p)) 143 | result["vendor"] = vendor 144 | result["product"] = cpe 145 | return result 146 | 147 | def getVersionsOfProduct(product): 148 | p = redisdb.smembers("p:" + product) 149 | return sorted(list(p)) 150 | -------------------------------------------------------------------------------- /lib/Singleton.py: -------------------------------------------------------------------------------- 1 | class Singleton(type): 2 | _instances = {} 3 | def __call__(cls, *args, **kwargs): 4 | if cls not in cls._instances: 5 | cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) 6 | return cls._instances[cls] 7 | -------------------------------------------------------------------------------- /lib/Toolkit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Toolkit for functions between scripts 5 | # 6 | # Software is free software released under the "Modified BSD license" 7 | # 8 | # Copyright (c) 2014-2016 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 9 | 10 | # Imports 11 | from dateutil import tz 12 | import dateutil.parser 13 | import re 14 | 15 | # Note of warning: CPEs like cpe:/o:microsoft:windows_8:-:-:x64 are given to us by Mitre 16 | # x64 will be parsed as Edition in this case, not Architecture 17 | def toStringFormattedCPE(cpe,autofill=False): 18 | cpe=cpe.strip() 19 | if not cpe.startswith('cpe:2.3:'): 20 | if not cpe.startswith('cpe:/'): return False 21 | cpe=cpe.replace('cpe:/','cpe:2.3:') 22 | cpe=cpe.replace('::',':-:') 23 | cpe=cpe.replace('~-','~') 24 | cpe=cpe.replace('~',':-:') 25 | cpe=cpe.replace('::',':') 26 | cpe=cpe.strip(':-') 27 | if autofill: 28 | e=cpe.split(':') 29 | for x in range(0,13-len(e)): 30 | cpe+=':-' 31 | return cpe 32 | 33 | # Note of warning: Old CPE's can come in different formats, and are not uniform. Possibilities are: 34 | # cpe:/a:7-zip:7-zip:4.65::~~~~x64~ 35 | # cpe:/a:7-zip:7-zip:4.65:-:~~~~x64~ 36 | # cpe:/a:7-zip:7-zip:4.65:-:~-~-~-~x64~ 37 | def toOldCPE(cpe): 38 | cpe=cpe.strip() 39 | if not cpe.startswith('cpe:/'): 40 | if not cpe.startswith('cpe:2.3:'): return False 41 | cpe=cpe.replace('cpe:2.3:','') 42 | parts = cpe.split(':') 43 | next = [] 44 | first= "cpe:/"+":".join(parts[:5]) 45 | last = parts[5:] 46 | if last: 47 | for x in last: 48 | next.append('~') if x == "-" else next.append(x) 49 | if "~" in next: 50 | pad(next,6,"~") 51 | cpe="%s:%s"%(first,"".join(next)) 52 | cpe=cpe.replace(':-:','::') 53 | cpe=cpe.strip(":") 54 | return cpe 55 | 56 | def impactScore(cve): 57 | score={'NONE':0,'PARTIAL':0.275,'COMPLETE':0.660} 58 | try: 59 | C=((cve['impact'])['confidentiality']).upper() 60 | I=((cve['impact'])['integrity']).upper() 61 | A=((cve['impact'])['availability']).upper() 62 | res = 10.41*(1-(1-score[C])*(1-score[I])*(1-score[A])) 63 | return 10.0 if res > 10.0 else res 64 | except: 65 | return '-' 66 | 67 | def exploitabilityScore(cve): 68 | cScore={'LOW':0.71,'MEDIUM':0.61,'HIGH':0.35} 69 | vScore={'NETWORK':1.0,'ADJACENT_NETWORK':0.646,'LOCAL':0.395} 70 | aScore={'NONE':0.704,'SINGLE_INSTANCE':0.56,'MULTIPLE_INSTANCES':0.45} 71 | try: 72 | C=((cve['access'])['complexity']).upper() 73 | V=((cve['access'])['vector']).upper() 74 | A=((cve['access'])['authentication']).upper() 75 | return 20* cScore[C]*vScore[V]*aScore[A] 76 | except: 77 | return '-' 78 | 79 | def pad(seq, target_length, padding=None): 80 | length = len(seq) 81 | if length > target_length: 82 | return seq 83 | seq.extend([padding] * (target_length - length)) 84 | return seq 85 | 86 | def currentTime(utc): 87 | timezone = tz.tzlocal() 88 | utc = dateutil.parser.parse(utc) 89 | output = utc.astimezone(timezone) 90 | output = output.strftime('%d-%m-%Y - %H:%M') 91 | return output 92 | 93 | def isURL(string): 94 | urlTypes= [re.escape(x) for x in ['http://','https://', 'www.']] 95 | return re.match("^(" + "|".join(urlTypes) + ")", string) 96 | 97 | def vFeedName(string): 98 | string=string.replace('map_','') 99 | string=string.replace('cve_','') 100 | return string.title() 101 | 102 | def mergeSearchResults(database, plugins): 103 | if 'errors' in database: 104 | results = {'data':[], 'errors':database['errors']} 105 | else: 106 | results = {'data': []} 107 | 108 | data = [] 109 | data.extend(database['data']) 110 | data.extend(plugins['data']) 111 | for cve in data: 112 | if not any(cve['id']==entry['id'] for entry in results['data']): 113 | results['data'].append(cve) 114 | return results 115 | 116 | def compile(regexes): 117 | if type(regexes) not in [list, tuple]: regexes = [regexes] 118 | r=[] 119 | for rule in regexes: 120 | r.append(re.compile(rule)) 121 | return r 122 | -------------------------------------------------------------------------------- /lib/User.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Admin creator script 5 | # 6 | # Creates an admin account in the database 7 | # Only master accounts are allowed to add and remove users 8 | # First account registered is the master account 9 | # 10 | # Software is free software released under the "Modified BSD license" 11 | # 12 | # Copyright (c) 2015 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 13 | 14 | # Imports 15 | import os 16 | runPath = os.path.dirname(os.path.realpath(__file__)) 17 | 18 | from flask_login import UserMixin 19 | 20 | from lib.Config import Configuration 21 | import lib.DatabaseLayer as db 22 | 23 | # Exception 24 | class UserNotFoundError(Exception): 25 | pass 26 | 27 | # Class 28 | class User(UserMixin): 29 | def __init__(self, id, auth_instance): 30 | '''Simple User class''' 31 | if not Configuration.loginRequired(): 32 | # dummy account for when logon is not required. 33 | self.id = "_dummy_" 34 | else: 35 | if not auth_instance.isCVESearchUser(id): 36 | raise UserNotFoundError() 37 | self.id = id 38 | self.authenticator = auth_instance 39 | 40 | def authenticate(self, password): 41 | return self.authenticator.validateUser(self.id, password) 42 | 43 | @classmethod 44 | def get(self_class, id , auth_instance): 45 | '''Return user instance of id, return None if not exist''' 46 | try: 47 | return self_class(id, auth_instance) 48 | except UserNotFoundError: 49 | return None 50 | -------------------------------------------------------------------------------- /lib/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /lib/authenticationMethods/readme.md: -------------------------------------------------------------------------------- 1 | # Authentication Modules 2 | Put your authentication modules in here. More information can be found 3 | [here](https://github.com/cve-search/Plugins/tree/master/auth) 4 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | click 2 | flask 3 | flask-login<=0.2.11 4 | flask-pymongo 5 | irc 6 | itsdangerous 7 | lxml 8 | passlib 9 | python-dateutil 10 | pytz 11 | redis 12 | requests 13 | six>=1.9.0 14 | sleekxmpp 15 | tornado 16 | whoosh 17 | xlrd 18 | 19 | Jinja2 20 | PyMongo>=2.7 21 | Werkzeug 22 | 23 | https://github.com/marianoguerra/feedformatter/archive/master.zip 24 | -------------------------------------------------------------------------------- /sbin/db_blacklist.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Blacklist feature to mark CVE's for CPE's of personal interest 5 | # 6 | # Software is free software released under the "Modified BSD license" 7 | # 8 | # Copyright (c) 2014-2016 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 9 | 10 | # Imports 11 | # make sure these modules are available on your system 12 | import os 13 | import sys 14 | runPath = os.path.dirname(os.path.realpath(__file__)) 15 | sys.path.append(os.path.join(runPath, "..")) 16 | 17 | import argparse 18 | 19 | from lib.cpelist import CPEList 20 | 21 | # parse command line arguments 22 | argparser = argparse.ArgumentParser(description='populate/update the blacklist used in webviews') 23 | argparser.add_argument('-a', metavar="CPE", nargs="*", help='Add one or more CPE to the blacklist') 24 | argparser.add_argument('-A', action='append', metavar="file", help='Read a file of CPEs and add them to the blacklist') 25 | argparser.add_argument('-r', metavar="CPE", nargs="*", help='Remove one or more CPE from the blacklist') 26 | argparser.add_argument('-R', action='append', metavar="file", help='Read a file of CPEs and remove them from the blacklist') 27 | argparser.add_argument('-t', metavar="type", default="cpe", help='Type of item to blacklist. Default: CPE') 28 | argparser.add_argument('-i', metavar="file", help='Import blacklist from file') 29 | argparser.add_argument('-e', metavar="file", help='Export blacklist to file') 30 | argparser.add_argument('-d', action='store_true', help='Drop the blacklist') 31 | argparser.add_argument('-f', action='store_true', help='Force') 32 | argparser.add_argument('-v', action='store_true', help='Verbose') 33 | args = argparser.parse_args() 34 | 35 | # Variables 36 | collection = "blacklist" 37 | 38 | # Functions 39 | def importBlacklist(importFile): 40 | oList = CPEList(collection, args) 41 | return oList.importList(importFile) 42 | 43 | 44 | def exportBlacklist(exportFile=None): 45 | oList = CPEList(collection, args) 46 | return oList.exportList(exportFile) 47 | 48 | 49 | def dropBlacklist(): 50 | oList = CPEList(collection, args) 51 | oList.dropCollection() 52 | 53 | 54 | def countBlacklist(): 55 | oList = CPEList(collection, args) 56 | return oList.countItems() 57 | 58 | 59 | def checkBlacklist(cpe): 60 | oList = CPEList(collection, args) 61 | amount = oList.check(cpe) 62 | return amount 63 | 64 | 65 | def insertBlacklist(cpe, cpeType): 66 | oList = CPEList(collection, args) 67 | return oList.insert(cpe,cpeType) 68 | 69 | 70 | def removeBlacklist(cpe): 71 | oList = CPEList(collection, args) 72 | return oList.remove(cpe) 73 | 74 | 75 | def updateBlacklist(cpeOld, cpeNew, cpeType): 76 | oList = CPEList(collection, args) 77 | return oList.update(cpeOld, cpeNew, cpeType) 78 | 79 | if __name__ == '__main__': 80 | oList = CPEList(collection, args) 81 | oList.process() 82 | -------------------------------------------------------------------------------- /sbin/db_cpe_browser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Importing CPE entries in a Redis database to improve lookup 5 | # 6 | # Until now, this part is only used by the web interface to improve response time 7 | # 8 | # Software is free software released under the "Modified BSD license" 9 | # 10 | # Copyright (c) 2014-2015 Alexandre Dulaunoy - a@foo.be 11 | # Copyright (c) 2014-2015 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 12 | 13 | # Imports 14 | import os 15 | import sys 16 | import argparse 17 | runPath = os.path.dirname(os.path.realpath(__file__)) 18 | sys.path.append(os.path.join(runPath, "..")) 19 | 20 | from redis import exceptions as redisExceptions 21 | 22 | from lib.Config import Configuration 23 | from lib.Toolkit import pad 24 | import lib.DatabaseLayer as db 25 | 26 | argParser = argparse.ArgumentParser(description='CPE entries importer in Redis cache') 27 | argParser.add_argument('-v', action='store_true', default=False, help='Verbose logging') 28 | argParser.add_argument('-o', action='store_true', default=False, help='Import cpeother database in Redis cache') 29 | args = argParser.parse_args() 30 | 31 | if args.o: 32 | cpe = db.getAlternativeCPEs() 33 | else: 34 | cpe = db.getCPEs() 35 | 36 | try: 37 | r = Configuration.getRedisVendorConnection() 38 | except: 39 | sys.exit(1) 40 | 41 | for e in cpe: 42 | try: 43 | if args.o is not True: 44 | prefix = 'cpe_2_2' 45 | value = e[prefix] 46 | else: 47 | value = e['id'] 48 | if args.o is not True: 49 | if e[prefix].count(':') > 4: 50 | value = ":".join(value.split(':')[:5]) 51 | (prefix, cpetype, vendor, product, version) = pad(value.split(':'),5) 52 | else: 53 | (prefix, cpeversion, cpetype, vendor, product, version, *remaining) = pad(value.split(':'),6) 54 | except Exception as ex: 55 | print(ex) 56 | pass 57 | try: 58 | if args.v: 59 | print(value + " added") 60 | r.sadd("prefix:" + prefix, cpetype) 61 | r.sadd("t:" + cpetype, vendor) 62 | r.sadd("v:" + vendor, product) 63 | if version: 64 | r.sadd("p:" + product, version) 65 | except redisExceptions.ConnectionError: 66 | sys.exit("Redis server not running on %s:%s"%(Configuration.getRedisHost(),Configuration.getRedisPort())) 67 | -------------------------------------------------------------------------------- /sbin/db_fulltext.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Fulltext indexer for the MongoDB CVE collection. 5 | # 6 | # The fulltext indexer is relying on Whoosh. 7 | # 8 | # The indexing is done by enumerating all items from 9 | # the MongoDB CVE collection and indexing the summary text of each 10 | # CVE. The Path of each document is the CVE-ID. 11 | # 12 | # Software is free software released under the "Modified BSD license" 13 | # 14 | # Copyright (c) 2012-2015 Alexandre Dulaunoy - a@foo.be 15 | # Copyright (c) 2015 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 16 | 17 | # Imports 18 | import os 19 | import sys 20 | runPath = os.path.dirname(os.path.realpath(__file__)) 21 | sys.path.append(os.path.join(runPath, "..")) 22 | 23 | import argparse 24 | 25 | from lib.Config import Configuration 26 | from lib.ProgressBar import progressbar 27 | import lib.CVEs as cves 28 | import lib.DatabaseLayer as db 29 | 30 | argParser = argparse.ArgumentParser(description='Fulltext indexer for the MongoDB CVE collection') 31 | argParser.add_argument('-v', action='store_true', default=False, help='Verbose logging') 32 | argParser.add_argument('-l', default=5, help='Number of last entries to index (Default: 5) - 0 to index all documents') 33 | argParser.add_argument('-n', action='store_true', default=False, help='lookup complete cpe (Common Platform Enumeration) name for vulnerable configuration to add in the index') 34 | args = argParser.parse_args() 35 | 36 | c = cves.last(namelookup=args.n) 37 | 38 | indexpath = Configuration.getIndexdir() 39 | 40 | from whoosh.index import create_in, exists_in, open_dir 41 | from whoosh.fields import Schema, TEXT, ID 42 | 43 | schema = Schema(title=TEXT(stored=True), path=ID(stored=True, unique=True), content=TEXT) 44 | 45 | if not os.path.exists(indexpath): 46 | os.mkdir(indexpath) 47 | 48 | if not exists_in(indexpath): 49 | ix = create_in(indexpath, schema) 50 | else: 51 | ix = open_dir(indexpath) 52 | def dumpallcveid(entry=None): 53 | return db.getCVEID if not entry else db.getCVEIDs(int(entry)) 54 | 55 | 56 | def getcve(cveid=None): 57 | if cveid is None: 58 | return False 59 | return db.getCVE(cveid) 60 | 61 | for cveid in progressbar(dumpallcveid(entry=args.l),prefix="Processing"): 62 | try: 63 | writer = ix.writer() 64 | except: 65 | print ("Index is locked. Another db_fulltext process running?") 66 | sys.exit(1) 67 | item = getcve(cveid=cveid) 68 | title = item['summary'][0:70] 69 | if args.n: 70 | for v in item['vulnerable_configuration']: 71 | cpe = c.getcpe(cpeid=v).strip('\n') 72 | item['summary'] += " " + cpe 73 | if args.v: 74 | print ('Indexing CVE-ID ' + str(cveid) + ' ' + title) 75 | writer.update_document(title=title, path=cveid, content=item['summary']) 76 | writer.commit() 77 | -------------------------------------------------------------------------------- /sbin/db_mgmt_admin.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Admin creator script 5 | # 6 | # Creates an admin account in the database 7 | # Only master accounts are allowed to add and remove users 8 | # First account registered is the master account 9 | # 10 | # Software is free software released under the "Modified BSD license" 11 | # 12 | # Copyright (c) 2015 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 13 | 14 | # Imports 15 | import os 16 | import sys 17 | runPath = os.path.dirname(os.path.realpath(__file__)) 18 | sys.path.append(os.path.join(runPath, "..")) 19 | 20 | import pymongo 21 | 22 | import argparse 23 | import getpass 24 | 25 | import lib.DatabaseLayer as dbLayer 26 | 27 | # args 28 | argParser = argparse.ArgumentParser(description='Admin account creator for the mongo database') 29 | argParser.add_argument('-a', help=' Add an account', default=False) 30 | argParser.add_argument('-c', help='Change the password of an account', default=None) 31 | argParser.add_argument('-r', help='Remove account', default=False) 32 | argParser.add_argument('-p', help='Promote account to master', default=False) 33 | argParser.add_argument('-d', help='Demote account to normal user', default=False) 34 | argParser.add_argument('-l', help='Make the user local-only', action='store_true') 35 | args = argParser.parse_args() 36 | 37 | # vars 38 | col = "mgmt_users" 39 | rounds = 8000 40 | saltLength = 10 41 | exits = {'userInDb': 'User already exists in database', 42 | 'userNotInDb': 'User does not exist in database', 43 | 'userpasscombo': 'Master user/password combination does not exist', 44 | 'passwordMatch': "The passwords don't match!", 45 | 'noMaster': 'Not a master account!', 46 | 'lastMaster': 'This user is the last admin in the database and thus can not be removed', 47 | 'dummy': '_dummy_ is a placeholder, and thus cannot be used'} 48 | 49 | # functions 50 | 51 | 52 | def verifyPass(password, user): 53 | if not dbLayer.userExists(user): 54 | sys.exit(exits['userNotInDb']) 55 | if not dbLayer.verifyUser(user, password): 56 | sys.exit(exits['userpasscombo']) 57 | return True 58 | 59 | 60 | def promptNewPass(): 61 | password = getpass.getpass("New password:") 62 | verify = getpass.getpass("Verify password:") 63 | if (password != verify): 64 | sys.exit(exits['passwordMatch']) 65 | return password 66 | 67 | 68 | def masterLogin(): 69 | master = input("Master account username: ") 70 | if verifyPass(getpass.getpass("Master password:"), master): 71 | if not dbLayer.isMasterAccount(master): 72 | sys.exit(exits['noMaster']) 73 | else: 74 | sys.exit('Master user/password combination does not exist') 75 | return True 76 | 77 | 78 | def isLastAdmin(user): 79 | if dbLayer.isSingleMaster(user): 80 | sys.exit(exits['lastMaster']) 81 | 82 | # script run 83 | try: 84 | if args.a: 85 | username = args.a 86 | if username.strip() == "_dummy_": 87 | sys.exit(exits['dummy']) 88 | if dbLayer.userExists(username): 89 | sys.exit(exits['userInDb']) 90 | # set master if db is empty 91 | if dbLayer.getSize(col) > 0: 92 | masterLogin() 93 | password = promptNewPass() 94 | dbLayer.addUser(username, password, localOnly=args.l) 95 | else: 96 | password = promptNewPass() 97 | dbLayer.addUser(username, password, admin=True, localOnly=args.l) 98 | sys.exit("User added") 99 | elif args.c: 100 | username = args.c 101 | verifyPass(getpass.getpass("Old password:"), username) 102 | password = promptNewPass() 103 | dbLayer.changePassword(username, password) 104 | sys.exit("Password updated") 105 | elif args.r: 106 | username = args.r 107 | if not dbLayer.userExists(username): 108 | sys.exit(exits['userNotInDb']) 109 | masterLogin() 110 | isLastAdmin(username) 111 | dbLayer.deleteUser(username) 112 | sys.exit('User removed from database') 113 | elif args.p: 114 | username = args.p 115 | if not dbLayer.userExists(username): 116 | sys.exit(exits['userNotInDb']) 117 | masterLogin() 118 | # promote 119 | dbLayer.setAdmin(username, True) 120 | sys.exit('User promoted') 121 | elif args.d: 122 | username = args.d 123 | if not dbLayer.userExists(username): 124 | sys.exit(exits['userNotInDb']) 125 | masterLogin() 126 | isLastAdmin(username) 127 | # demote 128 | dbLayer.setAdmin(username, False) 129 | sys.exit('User demoted') 130 | 131 | except pymongo.errors.ConnectionFailure: 132 | print("Can't connect to the mongo database") 133 | except Exception as e: 134 | print(e) 135 | print("Outdated database. Please drop and re-fill your database") 136 | -------------------------------------------------------------------------------- /sbin/db_mgmt_cpe_dictionary.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Import script of nvd cpe (Common Platform Enumeration) definition 4 | # into a collection used for human readable lookup of product name. 5 | # 6 | # Imported in cvedb in the collection named cpe. 7 | # 8 | # The format of the collection is the following 9 | # 10 | # { "_id" : ObjectId("50a2739eae24ac2274eae7c0"), "id" : 11 | # "cpe:/a:1024cms:1024_cms:0.7", "title" : "1024cms.org 1024 CMS 0.7" } 12 | # 13 | # Software is free software released under the "Modified BSD license" 14 | # 15 | # Copyright (c) 2012 Wim Remes 16 | # Copyright (c) 2012-2014 Alexandre Dulaunoy - a@foo.be 17 | # Copyright (c) 2014-2016 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 18 | 19 | # Imports 20 | import os 21 | import sys 22 | runPath = os.path.dirname(os.path.realpath(__file__)) 23 | sys.path.append(os.path.join(runPath, "..")) 24 | 25 | from xml.sax import make_parser 26 | from xml.sax.handler import ContentHandler 27 | 28 | from dateutil.parser import parse as parse_datetime 29 | 30 | from lib.ProgressBar import progressbar 31 | from lib.Toolkit import toStringFormattedCPE 32 | from lib.Config import Configuration 33 | import lib.DatabaseLayer as db 34 | 35 | class CPEHandler(ContentHandler): 36 | def __init__(self): 37 | self.cpe = [] 38 | self.titletag = False 39 | self.referencestag = False 40 | self.referencetag = False 41 | 42 | def startElement(self, name, attrs): 43 | if name == 'cpe-item': 44 | self.name = "" 45 | self.title = "" 46 | self.referencetitle = "" 47 | self.name = attrs.get('name') 48 | self.cpe.append({'name': attrs.get('name'), 'title': [], 'references': []}) 49 | elif name == 'title': 50 | if attrs.get('xml:lang') == 'en-US': 51 | self.titletag = True 52 | elif name == 'references': 53 | self.referencestag = True 54 | elif name == 'reference': 55 | self.referencetag = True 56 | self.href = attrs.get('href') 57 | self.cpe[-1]['references'].append(self.href) 58 | 59 | def characters(self, ch): 60 | if self.titletag: 61 | self.title += ch 62 | 63 | def endElement(self, name): 64 | if name == 'title': 65 | self.titletag = False 66 | self.cpe[-1]['title'].append(self.title.rstrip()) 67 | elif name == 'references': 68 | self.referencestag = False 69 | elif name == 'reference': 70 | self.referencetag = False 71 | self.href = None 72 | 73 | # make parser 74 | parser = make_parser() 75 | ch = CPEHandler() 76 | parser.setContentHandler(ch) 77 | # check modification date 78 | try: 79 | (f, r) = Configuration.getFeedData('cpe') 80 | except: 81 | sys.exit("Cannot open url %s. Bad URL or not connected to the internet?"%(Configuration.getFeedURL("cpe"))) 82 | i = db.getLastModified('cpe') 83 | last_modified = parse_datetime(r.headers['last-modified'], ignoretz=True) 84 | if i is not None: 85 | if last_modified == i: 86 | print("Not modified") 87 | sys.exit(0) 88 | # parse xml and store in database 89 | parser.parse(f) 90 | cpeList=[] 91 | for x in progressbar(ch.cpe): 92 | x['id']= toStringFormattedCPE(x['name']) 93 | x['title']=x['title'][0] 94 | x['cpe_2_2'] = x.pop('name') 95 | if not x['references']: x.pop('references') 96 | cpeList.append(x) 97 | db.bulkUpdate("cpe", cpeList) 98 | 99 | #update database info after successful program-run 100 | db.setColUpdate('cpe', last_modified) 101 | -------------------------------------------------------------------------------- /sbin/db_mgmt_cpe_other_dictionary.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Import script of cpe (Common Platform Enumeration) definition 5 | # into a collection used for human readable lookup of product name. 6 | # This is locating the cpe used inside the cve, but only the cpe 7 | # not present inside the cpe official dictionary. 8 | # 9 | # Exemple: 10 | # CVE-2014-5446 -> cpe:/a:zohocorp:manageengine_netflow_analyzer:.* 11 | # but 'cpe:/a:zohocorp:manageengine_netflow_analyzer' is not in the 12 | # cpe official dictionary. 13 | # 14 | # Imported in cvedb in the collection named cpeother. 15 | # 16 | # The format of the collection is the following 17 | # 18 | # { "_id" : ObjectId("50a2739eae24ac2274eae7c0"), 19 | # "id" : "cpe:/a:zohocorp:manageengine_netflow_analyzer:10.2", 20 | # "title" : "cpe:/a:zohocorp:manageengine_netflow_analyzer:10.2" 21 | # } 22 | # 23 | # Software is free software released under the "Modified BSD license" 24 | # 25 | # Copyright (c) 2014 psychedelys 26 | # Copyright (c) 2014-2015 PidgeyL 27 | 28 | # Imports 29 | import os 30 | import sys 31 | runPath = os.path.dirname(os.path.realpath(__file__)) 32 | sys.path.append(os.path.join(runPath, "..")) 33 | 34 | import urllib 35 | 36 | from lib.ProgressBar import progressbar 37 | import lib.DatabaseLayer as db 38 | 39 | # get dates 40 | icve = db.getLastModified('cve') 41 | icpeo = db.getLastModified('cpeother') 42 | 43 | # check modification date 44 | date = False 45 | if icve is not None and icpeo is not None: 46 | # Go check date 47 | if icve >= icpeo: 48 | print("Not modified") 49 | sys.exit(0) 50 | else: 51 | date = True 52 | 53 | # only get collection of new CVE's 54 | collections = [] 55 | if date: 56 | collections = db.getCVEsNewerThan(icve) 57 | else: 58 | collections = db.getCVEs() 59 | # check cpes for cves and parse and store missing cpes in cpeother 60 | batch = [] 61 | 62 | # skip on empty collections 63 | col=list(collections) 64 | if not col: 65 | print ("Empty collections, import skipped") 66 | sys.exit(2) 67 | 68 | for item in progressbar(col): 69 | for cpeentry in item['vulnerable_configuration']: 70 | checkdup = db.getAlternativeCPE(cpeentry) 71 | if checkdup and len(checkdup) <= 0: 72 | entry = db.getCPE(cpeentry) 73 | if entry and len(entry.count) <= 0: 74 | title = cpeentry 75 | title = title[10:] 76 | title = title.replace(':-:', ' ',10) 77 | title = title.replace(':', ' ',10) 78 | title = title.replace('_', ' ',10) 79 | title = urllib.parse.unquote_plus(title) 80 | 81 | title = title.title() 82 | batch.append({'id': cpeentry, 'title': title}) 83 | if len(batch) != 0: 84 | db.cpeotherBulkInsert(batch) 85 | 86 | #update database info after successful program-run 87 | db.setColUpdate('cpeother', icve) 88 | -------------------------------------------------------------------------------- /sbin/db_mgmt_create_index.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Script to check and ensure that the recommended index are created as recommended. 5 | # 6 | # Software is free software released under the "Modified BSD license" 7 | # 8 | # Copyright (c) 2014 psychedelys 9 | # Copyright (c) 2015-2106 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 10 | 11 | # Imports 12 | import os 13 | import sys 14 | runPath = os.path.dirname(os.path.realpath(__file__)) 15 | sys.path.append(os.path.join(runPath, "..")) 16 | 17 | from pymongo import TEXT 18 | 19 | import lib.DatabaseLayer as dbLayer 20 | 21 | def setIndex(col, field, printSuccess = True): 22 | try: 23 | dbLayer.ensureIndex(col, field) 24 | if printSuccess: 25 | print('[+]Success to create index %s on %s' % (field, col)) 26 | except Exception as e: 27 | print('[-]Failed to create index %s on %s: %s' % (col, field, e)) 28 | 29 | setIndex('cpe', 'id') 30 | setIndex('cpeother', 'id') 31 | setIndex('cves', 'id') 32 | setIndex('cves', 'vulnerable_configuration') 33 | setIndex('cves', 'Modified') 34 | setIndex('cves', [("summary",TEXT)]) 35 | setIndex('vendor', 'id') 36 | setIndex('via4', 'id') 37 | setIndex('mgmt_whitelist', 'id') 38 | setIndex('mgmt_blacklist', 'id') 39 | setIndex('capec', 'related_weakness') 40 | 41 | via4 = dbLayer.getInfo('via4') 42 | if via4: 43 | for index in via4.get('searchables', []): 44 | setIndex('via4', index, False) 45 | -------------------------------------------------------------------------------- /sbin/db_mgmt_cwe.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Import script of NIST CWE Common Weakness Enumeration. 4 | # 5 | # Until now, the import is only import Weakness description. 6 | # 7 | # The format is the following: 8 | # 9 | # { "_id" : ObjectId("52b70521b261026f36818515"), "weaknessabs" : "Variant", 10 | # "name" : "ASP.NET Misconfiguration: Missing Custom Error Page", 11 | # "description_summary" : "An ASP .NET application must enable custom error 12 | # pages in order to prevent attackers from mining information from the 13 | # framework's built-in responses.An ASP .NET application must enable custom 14 | # error pages in order to prevent attackers from mining information from the 15 | # framework's built-in responses.", "status" : "Draft", "id" : "12" } 16 | # 17 | # Software is free software released under the "Modified BSD license" 18 | # 19 | # Copyright (c) 2013-2014 Alexandre Dulaunoy - a@foo.be 20 | # Copyright (c) 2015-2016 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 21 | 22 | # Imports 23 | import os 24 | import sys 25 | runPath = os.path.dirname(os.path.realpath(__file__)) 26 | sys.path.append(os.path.join(runPath, "..")) 27 | 28 | from dateutil.parser import parse as parse_datetime 29 | 30 | from xml.sax import make_parser 31 | from xml.sax.handler import ContentHandler 32 | import argparse 33 | import zipfile 34 | import tempfile 35 | 36 | from lib.ProgressBar import progressbar 37 | from lib.Config import Configuration 38 | import lib.DatabaseLayer as db 39 | 40 | argparser = argparse.ArgumentParser(description='populate/update NIST CWE Common Weakness Enumeration database') 41 | argparser.add_argument('-v', action='store_true', help='verbose output') 42 | args = argparser.parse_args() 43 | 44 | class CWEHandler(ContentHandler): 45 | def __init__(self): 46 | self.cwe = [] 47 | self.description_summary_tag = False 48 | self.weakness_tag = False 49 | 50 | def startElement(self, name, attrs): 51 | if name == 'Weakness': 52 | self.weakness_tag = True 53 | self.statement = "" 54 | self.weaknessabs = attrs.get('Weakness_Abstraction') 55 | self.name = attrs.get('Name') 56 | self.idname = attrs.get('ID') 57 | self.status = attrs.get('Status') 58 | self.cwe.append({'name': self.name, 'id': self.idname, 'status': self.status, 'weaknessabs': self.weaknessabs}) 59 | elif name == 'Description_Summary' and self.weakness_tag: 60 | self.description_summary_tag = True 61 | self.description_summary = "" 62 | 63 | def characters(self, ch): 64 | if self.description_summary_tag: 65 | self.description_summary += ch.replace(" ", "") 66 | 67 | def endElement(self, name): 68 | if name == 'Description_Summary' and self.weakness_tag: 69 | self.description_summary_tag = False 70 | self.description_summary = self.description_summary + self.description_summary 71 | self.cwe[-1]['description_summary'] = self.description_summary.replace("\n", "") 72 | elif name == 'Weakness': 73 | self.weakness_tag = False 74 | 75 | # make parser 76 | parser = make_parser() 77 | ch = CWEHandler() 78 | parser.setContentHandler(ch) 79 | # check modification date 80 | try: 81 | (f, r) = Configuration.getFeedData('cwe') 82 | except Exception as e: 83 | print(e) 84 | sys.exit("Cannot open url %s. Bad URL or not connected to the internet?"%(Configuration.getFeedURL("cwe"))) 85 | lastmodified = parse_datetime(r.headers['last-modified'], ignoretz=True) 86 | i = db.getLastModified('cwe') 87 | if i is not None: 88 | if lastmodified == i: 89 | print("Not modified") 90 | sys.exit(0) 91 | 92 | 93 | # parse xml and store in database 94 | parser.parse(f) 95 | cweList=[] 96 | for cwe in progressbar(ch.cwe): 97 | cwe['description_summary']=cwe['description_summary'].replace("\t\t\t\t\t", " ") 98 | if args.v: 99 | print (cwe) 100 | cweList.append(cwe) 101 | db.bulkUpdate('cwe', cweList) 102 | 103 | #update database info after successful program-run 104 | db.setColUpdate('cwe', lastmodified) 105 | -------------------------------------------------------------------------------- /sbin/db_mgmt_ref.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Import of the VIA4 dataset (vFeed replacement) 5 | # 6 | # Software is free software released under the "Modified BSD license" 7 | # 8 | # Copyright (c) 2015 Alexandre Dulaunoy - a@foo.be 9 | # Copyright (c) 2016 Pieter-Jan Moreels 10 | # Imports 11 | import json 12 | import os 13 | import sys 14 | 15 | runPath = os.path.dirname(os.path.realpath(__file__)) 16 | sys.path.append(os.path.join(runPath, "..")) 17 | 18 | from dateutil.parser import parse as parse_datetime 19 | 20 | from lib.Config import Configuration 21 | import lib.DatabaseLayer as db 22 | 23 | # To Do: Implement REDIS 24 | 25 | try: 26 | redis = Configuration.getRedisRefConnection() 27 | try: 28 | redis.info() 29 | except: 30 | sys.exit("Redis server not running on %s:%s"%(Configuration.getRedisHost(),Configuration.getRedisPort())) 31 | except Exception as e: 32 | print(e) 33 | sys.exit(1) 34 | 35 | try: 36 | (f, r) = Configuration.getFeedData('via4') 37 | except: 38 | sys.exit("Cannot open url %s. Bad URL or not connected to the internet?"%(Configuration.getFeedURL("via4"))) 39 | 40 | # check modification date 41 | lastmodified = parse_datetime(r.headers['last-modified'], ignoretz=True) 42 | i=db.getLastModified("via4") 43 | if i is not None: 44 | if lastmodified == i: 45 | print("Not modified") 46 | sys.exit(0) 47 | 48 | data = json.loads(f.read().decode('utf-8')) 49 | cves = data['cves'] 50 | bulk = [dict(val, id=key) for key, val in cves.items() if key] 51 | db.bulkUpdate('via4', bulk) 52 | db.setColInfo('via4', 'sources', data['metadata']['sources']) 53 | db.setColInfo('via4', 'searchables', data['metadata']['searchables']) 54 | 55 | #update database info after successful program-run 56 | db.setColUpdate('via4', lastmodified) 57 | -------------------------------------------------------------------------------- /sbin/db_mgmt_vendorstatements.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Import script of NIST nvd vendor statement. 4 | # 5 | # Imported in cvedb in the collection named vendor. 6 | # 7 | # The format of the collection is the following: 8 | # { "_id" : ObjectId("52b5b33ab261021ad289f3ee"), "lastmodified" : "2006-09-27T00:00:00.000-04:00", "statement" : "CVE-2001-0935 refers to vulnerabilities found when SUSE did a code audit of the wu-ftpd glob.c file in wu-ftpd 2.6.0. They shared these details with the wu-ftpd upstream authors who clarified that some of the issues did not apply, and all were addressed by the version of glob.c in upstream wu-ftpd 2.6.1. Therefore we believe that the issues labelled as CVE-2001-0935 do not affect wu-ftpd 2.6.1 or later versions and therefore do not affect Red Hat Enterprise Linux 2.1.CVE-2001-0935 refers to vulnerabilities found when SUSE did a code audit of the wu-ftpd glob.c file in wu-ftpd 2.6.0. They shared these details with the wu-ftpd upstream authors who clarified that some of the issues did not apply, and all were addressed by the version of glob.c in upstream wu-ftpd 2.6.1. Therefore we believe that the issues labelled as CVE-2001-0935 do not affect wu-ftpd 2.6.1 or later versions and therefore do not affect Red Hat Enterprise Linux 2.1.", "contributor" : "Joshua Bressers", "organization" : "Red Hat", "id" : "CVE-2001-0935" } 9 | # 10 | # Software is free software released under the "Modified BSD license" 11 | # 12 | # Copyright (c) 2013 Alexandre Dulaunoy - a@foo.be 13 | # Copyright (c) 2015-2016 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 14 | 15 | # Imports 16 | import os 17 | import sys 18 | runPath = os.path.dirname(os.path.realpath(__file__)) 19 | sys.path.append(os.path.join(runPath, "..")) 20 | 21 | from dateutil.parser import parse as parse_datetime 22 | 23 | from xml.sax import make_parser 24 | from xml.sax.handler import ContentHandler 25 | import argparse 26 | 27 | from lib.ProgressBar import progressbar 28 | from lib.Config import Configuration 29 | 30 | import lib.DatabaseLayer as db 31 | 32 | argparser = argparse.ArgumentParser(description='populate/update vendor statement database') 33 | argparser.add_argument('-v', action='store_true', help='verbose output') 34 | args = argparser.parse_args() 35 | 36 | 37 | class VendorHandler(ContentHandler): 38 | def __init__(self): 39 | self.vendor = [] 40 | self.statementtag = False 41 | 42 | def startElement(self, name, attrs): 43 | if name == 'statement': 44 | self.statement = "" 45 | self.organization = attrs.get('organization') 46 | self.lastmodified = attrs.get('lastmodified') 47 | self.cvename = attrs.get('cvename') 48 | self.contributor = attrs.get('contributor') 49 | self.vendor.append({'organization': self.organization, 'lastmodified': self.lastmodified, 'id': self.cvename, 'contributor': self.contributor, 'statement': self.statement}) 50 | self.statementtag = True 51 | 52 | def characters(self, ch): 53 | if self.statementtag: 54 | self.statement += ch 55 | 56 | def endElement(self, name): 57 | if name == 'statement': 58 | self.statementtag = False 59 | self.statement = self.statement + self.statement.rstrip() 60 | self.vendor[-1]['statement'] = self.statement 61 | 62 | # make parser 63 | parser = make_parser() 64 | ch = VendorHandler() 65 | parser.setContentHandler(ch) 66 | # check modification date 67 | try: 68 | (f, r) = Configuration.getFeedData('vendor') 69 | except: 70 | sys.exit("Cannot open url %s. Bad URL or not connected to the internet?"%(Configuration.getFeedURL('vendor'))) 71 | last_modified = parse_datetime(r.headers['last-modified'], ignoretz=True) 72 | i = db.getLastModified('vendor') 73 | if i is not None: 74 | if last_modified == i: 75 | print("Not modified") 76 | sys.exit(0) 77 | # parse xml and store in database 78 | parser.parse(f) 79 | statements=[] 80 | for statement in progressbar(ch.vendor): 81 | if args.v: 82 | print (statement) 83 | statements.append(statement) 84 | db.bulkUpdate('vendor', statements) 85 | 86 | #update database info after successful program-run 87 | db.setColUpdate('vendor', last_modified) 88 | -------------------------------------------------------------------------------- /sbin/db_notification.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Notification database 5 | # includes the user who will receive a notification 6 | # when a new CVE is published and matching their monitored CPE 7 | # 8 | # Software is free software released under the "Modified BSD license" 9 | # 10 | # Copyright (c) 2014 Alexandre Dulaunoy - a@foo.be 11 | # Copyright (c) 2015 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 12 | 13 | # Imports 14 | import os 15 | import sys 16 | runPath = os.path.dirname(os.path.realpath(__file__)) 17 | sys.path.append(os.path.join(runPath, "..")) 18 | 19 | import argparse 20 | import lib.DatabaseLayer as dbLayer 21 | from lib.Config import Configuration 22 | 23 | argParser = argparse.ArgumentParser(description='Notification database management for cve-search', epilog='') 24 | argParser.add_argument('-c', action='append', help='CPE name(s) to add (e.g. google:chrome)') 25 | argParser.add_argument('-g', type=str, help='Name of the organization (e.g. mycompany)') 26 | argParser.add_argument('-d', action='append', help='Destination(s) of matching CPE (mailto:foo@bar.com)') 27 | argParser.add_argument('-a', action='store_true', default=False, help='Add a notification entry') 28 | argParser.add_argument('-r', action='store_true', default=False, help='Remove a notification entry') 29 | argParser.add_argument('-v', action='store_true', default=False, help='Verbose logging') 30 | argParser.add_argument('-n', action='store_true', default=False, help='Run notification') 31 | argParser.add_argument('-f', action='store_true', default=False, help='Flush state') 32 | argParser.add_argument('-l', action='store_true', default=False, help='List notification entries') 33 | args = argParser.parse_args() 34 | 35 | 36 | def checkreq(): 37 | 38 | if args.c is None: 39 | print ("You need at least one cpe or partial cpe entry (-c) \n") 40 | argParser.print_help() 41 | exit(1) 42 | if args.g is None: 43 | print ("Organization is missing (-g) \n") 44 | argParser.print_help() 45 | exit(1) 46 | 47 | def searchcve(cpe=None): 48 | if cpe is None: 49 | return False 50 | cve = dbLayer.cvesForCPE(cpe) 51 | return cve 52 | 53 | 54 | def updatestate(org=None, cve=None): 55 | if cve is None or org is None: 56 | return False 57 | for c in cve: 58 | r.sadd("s:" + org, c) 59 | 60 | 61 | def sendnotification(org=None, cve=None): 62 | if org is None or cve is None: 63 | return False 64 | for destination in r.smembers("d:" + org): 65 | for c in cve: 66 | print ("notification of " + c + " to " + destination) 67 | 68 | # Redis db 10 (cpe) 69 | # Redis db 11 (notification) 70 | 71 | # Set of notification for an organization set(d:orgname) -> notification destination 72 | # Set of cpe value for an organization set(c:orgname) -> cpe values 73 | # Set of organizations set(orgs) -> organisations 74 | 75 | # Set of state notification set(s:orgs) -> CVEs 76 | r = Configuration.getRedisNotificationsConnection() 77 | 78 | if args.a and args.r and args.n and args.f and args.l: 79 | argParser.print_help() 80 | exit(1) 81 | 82 | if args.a: 83 | checkreq() 84 | if not r.sismember("orgs", args.g): 85 | if args.v: 86 | print ("Organization " + args.g + " added.") 87 | r.sadd("orgs", args.g) 88 | 89 | for cpe in args.c: 90 | r.sadd("c:" + args.g, cpe) 91 | if args.v: 92 | print (cpe + " added") 93 | 94 | if not r.scard("d:" + args.g): 95 | if args.g: 96 | for destination in args.d: 97 | r.sadd("d:" + args.g, destination) 98 | else: 99 | print ("destination missing for " + args.g + " you need at least one destination -d") 100 | exit(1) 101 | 102 | elif args.r: 103 | checkreq() 104 | for cpe in args.c: 105 | r.srem("c:" + args.g, cpe) 106 | if args.v: 107 | print (cpe + " removed") 108 | 109 | if r.scard("c:" + args.g) < 1: 110 | r.srem("orgs", args.g) 111 | if args.v: 112 | print ("org " + args.g + " removed") 113 | 114 | elif args.n: 115 | for org in r.smembers("orgs"): 116 | if args.v: 117 | print("Notification for " + org) 118 | knowncve = set() 119 | for cpe in r.smembers("c:" + org): 120 | if args.v: 121 | print("CPE " + cpe) 122 | for cve in searchcve(cpe=cpe): 123 | knowncve.add(cve['id']) 124 | if r.exists("s:" + org): 125 | x = r.smembers("s:" + org) 126 | diff = knowncve.difference(x) 127 | if diff: 128 | sendnotification(org=org, cve=diff) 129 | 130 | updatestate(org=org, cve=knowncve) 131 | 132 | elif args.f: 133 | for org in r.smembers("orgs"): 134 | r.delete('s:' + org) 135 | if args.v: 136 | print ("State for " + org + " deleted") 137 | 138 | elif args.l: 139 | for org in r.smembers("orgs"): 140 | print (org) 141 | for cpe in r.smembers("c:" + org): 142 | print (" " + cpe) 143 | for destination in r.smembers("d:" + org): 144 | print ("->" + destination) 145 | 146 | else: 147 | argParser.print_help() 148 | -------------------------------------------------------------------------------- /sbin/db_ranking.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Import ranking values into the ranking collection. 5 | # 6 | # A cpe regex is use to match vulnerable configuration 7 | # and a ranking value is assigned per a group name. 8 | # 9 | # The idea is to set a specific weight for a vulnerability 10 | # when it's of a specific interest of a group/dept/organization 11 | # within your infrastructure. This can be also used to send 12 | # notification when you have an urgent vulnerability that need 13 | # to be worked on. 14 | # 15 | # The format of the collection is the following 16 | # 17 | # { "_id" : ObjectId("50b1f33e597549f61b2a259b"), "cpe" : "google:chrome", "rank" : [ { "circl" : 3, "other" : 3 } ] } 18 | # { "_id" : ObjectId("50b1fd79597549f61b2a259f"), "cpe" : "cisco", "rank" : [ { "circl" : 2 } ] } 19 | # 20 | # Software is free software released under the "Modified BSD license" 21 | # 22 | # Copyright (c) 2012-2015 Alexandre Dulaunoy - a@foo.be 23 | # Copyright (c) 2015 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 24 | 25 | # Imports 26 | import os 27 | import sys 28 | runPath = os.path.dirname(os.path.realpath(__file__)) 29 | sys.path.append(os.path.join(runPath, "..")) 30 | 31 | import argparse 32 | 33 | import lib.DatabaseLayer as db 34 | 35 | 36 | def add(cpe=None, key=None, rank=1): 37 | if cpe is None or key is None: 38 | return False 39 | return db.addRanking(cpe, key, rank) 40 | 41 | def findranking(cpe=None, loosy=True): 42 | if cpe is None: 43 | return False 44 | 45 | result = False 46 | if loosy: 47 | for x in cpe.split(':'): 48 | if x is not '': 49 | i = db.findRanking(x, regex=True) 50 | if i is None: 51 | continue 52 | if 'rank' in i: 53 | result = i['rank'] 54 | else: 55 | i = db.findRanking(cpe, regex=True) 56 | print (cpe) 57 | if i is None: 58 | return result 59 | if 'rank' in i: 60 | result = i['rank'] 61 | 62 | return result 63 | 64 | 65 | def removeranking(cpe=None): 66 | 67 | if cpe is None or cpe is '': 68 | return False 69 | 70 | return db.removeRanking(cpe) 71 | 72 | 73 | def listranking(format='json'): 74 | ranks = [] 75 | for x in db.findRanking(): 76 | if format == "json": 77 | ranks.append(x) 78 | else: 79 | ranks.append(x['cpe'] + " " + str(x['rank'])) 80 | return ranks 81 | 82 | argParser = argparse.ArgumentParser(description='Ranking database management for cve-search', epilog='You can add a specific cpe to rank: \'db_ranking.py -c oracle:java -g mycompany -r 4\'\n and then lookup for \'db_ranking.py -f java\'\n Rankings encoded are used to enhance the output of the other cve-search query tools.\n') 83 | argParser.add_argument('-c', type=str, help='CPE name to add (e.g. google:chrome)') 84 | argParser.add_argument('-g', type=str, help='Name of the organization (e.g. mycompany)') 85 | argParser.add_argument('-r', type=int, default=1, help='Ranking value (integer) default value is 1') 86 | argParser.add_argument('-f', type=str, help='Find ranking based on a CPE name regexp') 87 | argParser.add_argument('-l', action='store_true', help='List all ranking') 88 | argParser.add_argument('-d', type=str, default=None, help='Remove ranking based on a CPE name regexp') 89 | args = argParser.parse_args() 90 | 91 | if args.c is not None and args.g is not None: 92 | add(cpe=args.c, key=args.g, rank=args.r) 93 | elif args.f is not None: 94 | print (findranking(cpe=args.f)) 95 | elif args.l: 96 | print (listranking()) 97 | elif args.d: 98 | print (removeranking(cpe=args.d)) 99 | else: 100 | argParser.print_help() 101 | -------------------------------------------------------------------------------- /sbin/db_whitelist.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Whitelist feature to mark CVE's for CPE's of personal interest 5 | # 6 | # Software is free software released under the "Modified BSD license" 7 | # 8 | # Copyright (c) 2014-2016 Pieter-Jan Moreels - pieterjan.moreels@gmail.com 9 | 10 | # Imports 11 | # make sure these modules are available on your system 12 | import os 13 | import sys 14 | runPath = os.path.dirname(os.path.realpath(__file__)) 15 | sys.path.append(os.path.join(runPath, "..")) 16 | 17 | import argparse 18 | 19 | from lib.cpelist import CPEList 20 | 21 | # parse command line arguments 22 | argparser = argparse.ArgumentParser(description='populate/update the whitelist used in webviews') 23 | argparser.add_argument('-a', metavar="CPE", nargs="*", help='Add one or more CPE to the whitelist') 24 | argparser.add_argument('-A', action='append', metavar="file", help='Read a file of CPEs and add them to the whitelist') 25 | argparser.add_argument('-r', metavar="CPE", nargs="*", help='Remove one or more CPE from the whitelist') 26 | argparser.add_argument('-R', action='append', metavar="file", help='Read a file of CPEs and remove them from the whitelist') 27 | argparser.add_argument('-t', metavar="type", default="cpe", help='Type of item to blacklist. Default: CPE') 28 | argparser.add_argument('-i', metavar="file", help='Import whitelist from file') 29 | argparser.add_argument('-e', metavar="file", help='Export whitelist to file') 30 | argparser.add_argument('-d', action='store_true', help='Drop the whitelist') 31 | argparser.add_argument('-f', action='store_true', help='Force') 32 | argparser.add_argument('-v', action='store_true', help='Verbose') 33 | args = argparser.parse_args() 34 | 35 | # Variables 36 | collection = "whitelist" 37 | 38 | def importWhitelist(importFile): 39 | oList = CPEList(collection, args) 40 | return oList.importList(importFile) 41 | 42 | 43 | def exportWhitelist(exportFile=None): 44 | oList = CPEList(collection, args) 45 | return oList.exportList(exportFile) 46 | 47 | 48 | def dropWhitelist(): 49 | oList = CPEList(collection, args) 50 | oList.dropCollection() 51 | 52 | 53 | def countWhitelist(): 54 | oList = CPEList(collection, args) 55 | return oList.countItems() 56 | 57 | 58 | def checkWhitelist(cpe): 59 | oList = CPEList(collection, args) 60 | amount = oList.check(cpe) 61 | return amount 62 | 63 | 64 | def insertWhitelist(cpe, cpeType): 65 | oList = CPEList(collection, args) 66 | return oList.insert(cpe,cpeType) 67 | 68 | 69 | def removeWhitelist(cpe): 70 | oList = CPEList(collection, args) 71 | return oList.remove(cpe) 72 | 73 | 74 | def updateWhitelist(cpeOld, cpeNew, cpeType): 75 | oList = CPEList(collection, args) 76 | return oList.update(cpeOld, cpeNew, cpeType) 77 | 78 | if __name__ == '__main__': 79 | oList = CPEList(collection, args) 80 | oList.process() 81 | -------------------------------------------------------------------------------- /web/static/css/custom/admin.css: -------------------------------------------------------------------------------- 1 | .tab { 2 | width: 300px; 3 | 4 | } 5 | #stats, #plugins, #token_request { 6 | float: right; 7 | width: calc(100% - 320px); 8 | } 9 | #stats, #plugins > table > tbody > tr > td{ 10 | font-size: 14px; 11 | } 12 | -------------------------------------------------------------------------------- /web/static/css/custom/cve.css: -------------------------------------------------------------------------------- 1 | .cve-info { 2 | width: 400px; 3 | } 4 | .cve-info td { 5 | text-align: center; 6 | } 7 | 8 | .table-even { 9 | table-layout: fixed 10 | } 11 | 12 | .impact-none { 13 | color:green; 14 | } 15 | 16 | .impact-partial { 17 | color:orange; 18 | } 19 | 20 | .impact-complete { 21 | color:red; 22 | } 23 | 24 | #actions { 25 | float:right; 26 | } 27 | 28 | #actions button { 29 | width:100%; 30 | } 31 | 32 | td > div { 33 | padding-right: 10px; 34 | } 35 | 36 | pre { 37 | white-space: pre-wrap; /* CSS 3 */ 38 | white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ 39 | white-space: -pre-wrap; /* Opera 4-6 */ 40 | white-space: -o-pre-wrap; /* Opera 7 */ 41 | word-wrap: break-word; /* Internet Explorer 5.5+ */ 42 | } 43 | -------------------------------------------------------------------------------- /web/static/css/custom/filter.css: -------------------------------------------------------------------------------- 1 | .searchTable{ 2 | border: 1px solid #CCCCCC; 3 | } 4 | .searchTable td{ 5 | padding: 4px; 6 | } 7 | .searchTable input[type="number"]{ 8 | width:60px; 9 | } 10 | .searchTable button{ 11 | float:right; 12 | } 13 | .text{ 14 | width: 100px; 15 | } 16 | -------------------------------------------------------------------------------- /web/static/css/sidebar.css: -------------------------------------------------------------------------------- 1 | body.withNav { 2 | background: none repeat scroll 0 0 white; 3 | padding-left: 26px; 4 | } 5 | nav.sidebar-menu-collapsed { 6 | width: 30px; 7 | } 8 | nav.sidebar-menu-expanded { 9 | width: auto; 10 | } 11 | nav.sidebar { 12 | position: fixed; 13 | top: 0px; 14 | left: 0px; 15 | height: 100%; 16 | background: none repeat scroll 0 0 #888; 17 | color: white; 18 | padding: 10px 5px; 19 | } 20 | nav.sidebar a#justify-icon { 21 | outline: 0; 22 | color: white; 23 | font-size: 18px; 24 | font-style: normal; 25 | } 26 | nav.sidebar ul { 27 | margin: 0; 28 | padding: 0; 29 | margin-top: 60px; 30 | } 31 | nav.sidebar ul li { 32 | margin: 0; 33 | padding: 0; 34 | list-style-type: none; 35 | } 36 | nav.sidebar ul li a.expandable { 37 | outline: 0; 38 | display: block; 39 | position: relative; 40 | width: 100%; 41 | height: 30px; 42 | color: white; 43 | text-decoration: none; 44 | text-align: left; 45 | padding: 4px 4px 4px 0px; 46 | font-size: 20px; 47 | } 48 | nav.sidebar ul li a.expandable:hover { 49 | color: #bbbbbb; 50 | } 51 | nav.sidebar ul li a.expandable span.expanded-element { 52 | display: none; 53 | font-size: 14px; 54 | position: relative; 55 | bottom: 5px; 56 | } 57 | nav.sidebar ul li:last-child { 58 | border-bottom: none; 59 | } 60 | nav.sidebar ul li a { 61 | text-decoration: none; 62 | outline: 0; 63 | color: white; 64 | text-decoration: none; 65 | font-size: 11px; 66 | } 67 | -------------------------------------------------------------------------------- /web/static/css/style.css: -------------------------------------------------------------------------------- 1 | .whitelisted{ 2 | color: #AA0000; 3 | } 4 | .blacklisted{ 5 | color: #555588; 6 | } 7 | .table.table-striped tr.selected{ 8 | background-color: #556677; 9 | color: #FFFFFF; 10 | } 11 | .listInput{ 12 | width:calc(50% - 25px); 13 | min-width:200px; 14 | } 15 | .listInput textarea, input[type=text]{ 16 | width:100%; 17 | } 18 | .listInput input[type=submit]{ 19 | margin:0px auto; 20 | width:150px; 21 | } 22 | .listInputCenter p{ 23 | padding-top:100px; 24 | text-align:center; 25 | } 26 | .invisiTable td{ 27 | padding:0px 5px; 28 | } 29 | .badge a{ 30 | color:white; 31 | } 32 | #admin{ 33 | float: right; 34 | } 35 | ul.nav li.dropdown:hover > ul.dropdown-menu { 36 | display: block; 37 | } 38 | .back-to-top { 39 | position: fixed; 40 | bottom: 2em; 41 | right: 0px; 42 | text-decoration: none; 43 | color: #000000; 44 | background-color: rgba(235, 180, 180, 0.70); 45 | font-size: 12px; 46 | padding: 1em; 47 | display: none; 48 | } 49 | .select-submit { 50 | position: fixed; 51 | bottom: 6em; 52 | right: 0px; 53 | text-decoration: none; 54 | color: #000000; 55 | background-color: rgba(180, 180, 235, 0.70); 56 | font-size: 12px; 57 | padding: 1em; 58 | display: none; 59 | } 60 | 61 | .back-to-top:hover { 62 | background-color: rgba(135, 135, 135, 0.50); 63 | } 64 | 65 | .table-nonfluid { 66 | width: auto; 67 | } 68 | 69 | .block { 70 | display: inline-block; 71 | } 72 | .semiCollapsed { 73 | overflow: hidden; 74 | text-overflow: ellipsis; 75 | max-height:110px; 76 | } 77 | 78 | .pagerdiv { 79 | width:100%; 80 | text-align:center; 81 | } 82 | 83 | #status { 84 | position:fixed; 85 | top: 50%; 86 | left: 50%; 87 | width:50em; 88 | height:6em; 89 | margin-top: -3em; 90 | margin-left: -25em; 91 | border: 1px solid #ccc; 92 | text-align:center; 93 | } 94 | 95 | .hidden { 96 | visibility:hide; 97 | } 98 | 99 | ul.via4 { 100 | padding-left:0px; 101 | } 102 | 103 | ul.via4 > li { 104 | margin: 3px 0px; 105 | padding-left: 3px; 106 | list-style-type: none; 107 | position: relative; 108 | } 109 | 110 | ul.via4 > li:after { 111 | padding:0;margin:0;display:block;/* not really needed */ 112 | content: ""; 113 | height:90%; 114 | width:3px; 115 | background-color: #8AE790; 116 | position: absolute; 117 | left:0; 118 | top:5%; 119 | } 120 | 121 | -------------------------------------------------------------------------------- /web/static/flash/ZeroClipboard.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PidgeyL/cve-search/8e47223fa34ba1375226b003ea362f2d29dff413/web/static/flash/ZeroClipboard.swf -------------------------------------------------------------------------------- /web/static/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PidgeyL/cve-search/8e47223fa34ba1375226b003ea362f2d29dff413/web/static/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /web/static/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PidgeyL/cve-search/8e47223fa34ba1375226b003ea362f2d29dff413/web/static/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /web/static/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PidgeyL/cve-search/8e47223fa34ba1375226b003ea362f2d29dff413/web/static/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /web/static/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PidgeyL/cve-search/8e47223fa34ba1375226b003ea362f2d29dff413/web/static/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /web/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PidgeyL/cve-search/8e47223fa34ba1375226b003ea362f2d29dff413/web/static/img/favicon.ico -------------------------------------------------------------------------------- /web/static/js/ZeroClipboard.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PidgeyL/cve-search/8e47223fa34ba1375226b003ea362f2d29dff413/web/static/js/ZeroClipboard.swf -------------------------------------------------------------------------------- /web/static/js/custom/admin.js: -------------------------------------------------------------------------------- 1 | function updateDB(){ 2 | setStatus("Database update started", "info") 3 | $.getJSON('/admin/updatedb', {}, function(data){ parseStatus(data) }) 4 | .fail(function() { parseStatus({"status": "auth_again"}); }) 5 | } 6 | function whitelistImport(){ listURLBuilder("/admin/whitelist/import", 'wl');} 7 | function blacklistImport(){ listURLBuilder("/admin/blacklist/import", 'bl');} 8 | function whitelistExport(){ window.location = '/admin/whitelist/export';} 9 | function blacklistExport(){ window.location = '/admin/blacklist/export';} 10 | function dropWhitelist(){ 11 | if(confirm("You are about to drop the whitelist. Are you sure?")){ 12 | $.getJSON('/admin/whitelist/drop', {}, function(data){ 13 | if (parseStatus(data)){$("#wl_rules").text("Whitelist: 0 rules");} 14 | }) 15 | } 16 | } 17 | function dropBlacklist(){ 18 | if(confirm("You are about to drop the whitelist. Are you sure?")){ 19 | $.getJSON('/admin/blacklist/drop', {}, function(data){ 20 | if (parseStatus(data)){$("#bl_rules").text("Blacklist: 0 rules");} 21 | }) 22 | } 23 | } 24 | function listURLBuilder(url, list){ 25 | var file = list+"_Import"; 26 | var force = ""; 27 | if ((document.getElementById(file).files).length == 1){ 28 | if (document.getElementById(list+"_ForceImport").checked == true){ 29 | force = "f"; 30 | }else{ 31 | force = "df"; 32 | } 33 | postURL(url, force, file) 34 | }else{ 35 | alert('Please select a file'); 36 | } 37 | } 38 | function postURL(url, force, file) { 39 | var form = document.createElement("FORM"); 40 | form.enctype="multipart/form-data"; 41 | form.method = "POST"; 42 | form.style.display = "none"; 43 | document.body.appendChild(form); 44 | form.action = url 45 | inputForce = document.createElement("INPUT"); 46 | inputForce.type = "hidden"; 47 | inputForce.name = "force" 48 | inputForce.value = force 49 | form.appendChild(inputForce); 50 | inputFile = document.getElementById(file); 51 | form.appendChild(inputFile); 52 | form.submit(); 53 | } 54 | function changePass() { 55 | var pass1 = document.getElementById("new_pass").value; 56 | var pass2 = document.getElementById("repeat_pass").value; 57 | var ok = true; 58 | if (pass1 != pass2) { 59 | document.getElementById("new_pass").style.borderColor = "#E34234"; 60 | document.getElementById("repeat_pass").style.borderColor = "#E34234"; 61 | }else { 62 | data = {'new_pass':pass1, 'current_pass':document.getElementById("current_pass").value} 63 | $.getJSON('/admin/change_pass', data, function(data){ parseStatus(data) }) 64 | .fail(function() { parseStatus({"status": "auth_again"}); }) 65 | } 66 | } 67 | function requestToken() { 68 | $.getJSON('/admin/request_token', data, function(data){$("#token").val(data['token'])}) 69 | } 70 | -------------------------------------------------------------------------------- /web/static/js/custom/autoload.js: -------------------------------------------------------------------------------- 1 | //Autoloads 2 | $(function() { 3 | $.getJSON('/_get_plugins',{},function(data){ 4 | plugins = data["plugins"] 5 | if(plugins == undefined || plugins.length == 0){ 6 | $("#sidebar").hide() 7 | $("body").removeClass("withNav"); 8 | }else{ 9 | $("#plugin-pages").empty() 10 | for (var i=0; i < plugins.length; i++){ 11 | j=plugins[i]; 12 | $("#plugin-pages").append("
  • "); 13 | } 14 | $("#sidebar").show() 15 | $("body").addClass("withNav"); 16 | } 17 | }) 18 | }) 19 | -------------------------------------------------------------------------------- /web/static/js/custom/cve.js: -------------------------------------------------------------------------------- 1 | function copyToClipboard() { 2 | var oTable = document.getElementById('cveInfo'); 3 | var rowLength = oTable.rows.length; 4 | var text = ""; 5 | for (i = 0; i < rowLength; i++){ 6 | var oCells = oTable.rows.item(i).cells; 7 | var attribute = oCells.item(0).innerHTML; 8 | var value = oCells.item(1).innerHTML; 9 | 10 | var toAdd = attribute + ": \t" + value; 11 | text = text + toAdd + "\n"; 12 | } 13 | text = text.replace("Copy to Clipboard", ""); 14 | text = text.replace(/<\/?[^>]+(>|$)/g, ""); 15 | text = text.replace(/\n\s+\n/g, "\n"); 16 | text = text.trim(); 17 | return text; 18 | } 19 | 20 | function loadPluginActions(){ 21 | $.getJSON('/plugin/_get_cve_actions',{cve: $("#_cveID").val()},function(data){ 22 | actions = data["actions"] 23 | $("#cve_actions").empty() 24 | $("#cve_actions").append('
    ') 25 | for(var i=0; i < actions.length; i++){ 26 | if(('icon' in actions[i]) || ('text' in actions[i])){ 27 | add="
    " 31 | $("#cve_actions").append(add); 32 | if('action' in actions[i]){ 33 | $("#action-"+i).attr('id', "action-"+actions[i]['plugin']+"-"+actions[i]['action']) 34 | $("#action-"+actions[i]['plugin']+"-"+actions[i]['action']).click(function(e){ 35 | plugin = this.id.split("-")[1] 36 | act = this.id.split("-")[2] 37 | $.getJSON('/plugin/'+plugin+'/_cve_action/'+act,{cve: $("#_cveID").val()},function(data){ 38 | parseStatus(data) 39 | loadPluginActions() 40 | }) 41 | }) 42 | } 43 | } 44 | } 45 | }) 46 | } 47 | 48 | $(document).ready(function() { 49 | loadPluginActions(); 50 | 51 | var client = new ZeroClipboard($("#copy-button"), { 52 | moviePath: "/static/js/ZeroClipboard.swf" 53 | }); 54 | client.setText(copyToClipboard()); 55 | }); 56 | -------------------------------------------------------------------------------- /web/static/js/custom/filter.js: -------------------------------------------------------------------------------- 1 | function timeSelectDisable(){ 2 | var selected = document.getElementById("timeSelect").value; 3 | switch(selected){ 4 | case "all": 5 | document.getElementById('startDate').readOnly = true; 6 | document.getElementById('endDate').readOnly = true; 7 | document.getElementById('timeTypeSelect').readOnly = true; 8 | break; 9 | case "from": 10 | document.getElementById('startDate').readOnly = false; 11 | document.getElementById('endDate').readOnly = true; 12 | document.getElementById('timeTypeSelect').readOnly = false; 13 | break; 14 | case "until": 15 | document.getElementById('startDate').readOnly = true; 16 | document.getElementById('endDate').readOnly = false; 17 | document.getElementById('timeTypeSelect').readOnly = false; 18 | break; 19 | case "between": 20 | case "outside": 21 | document.getElementById('startDate').readOnly = false; 22 | document.getElementById('endDate').readOnly = false; 23 | document.getElementById('timeTypeSelect').readOnly = false; 24 | } 25 | } 26 | function cvssSelectDisable(){ 27 | var selected = document.getElementById("cvssSelect").value; 28 | switch(selected){ 29 | case "all": 30 | document.getElementById('cvss').readOnly = true; 31 | break; 32 | default: 33 | document.getElementById('cvss').readOnly = false; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /web/static/js/custom/list.js: -------------------------------------------------------------------------------- 1 | function clear(table){ 2 | $("#"+table+"id").val(""); 3 | $("#"+table+"comments").val(""); 4 | $("#"+table+"add").val("Add"); 5 | if(table != "cpe"){$("#"+table+"select").val("targetsoftware");} 6 | $('#cancel'+table).remove(); 7 | editedcpe=""; 8 | editedkeyword=""; 9 | } 10 | var editedcpe; 11 | var editedkeyword; 12 | $(document).ready(function() { 13 | init(); 14 | }); 15 | function init(){ 16 | $('#cpes tbody tr').add('#keywords tbody tr').on( 'click', '#edit', function () { 17 | var table = $(this).closest('table').attr('id').slice(0, -1); 18 | $("#cancel"+table).remove(); 19 | window["edited"+table] = $(this).closest('tr').find("td").eq(2).text(); 20 | if(table == "cpe"){ var td=3; }else{ var td=4; } 21 | var comments = $(this).closest('tr').find("td").eq(td).text().split("\n"); 22 | var commentString=""; 23 | for(comment in comments){ 24 | if(comments[comment].trim().length!=0){commentString = commentString + comments[comment].trim() + "\n"}; 25 | } 26 | commentString = commentString.trim(); 27 | $("#"+table+"id").val(window["edited"+table]); 28 | $("#"+table+"comments").val(commentString); 29 | if(table != "cpe"){ 30 | $("#"+table+"select").val($(this).closest('tr').find("td").eq(3).text().trim().replace(" ","").toLowerCase()); 31 | } 32 | $("#"+table+"add").val("Edit"); 33 | $("#add"+table).append(" "); 34 | $('#cancel'+table).click(function() { 35 | clear(table); 36 | }); 37 | jQuery('html, body').animate({scrollTop: 0}, 500); 38 | }); 39 | } 40 | function remove(item){ 41 | if(confirm("Are you sure you want to remove this rule?")){ 42 | $.getJSON('/admin/removeFromList', { 43 | list: $("#values").val(), cpe:item 44 | }, function(data) { 45 | if(parseStatus(data)){ fillTable(data);} 46 | }); 47 | } 48 | } 49 | function addItem(cpetype) { 50 | var CPE, commentArray, keyword; 51 | var comments = ""; 52 | // get field info and build cpe 53 | if(cpetype == "cpe"){var listType="cpe"}else{var listType="keyword"} 54 | CPE = $("#"+listType+"id").val().trim(); 55 | commentArray = $("#"+listType+"comments").val().trim(); 56 | if(cpetype != "cpe"){ 57 | cpetype = $("#keywordselect").val().trim(); 58 | } 59 | if (commentArray){ 60 | commentArray = commentArray.split("\n"); 61 | for (comment in commentArray){ 62 | comments = comments + "# " + commentArray[comment]; 63 | } 64 | } 65 | CPE = CPE+comments; 66 | // check if cpe was edited 67 | if(window["edited"+listType]){ 68 | $.getJSON('/admin/editInList', { 69 | list: $("#values").val(), cpe:CPE, oldCPE:window["edited"+listType], type:cpetype 70 | }, function(data) { 71 | if(parseStatus(data)){ fillTable(data);} 72 | }); 73 | }else{ 74 | alert($("#values").val()); 75 | $.getJSON('/admin/addToList', { 76 | list: $("#values").val(), cpe:CPE, type:cpetype 77 | }, function(data) { 78 | if(parseStatus(data)){ fillTable(data);} 79 | }); 80 | } 81 | clear(listType); 82 | } 83 | function fillTable(data){ 84 | var rules=data['rules']; 85 | $("#cpes > tbody > tr").remove(); 86 | $("#keywords > tbody > tr").remove(); 87 | var line = ""; 88 | for (i=0;i"; 91 | //Second td 92 | if('comments' in rules[i]){line += ""; 93 | }else{ line += "";} 94 | //Third td 95 | line += ""+rules[i]['id']+""; 96 | //Possible fourth td 97 | if(rules[i]['type']!='cpe'){ 98 | if(rules[i]['type'] == 'targethardware'){ line += "Target Hardware"; 99 | }else if (rules[i]['type'] == 'targetsoftware'){ line += "Target Software";} 100 | } 101 | //last td 102 | line += "
      "; 103 | if('comments' in rules[i]){ 104 | for (j=0;j"; 106 | } 107 | } 108 | line += "
    "; 109 | if(rules[i]['type']=='cpe'){ $("#cpes > tbody").append(line); 110 | }else{ $("#keywords > tbody").append(line); 111 | } 112 | line=""; 113 | } 114 | init(); 115 | } 116 | 117 | -------------------------------------------------------------------------------- /web/static/js/custom/listmanagement.js: -------------------------------------------------------------------------------- 1 | function addCPE(list, item){ 2 | $.getJSON('/admin/listmanagement/add', { 3 | list:list, item:item 4 | }, function(data) { 5 | parseStatus(data); 6 | }); 7 | } 8 | -------------------------------------------------------------------------------- /web/static/js/custom/pager.js: -------------------------------------------------------------------------------- 1 | // Requires filter.js, where setSetings() is located 2 | function postURL(url) { 3 | var form = document.getElementById("filter"); 4 | form.action = url; 5 | form.submit(); 6 | } 7 | function next(n){ 8 | setSettings(); 9 | var url = "/r/"+n; 10 | postURL(url); 11 | } 12 | function previous(n){ 13 | setSettings(); 14 | if(n < 0){ 15 | n = 0;} 16 | var url = "/r/" + n; 17 | postURL(url); 18 | } 19 | -------------------------------------------------------------------------------- /web/static/js/custom/scripts.js: -------------------------------------------------------------------------------- 1 | //Search function 2 | function redirect() { 3 | var search = document.getElementById("search").value 4 | if(/^CVE-[0-9]{4}-[0-9]{4,6}$/.test(search.toUpperCase())){ 5 | var url = "/cve/" + search; window.location = url; 6 | }else{ 7 | var form = document.createElement("form"); 8 | form.method="POST"; 9 | form.action="/search"; 10 | var field = document.createElement("INPUT"); 11 | field.type = "hidden"; 12 | field.name = "search" 13 | field.value = search 14 | form.appendChild(field); 15 | document.body.appendChild(form); 16 | form.submit(); 17 | } 18 | 19 | } 20 | 21 | //Bootstrap tooltip 22 | jQuery(function () { 23 | $("[rel='tooltip']").tooltip(); 24 | }); 25 | 26 | //Back To Top 27 | jQuery(document).ready(function() { 28 | var offset = 220; 29 | var duration = 500; 30 | jQuery(window).scroll(function() { 31 | if (jQuery(this).scrollTop() > offset) { 32 | jQuery('.back-to-top').fadeIn(duration); 33 | } else { 34 | jQuery('.back-to-top').fadeOut(duration); 35 | } 36 | }); 37 | jQuery('.back-to-top').click(function(event) { 38 | event.preventDefault(); 39 | jQuery('html, body').animate({scrollTop: 0}, duration); 40 | return false; 41 | }) 42 | }); 43 | 44 | //Temporary undo class 45 | (function($){ 46 | $.fn.extend({ 47 | removeTemporaryClass: function(className, duration) { 48 | var elements = this; 49 | setTimeout(function() { 50 | elements.addClass(className); 51 | }, duration); 52 | return this.each(function() { 53 | $(this).removeClass(className); 54 | }); 55 | } 56 | }); 57 | })(jQuery); 58 | 59 | jQuery(document).ready(function() { 60 | var indicator = 0; 61 | 62 | jQuery('.colfield').each(function(){ 63 | $(this).html($(this).html() + ''); 64 | $(this).attr("id", "col_"+indicator); 65 | indicator +=1 66 | }); 67 | jQuery("[id^='colf_']").on('click', function(event){ 68 | name = "#col_" + $(this).attr("id").split("_")[1] 69 | $(name).toggleClass("semiCollapsed"); 70 | $(this).toggleClass("glyphicon-chevron-down glyphicon-chevron-up"); 71 | }); 72 | }); 73 | -------------------------------------------------------------------------------- /web/static/js/custom/sidebar.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | $(function () { 3 | var SideBAR; 4 | SideBAR = (function () { 5 | function SideBAR() {} 6 | 7 | SideBAR.prototype.expandMyMenu = function () { 8 | return $("nav.sidebar").removeClass("sidebar-menu-collapsed").addClass("sidebar-menu-expanded"); 9 | }; 10 | 11 | SideBAR.prototype.collapseMyMenu = function () { 12 | return $("nav.sidebar").removeClass("sidebar-menu-expanded").addClass("sidebar-menu-collapsed"); 13 | }; 14 | 15 | SideBAR.prototype.showMenuTexts = function () { 16 | return $("nav.sidebar ul a span.expanded-element").show(); 17 | }; 18 | 19 | SideBAR.prototype.hideMenuTexts = function () { 20 | return $("nav.sidebar ul a span.expanded-element").hide(); 21 | }; 22 | 23 | SideBAR.prototype.showActiveSubMenu = function () { 24 | $("li.active ul.level2").show(); 25 | return $("li.active a.expandable").css({ 26 | width: "100%" 27 | }); 28 | }; 29 | 30 | SideBAR.prototype.hideActiveSubMenu = function () { 31 | return $("li.active ul.level2").hide(); 32 | }; 33 | 34 | SideBAR.prototype.adjustPaddingOnExpand = function () { 35 | $("ul.level1 li a.expandable").css({ 36 | padding: "1px 4px 4px 0px" 37 | }); 38 | return $("ul.level1 li.active a.expandable").css({ 39 | padding: "1px 4px 4px 4px" 40 | }); 41 | }; 42 | 43 | SideBAR.prototype.resetOriginalPaddingOnCollapse = function () { 44 | $("ul.nbs-level1 li a.expandable").css({ 45 | padding: "4px 4px 4px 0px" 46 | }); 47 | return $("ul.level1 li.active a.expandable").css({ 48 | padding: "4px" 49 | }); 50 | }; 51 | 52 | SideBAR.prototype.ignite = function () { 53 | return (function (instance) { 54 | return $("#justify-icon").click(function (e) { 55 | if ($(this).parent("nav.sidebar").hasClass("sidebar-menu-collapsed")) { 56 | instance.adjustPaddingOnExpand(); 57 | instance.expandMyMenu(); 58 | instance.showMenuTexts(); 59 | instance.showActiveSubMenu(); 60 | $(this).css({ 61 | color: "#000" 62 | }); 63 | } else if ($(this).parent("nav.sidebar").hasClass("sidebar-menu-expanded")) { 64 | instance.resetOriginalPaddingOnCollapse(); 65 | instance.collapseMyMenu(); 66 | instance.hideMenuTexts(); 67 | instance.hideActiveSubMenu(); 68 | $(this).css({ 69 | color: "#FFF" 70 | }); 71 | } 72 | return false; 73 | }); 74 | })(this); 75 | }; 76 | 77 | return SideBAR; 78 | 79 | })(); 80 | return (new SideBAR).ignite(); 81 | }); 82 | 83 | }).call(this); 84 | -------------------------------------------------------------------------------- /web/static/js/custom/statusses.js: -------------------------------------------------------------------------------- 1 | function parseStatus(data){ 2 | _ok = false; 3 | if (data['status'] != undefined){ 4 | list = ""; 5 | if (data['status'].startsWith('wl_')){ list = "Whitelist"; 6 | }else if (data['status'].startsWith('bl_')){ list = "Blacklist";} 7 | 8 | switch(data['status']){ 9 | case "default": 10 | if (data['updateOutput'] != undefined){ 11 | setStatus("Last update info
    "+data['updateOutput']+"
    ", "success"); break; 12 | } 13 | _ok=true;break; 14 | case "logged_in": setStatus("Logged in successfully", "success"); _ok=true;break; 15 | case "auth_again": setStatus("Please authenticate again", "danger"); break; 16 | case "wrong_user_pass": setStatus("Combination user / password is wrong", "danger"); break; 17 | case "password_changed": setStatus("Password updated!", "success"); _ok=true;break; 18 | case "no_password": setStatus("Please make sure you enter a password", "danger"); break; 19 | case "outdated_database": setStatus("The database model is outdated! Please update to the latest database model", "danger"); break; 20 | case "db_updated": setStatus("Database update finished
    "+data['updateOutput']+"
    ", "success"); _ok=true;break; 21 | case "wl_imported": 22 | case "bl_imported": setStatus(list+" import finished"); _ok=true;break; 23 | case "wl_already_filled": 24 | case "bl_already_filled": setStatus(list+" is already filled. You can force to drop the database", "info"); break; 25 | case "wl_dropped": 26 | case "bl_dropped": setStatus(list+" dropped", "success"); _ok=true;break; 27 | case "added_to_list": briefShow("Rule added to the "+data["listType"], "success", "ok"); _ok=true;break; 28 | case "could_not_add_to_list": briefShow("Could not add the CPE to the " +data["listType"], "danger", "remove"); break; 29 | case "removed_from_list": briefShow("Rule removed from the "+data["listType"], "success", "ok"); _ok=true;break; 30 | case "already_exists_in_list": briefShow("This rule or a more global rule already exists in the "+data["listType"], "info", "info"); break; 31 | case "already_removed_from_list": briefShow("Rule was already removed from the "+data["listType"], "info", "info"); break; 32 | case "invalid_cpe": briefShow("This cpe is not valid", "danger", "remove"); break; 33 | case "cpelist_updated": briefShow("The rule was updated", "success", "ok"); _ok=true;break; 34 | case "cpelist_update_failed": briefShow("Failed to update the rule in the "+data["listType"], "danger", "remove"); break; 35 | case "plugin_action_failed": setStatus("The action of the plugin failed", "danger"); break; 36 | case "plugin_action_complete": _ok=true;break; 37 | default: 38 | setStatus("A problem occurred with the server!", "danger"); 39 | } 40 | } 41 | return _ok; 42 | } 43 | 44 | function setStatus(text, status){ 45 | $("#status-box").empty(); 46 | $("#status-box").removeClass(); 47 | $("#status-box").addClass("alert alert-"+status); 48 | $("#status-box").append(text); 49 | } 50 | 51 | function briefShow(text, status, icon){ 52 | $("#status").removeClass(); 53 | $("#status").addClass("alert alert-"+status); 54 | $("#status_icon").removeClass(); 55 | $("#status_icon").addClass("glyphicon glyphicon-"+icon+"-sign"); 56 | $("#status_message").empty(); 57 | $("#status_message").append(text); 58 | $("#status").removeTemporaryClass("hidden", 3000); 59 | } 60 | -------------------------------------------------------------------------------- /web/static/js/html5shiv.js: -------------------------------------------------------------------------------- 1 | /* 2 | HTML5 Shiv v3.6.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | (function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag(); 5 | a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x"; 6 | c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode|| 7 | "undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup main mark meter nav output progress section summary time video",version:"3.6.2",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment(); 8 | for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d 6 |

    404

    7 |

    This means page not found

    8 |

    You navigated to a page that cannot be recreated by the server. Check the URL or try something else.

    9 | 10 | {% endblock %} 11 | -------------------------------------------------------------------------------- /web/templates/admin.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/master-page' %} 2 | {% block title %}Admin page{% endblock %} 3 | {% block head %} 4 | 5 | 6 | 7 | 8 | 9 | 15 | {% endblock %} 16 | {% block content %} 17 |
    18 | Database info for database {{stats['stats']['dbName']}} 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
    Collection#recordsLast update
    CVES {{stats['data']['cves']['size']}} {% if stats['data']['cves']['last_update'] is not none %} {{stats['data']['cves']['last_update'].strftime('%d-%m-%Y - %H:%M')}} {% else %}Not updated{% endif %}
    CPE {{stats['data']['cpe']['size']}} {% if stats['data']['cpe']['last_update'] is not none %} {{stats['data']['cpe']['last_update'].strftime('%d-%m-%Y - %H:%M')}} {% else %}Not updated{% endif %}
    CPE-other {{stats['data']['cpeOther']['size']}}{% if stats['data']['cpeOther']['last_update'] is not none %} {{stats['data']['cpeOther']['last_update'].strftime('%d-%m-%Y - %H:%M')}} {% else %}Not updated{% endif %}
    Capec {{stats['data']['capec']['size']}} {% if stats['data']['capec']['last_update'] is not none %} {{stats['data']['capec']['last_update'].strftime('%d-%m-%Y - %H:%M')}} {% else %}Not updated{% endif %}
    CWE {{stats['data']['cwe']['size']}} {% if stats['data']['cwe']['last_update'] is not none %} {{stats['data']['cwe']['last_update'].strftime('%d-%m-%Y - %H:%M')}} {% else %}Not updated{% endif %}
    via4 {{stats['data']['via4']['size']}} {% if stats['data']['via4']['last_update'] is not none %} {{stats['data']['via4']['last_update'].strftime('%d-%m-%Y - %H:%M')}} {% else %}Not updated{% endif %}
    38 | Whitelist: {{stats['data']['whitelist']['size']}} rules
    39 | Blacklist: {{stats['data']['blacklist']['size']}} rules

    40 | Database size: {{'%0.2f' % (stats['stats']['db_size']/1024**2)}}MB ({{'%0.2f' % (stats['stats']['db_size']/1024**3)}}GB)
    41 | Database size on disk: {{'%0.2f' % (stats['stats']['size_on_disk']/1024**2)}}MB ({{'%0.2f' % (stats['stats']['size_on_disk']/1024**3)}}GB) 42 |
    43 | 44 |
    45 | 46 | 47 | 48 | 49 | 50 |
    51 |
    52 | 53 |
    54 | Plug-in Information
    55 | 56 | 57 | 58 | 59 | 60 | {% for plug in plugins|sort(attribute="name") %} 61 | {% set ptype = "Web" if plug.isWebPlugin() else "Backend" %} 62 | 63 | {% endfor %} 64 | 65 |
    NameUIDTypeState
    {{plug.name}}{{plug.uid}}{{ptype}}{{plug.loadstate}}
    66 |
    67 | 68 |
    69 | Update the database
    70 | 71 |
    72 | 73 |
    74 | Manage whitelist
    75 |
    76 | Force
    77 | 78 | 79 | 80 | 81 |
    82 | 83 |
    84 | Manage blacklist
    85 |
    86 | Force
    87 | 88 | 89 | 90 | 91 |
    92 | 93 |
    94 | Change your password
    95 | 96 | 97 | 98 | 99 |
    Current
    New
    Repeat
    100 | 101 |
    102 | Back to Top 103 | {% endblock %} 104 | -------------------------------------------------------------------------------- /web/templates/bookmarked.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/master-page' %} 2 | {% block title %}Bookmarked CVEs{% endblock %} 3 | {% block content %} 4 | 5 | 9 | {% include 'subpages/table.html' %} 10 | {% endblock %} 11 | -------------------------------------------------------------------------------- /web/templates/browse.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/master-page' %} 2 | {% block title %}Vendor browsing{% endblock %} 3 | {% block content %} 4 | 5 | 13 | 14 | 15 | 16 | 17 | {% if product != None %} 18 | 19 | {% elif product == None %} 20 | 21 | {% endif %} 22 | 23 | {% if product != None %} 24 | {% for p in product %} 25 | 26 | 27 | 28 | {% endfor %} 29 | {% else %} 30 | {% for v in vendor %} 31 | 32 | 33 | 34 | {% endfor %} 35 | {% endif %} 36 | 37 |
    Products for {{ vendor|htmlDecode }}Vendors
    {{ p|htmlDecode }}
    {{ v|htmlDecode }}
    38 | {% endblock %} 39 | -------------------------------------------------------------------------------- /web/templates/capec.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/master-page' %} 2 | {% block title %}CAPEC browsing{% endblock %} 3 | {% block content %} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 19 | 20 | 21 |
    Name {{capec.name}}
    Summary {{capec.summary}}
    Prerequisites {{capec.prerequisites}}
    Solutions {{capec.solutions}}
    Related Weaknesses 12 | 13 | 14 | {% for c in capec.related_weakness|sortIntLikeStr %} 15 | 16 | {% endfor %} 17 |
    CWE ID Description
    CWE-{{c}} {{cwes[c]}}
    18 |
    22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /web/templates/cwe.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/master-page' %} 2 | {% block title %}Weakness browsing{% endblock %} 3 | {% block content %} 4 | {% if capec != None %} 5 | 6 | 10 | {% endif %} 11 |
    12 | 13 | 14 | 15 | {% if capec == None %} 16 | 17 | {% else %} 18 | 19 | {% endif %} 20 | 21 | {% if capec == None %} 22 | {% for c in cwes %} 23 | 24 | {% endfor %} 25 | {% else %} 26 | {% for c in capec %} 27 | 28 | 29 | 34 | 35 | {% endfor %} 36 | {% endif %} 37 | 38 |
    CWE ID DescriptionCAPEC Related Weakness
    CWE-{{c.id}} {{c.name}}
    {{c.name}}
    30 | {% for r in c.related_weakness|sortIntLikeStr %} 31 | {% endfor %} 32 |
    CWE-{{r}}{{cwes[r]}}
    33 |
    39 |
    40 | {% endblock %} 41 | -------------------------------------------------------------------------------- /web/templates/documentation/api/blacklist: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set admin = True %} 3 | {% set id = "blacklist" %} 4 | {% set title = "/api/admin/blacklist" %} 5 | {% set method = "GET" %} 6 | 7 | 8 | {% block desc %} 9 | Returns the content of the blacklist.
    10 | The blacklist is a list of CPEs that will hide a CVE when all the CPEs a product applies to are blacklisted. 11 | It is intended to be used as a way to hide unwanted information.
    12 | There are three types of CPEs: 13 |
      14 |
    • cpe - A fully qualified CPE code in CPE2.2 or CPE2.3 format
    • 15 |
    • targetsoftware - A software the CPE applies to. Equivalent to cpe:2.3:-:-:-:-:-:-:-:-:<cpe>
    • 16 |
    • targethardware - A hardware the CPE applies to. Equivalent to cpe:2.3:-:-:-:-:-:-:-:-:-:<cpe>
    • 17 |
    18 | Other types are possible, but are not used by the software. 19 | {% endblock %} 20 | 21 | {% block output %} 22 | [ 23 | { 24 | "id": "iphone_os", 25 | "type": "targetsoftware" 26 | }, 27 | { 28 | "id": "cpe:2.3:o:apple", 29 | "type": "cpe" 30 | }, 31 | { 32 | "id": "cpe:2.3:o:microsoft:windows_xp", 33 | "type": "cpe" 34 | } 35 | ] 36 | {% endblock %} 37 | -------------------------------------------------------------------------------- /web/templates/documentation/api/blacklist_add: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set admin = True %} 3 | {% set id = "blacklist_add" %} 4 | {% set title = "/api/admin/blacklist/add" %} 5 | {% set method = "PUT" %} 6 | {% set headers = [('Content-Type', "This field is required to be set to:", "application/x-www-form-urlencoded")]%} 7 | {% set formdata = [('cpe', "CPE code in cpe2.2 or cpe2.3 format", "cpe:2.3:o:gnu:gcc#Comment"), 8 | ('type', "CPE type", "cpe, targetsoftware or targethardware")] %} 9 | 10 | {% block desc %} 11 | Adds a CPE to the blacklist. If the CPE was added to the blacklist, the output will be true. If not, it will be false.
    12 | Comments can be added by appending # 13 | {% endblock %} 14 | 15 | {% block output %} 16 | true 17 | {% endblock %} 18 | -------------------------------------------------------------------------------- /web/templates/documentation/api/blacklist_drop: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set admin = True %} 3 | {% set id = "blacklist_drop" %} 4 | {% set title = "/api/admin/blacklist/drop" %} 5 | {% set method = "POST" %} 6 | 7 | 8 | {% block desc %} 9 | Drops the content of the blacklist. 10 | {% endblock %} 11 | 12 | {% block output %} 13 | null 14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /web/templates/documentation/api/blacklist_export: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set admin = True %} 3 | {% set id = "blacklist_export" %} 4 | {% set title = "/api/admin/blacklist/export" %} 5 | {% set method = "GET" %} 6 | 7 | 8 | {% block desc %} 9 | See /api/admin/blacklist 10 | {% endblock %} 11 | 12 | {% block output %} 13 | [ 14 | { 15 | "id": "iphone_os", 16 | "type": "targetsoftware" 17 | }, 18 | { 19 | "id": "cpe:2.3:o:apple", 20 | "type": "cpe" 21 | }, 22 | { 23 | "id": "cpe:2.3:o:microsoft:windows_xp", 24 | "type": "cpe" 25 | } 26 | ] 27 | {% endblock %} 28 | -------------------------------------------------------------------------------- /web/templates/documentation/api/blacklist_import: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set admin = True %} 3 | {% set id = "blacklist_import" %} 4 | {% set title = "/api/admin/blacklist/import" %} 5 | {% set method = "PUT" %} 6 | 7 | 8 | {% block desc %} 9 | Imports the blacklist. The blacklist data should be of the same format as the output of 10 | /api/admin/blacklist 11 | and should be put in the request body. 12 | {% endblock %} 13 | 14 | {% block output %} 15 | null 16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /web/templates/documentation/api/blacklist_remove: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set admin = True %} 3 | {% set id = "blacklist_remove" %} 4 | {% set title = "/api/admin/blacklist/remove" %} 5 | {% set method = "PUT" %} 6 | {% set headers = [('Content-Type', "This field is required to be set to:", "application/x-www-form-urlencoded")]%} 7 | {% set formdata = [('cpe', "CPE code in cpe2.2 or cpe2.3 format", "cpe:2.3:o:gnu:gcc#Comment")] %} 8 | 9 | {% block desc %} 10 | Remove a CPE from the blacklist. If the CPE was removed from the blacklist, the output will be true. If not, it will be false. 11 | {% endblock %} 12 | 13 | {% block output %} 14 | true 15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /web/templates/documentation/api/browse: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set id = "browse" %} 3 | {% set title = "/api/browse/<vendor>" %} 4 | {% set method = "GET" %} 5 | {% set args = [('vendor', "Vendor name", "microsoft")] %} 6 | 7 | {% block desc %} 8 | Returns a list of vendors or products of a specific vendor.
    9 | This API call can be used in two ways; With or without the vendor.
    10 | When the link is called without a vendor, it will return a list of possible vendors.
    11 | When the link is called with a vendor, it enumerates the products for said vendor. 12 | {% endblock %} 13 | 14 | {% block output %} 15 | { 16 | "product": null, 17 | "vendor": [ 18 | "%240.99_kindle_books_project", 19 | "1024cms", 20 | "11in1", 21 | "129zou", 22 | "12net", 23 | "133", 24 | "163", 25 | "1800contacts", 26 | "1kxun", 27 | "2g_live_tv_project", 28 | ... 29 | 30 | 31 | { 32 | "vendor": "microsoft" 33 | "product": [ 34 | ".net_framework", 35 | ".net_windows_server", 36 | "access", 37 | "access_multilingual_user_interface_pack", 38 | "active_directory", 39 | "active_directory_application_mode", 40 | "active_directory_federation_services", 41 | ... 42 | {% endblock %} 43 | -------------------------------------------------------------------------------- /web/templates/documentation/api/capec: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set id = "capec" %} 3 | {% set title = "/api/capec/<cweid>" %} 4 | {% set method = "GET" %} 5 | {% set args = [('cweid', "CWE ID", "200")] %} 6 | 7 | {% block desc %} 8 | Outputs a list of CAPEC related to a CWE.
    9 | CAPEC (Common Attack Pattern Enumeration and Classification) are a list of attack types commonly used by attackers. 10 | {% endblock %} 11 | 12 | {% block output %} 13 | [ 14 | { 15 | "id": "13", 16 | "name": "Subverting Environment Variable Values", 17 | "prerequisites": "An environment variable is accessible to the user.\nAn environment variable used by the application can be tainted with user supplied data.\nInput data used in an environment variable is not validated properly.\nThe variables encapsulation is not done properly. For instance setting a variable as public in a class makes it visible and an attacker may attempt to manipulate that variable.", 18 | "related_weakness": [ 19 | "353", 20 | "285", 21 | "302", 22 | "74", 23 | "15", 24 | "73", 25 | "20", 26 | "200" 27 | ], 28 | "solutions": "Protect environment variables against unauthorized read and write access.\nProtect the configuration files which contain environment variables against illegitimate read and write access.\nAssume all input is malicious. Create a white list that defines all valid input to the software system based on the requirements specifications. Input that does not match against the white list should not be permitted to enter into the system.\nApply the least privilege principles. If a process has no legitimate reason to read an environment variable do not give that privilege.", 29 | "summary": "The attacker directly or indirectly modifies environment variables used by or controlling the target software. The attacker's goal is to cause the target software to deviate from its expected operation in a manner that benefits the attacker." 30 | }, 31 | ... 32 | {% endblock %} 33 | -------------------------------------------------------------------------------- /web/templates/documentation/api/cpe22: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set id = "cpe22" %} 3 | {% set title = "/api/cpe2.2/<cpe>" %} 4 | {% set method = "GET" %} 5 | {% set args = [('cpe', "CPE code in cpe2.2 or cpe2.3 format", "cpe:2.3:o:microsoft:windows_vista:6.0:sp1:-:-:home_premium:-:-:x64:-")] %} 6 | 7 | {% block desc %} 8 | Converts a CPE code to the CPE2.2 standard, stripped of appendices.
    9 | CPE2.2 is the old standard, and is a lot less uniform than the CPE2.3 standard. 10 | {% endblock %} 11 | 12 | {% block output %} 13 | cpe:/o:microsoft:windows_vista:6.0:sp1:~~home_premium~~x64~ 14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /web/templates/documentation/api/cpe23: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set id = "cpe23" %} 3 | {% set title = "/api/cpe2.3/<cpe>" %} 4 | {% set method = "GET" %} 5 | {% set args = [('cpe', "CPE code in cpe2.2 or cpe2.3 format", "cpe:/o:microsoft:windows_vista:6.0:sp1:~-~home_premium~-~x64~-")] %} 6 | 7 | {% block desc %} 8 | Converts a CPE code to the CPE2.3 standard, stripped of appendices.
    9 | CPE2.3 is the newer standard, and is a lot more uniform and easier to read than the CPE2.2 standard. 10 | {% endblock %} 11 | 12 | {% block output %} 13 | cpe:2.3:o:microsoft:windows_vista:6.0:sp1:-:-:home_premium:-:-:x64 14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /web/templates/documentation/api/cve: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set id = "cve" %} 3 | {% set title = "/api/cve/<cveid>" %} 4 | {% set method = "GET" %} 5 | {% set args = [('cveid', "CVE number", "CVE-2016-3333")] %} 6 | 7 | {% block desc %} 8 | Outputs all available information for the specified CVE (Common Vulnerability and Exposure), in JSON format.
    9 | This information includes basic CVE information like CVSS (Common Vulnerability Scoring System), 10 | related CPE (Common Product Enumeration), CWE (Common Weakness Enumeration), ... as well as additional information (RedHat Advisories etc). 11 | {% endblock %} 12 | 13 | {% block output %} 14 | { 15 | "cvss": "9.3", 16 | "cvss-time": { 17 | "$date": 1478779997053 18 | }, 19 | "cwe": "CWE-119", 20 | "id": "CVE-2016-3333", 21 | "impact": { 22 | "availability": "COMPLETE", 23 | "confidentiality": "COMPLETE", 24 | "integrity": "COMPLETE" 25 | }, 26 | "last-modified": { 27 | "$date": 1480345703170 28 | }, 29 | ... 30 | {% endblock %} 31 | -------------------------------------------------------------------------------- /web/templates/documentation/api/cvefor: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set id = "cvefor" %} 3 | {% set title = "/api/cvefor/<cpe>" %} 4 | {% set method = "GET" %} 5 | {% set args = [('cpe', "CPE code in cpe2.2 or cpe2.3 format", "cpe:/o:microsoft:windows_vista:6.0:sp1:~-~home_premium~-~x64~-")] %} 6 | 7 | {% block desc %} 8 | Outputs a list of CVEs related to the product 9 | {% endblock %} 10 | 11 | {% block output %} 12 | [ 13 | { 14 | "cvss": 7.5, 15 | "cvss-time": { 16 | "$date": 1117762800000 17 | }, 18 | "id": "CVE-2005-0100", 19 | "impact": { 20 | "availability": "PARTIAL", 21 | "confidentiality": "PARTIAL", 22 | "integrity": "PARTIAL" 23 | }, 24 | ... 25 | {% endblock %} 26 | -------------------------------------------------------------------------------- /web/templates/documentation/api/cwe: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set id = "cwe" %} 3 | {% set title = "/api/cwe" %} 4 | {% set method = "GET" %} 5 | 6 | 7 | {% block desc %} 8 | Outputs a list of all CWEs (Common Weakness Enumeration). 9 | {% endblock %} 10 | 11 | {% block output %} 12 | [ 13 | { 14 | "description_summary": "Information sent over a network can be compromised while in transit. An attacker may be able to read/modify the contents if the data are sent in plaintext or are weakly encrypted.Information sent over a network can be compromised while in transit. An attacker may be able to read/modify the contents if the data are sent in plaintext or are weakly encrypted.", 15 | "id": "5", 16 | "name": "J2EE Misconfiguration: Data Transmission Without Encryption", 17 | "status": "Draft", 18 | "weaknessabs": "Variant" 19 | }, 20 | ... 21 | {% endblock %} 22 | -------------------------------------------------------------------------------- /web/templates/documentation/api/dbInfo: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set id = "dbInfo" %} 3 | {% set title = "/api/dbInfo" %} 4 | {% set method = "GET" %} 5 | 6 | 7 | {% block desc %} 8 | Returns the stats of the database. When the user authenticates, more information is returned. This information includes: 9 |
      10 |
    • Amount of whitelist and blacklist records
    • 11 |
    • Some server settings like the database name
    • 12 |
    • Some database information like disk usage
    • 13 |
    14 | Unauthenticated queries return only collection information. 15 | {% endblock %} 16 | 17 | {% block output %} 18 | { 19 | "capec": { 20 | "last_update": { 21 | "$date": 1417734881000 22 | }, 23 | "size": 463 24 | }, 25 | "cpe": { 26 | "last_update": { 27 | "$date": 1485582988000 28 | }, 29 | "size": 117276 30 | }, 31 | "cpeOther": { 32 | "last_update": null, 33 | "size": 0 34 | }, 35 | "cves": { 36 | "last_update": { 37 | "$date": 1485781223000 38 | }, 39 | "size": 81284 40 | }, 41 | "cwe": { 42 | "last_update": { 43 | "$date": 1406765683000 44 | }, 45 | "size": 719 46 | }, 47 | "via4": { 48 | "last_update": { 49 | "$date": 1485703986000 50 | }, 51 | "size": 81143 52 | } 53 | } 54 | {% endblock %} 55 | -------------------------------------------------------------------------------- /web/templates/documentation/api/dbupdate: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set admin = True %} 3 | {% set id = "updatedb" %} 4 | {% set title = "/api/admin/updatedb" %} 5 | {% set method = "GET" %} 6 | 7 | {% block desc %} 8 | Update the database.
    9 | The return value of the of the request is the output of the database update. This might take a long time to finish. 10 | {% endblock %} 11 | 12 | {% block output %} 13 | Not modified 14 | Not modified 15 | Not modified 16 | Not modified 17 | Not modified 18 | Not modified 19 | [+]Success to create index id on cpe 20 | [+]Success to create index id on cpeother 21 | [+]Success to create index id on cves 22 | [+]Success to create index vulnerable_configuration on cves 23 | [+]Success to create index Modified on cves 24 | [+]Success to create index [('summary', 'text')] on cves 25 | [+]Success to create index id on vendor 26 | [+]Success to create index id on via4 27 | [+]Success to create index id on mgmt_whitelist 28 | [+]Success to create index id on mgmt_blacklist 29 | [+]Success to create index related_weakness on capec 30 | ========================== 31 | Wed 01 February 2017 08:37 32 | ========================== 33 | Starting cve 34 | cve has 81370 elements (0 update) 35 | Starting cpe 36 | cpe has 117276 elements (0 update) 37 | Starting vendor 38 | vendor has 1426 elements (0 update) 39 | Starting cwe 40 | cwe has 719 elements (0 update) 41 | Starting capec 42 | capec has 463 elements (0 update) 43 | Starting via4 44 | via4 has 81143 elements (0 update) 45 | Starting ensureindex 46 | 47 | [!] Could not find plugin loader file! 48 | {% endblock %} 49 | -------------------------------------------------------------------------------- /web/templates/documentation/api/last: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set id = "last" %} 3 | {% set title = "/api/last/<limit>" %} 4 | {% set method = "GET" %} 5 | {% set args = [('limit', "The amount of CVEs to display", "10")] %} 6 | 7 | {% block desc %} 8 | Outputs the last n amount of vulnerabilities. If the limit is not specified, the default of 30 is used. 9 | {% endblock %} 10 | 11 | {% block output %} 12 | [ 13 | { 14 | "Modified": { 15 | "$date": 1485277140307 16 | }, 17 | "Published": { 18 | "$date": 1485277140307 19 | }, 20 | "cvss": null, 21 | "cwe": "Unknown", 22 | "id": "CVE-2016-10162", 23 | "last-modified": { 24 | "$date": 1485277140307 25 | }, 26 | "references": [ 27 | "http://php.net/ChangeLog-7.php", 28 | "https://bugs.php.net/bug.php?id=73831", 29 | "https://github.com/php/php-src/commit/8d2539fa0faf3f63e1d1e7635347c5b9e777d47b" 30 | ], 31 | "summary": "The php_wddx_pop_element function in ext/wddx/wddx.c in PHP 7.0.x before 7.0.15 and 7.1.x before 7.1.1 allows remote attackers to cause a denial of service (NULL pointer dereference and application crash) via an inapplicable class name in a wddxPacket XML document, leading to mishandling in a wddx_deserialize call.", 32 | "vulnerable_configuration": [], 33 | "vulnerable_configuration_cpe_2_2": [] 34 | }, 35 | ... 36 | {% endblock %} 37 | -------------------------------------------------------------------------------- /web/templates/documentation/api/link: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set id = "link" %} 3 | {% set title = "/api/link/<key>/<value>" %} 4 | {% set method = "GET" %} 5 | {% set args = [('key', "The key to link CVEs on", "msbulletin.bulletin_id"), 6 | ('value', "The value for the given key", "MS16-098")] %} 7 | 8 | {% block desc %} 9 | Returns all CVEs that are linked by a given key/value pair 10 | {% endblock %} 11 | 12 | {% block output %} 13 | { 14 | "stats": { 15 | "count": 4, 16 | "maxCVSS": 7.2, 17 | "minCVSS": 7.2 18 | }, 19 | "cves": [ 20 | { 21 | "Modified": { 22 | "$date": 1474927194753 23 | }, 24 | "Published": { 25 | "$date": 1470765557223 26 | }, 27 | "access": { 28 | "authentication": "NONE", 29 | "complexity": "LOW", 30 | "vector": "LOCAL" 31 | }, 32 | "cvss": "7.2", 33 | "cvss-time": { 34 | "$date": 1470923642083 35 | }, 36 | "cwe": "CWE-264", 37 | "id": "CVE-2016-3310", 38 | "impact": { 39 | "availability": "COMPLETE", 40 | "confidentiality": "COMPLETE", 41 | "integrity": "COMPLETE" 42 | }, 43 | ... 44 | {% endblock %} 45 | -------------------------------------------------------------------------------- /web/templates/documentation/api/query: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set id = "query" %} 3 | {% set title = "/api/query" %} 4 | {% set method = "GET" %} 5 | {% set headers = [('rejected', "Hide or show rejected CVEs", "show(default)/hide"), 6 | ('cvss_score', "CVSS score", "6.8"), 7 | ('cvss_modifier', "Select the CVSS score of the CVEs related to cvss_score", "above/equals/below"), 8 | ('time_start', "Earliest time for a CVE", "dd-mm-yyyy or dd-mm-yy format, using - or /"), 9 | ('time_end', "Latest time for a CVE", "dd-mm-yyyy or dd-mm-yy format, using - or /"), 10 | ('time_modifier', "Timeframe for the CVEs, related to the start and end time", "from/until/between/outside"), 11 | ('time_type', "Select which time is used for the filter", "Modified/Published/last-modified"), 12 | ('skip', "Skip the n latest vulnerabilities", "50"), 13 | ('limit', "Limit the amount of vulnerabilities to return", "20"), 14 | ]%} 15 | 16 | {% block desc %} 17 | Returns a list of CVEs matching the criteria of the filters specified in the headers. 18 | {% endblock %} 19 | 20 | {% block output %} 21 | [ 22 | { 23 | "Modified": { 24 | "$date": 1480730341713 25 | }, 26 | "Published": { 27 | "$date": 1480730340167 28 | }, 29 | "cvss": 10.0, 30 | "cwe": "CWE-287", 31 | "id": "CVE-2016-9796", 32 | "last-modified": { 33 | "$date": 1481117600060 34 | }, 35 | "references": [ 36 | "http://blog.malerisch.net/2016/12/alcatel-omnivista-8770-unauth-rce-giop-corba.html", 37 | "http://www.securityfocus.com/bid/94649", 38 | "https://github.com/malerisch/omnivista-8770-unauth-rce", 39 | "https://www.youtube.com/watch?v=aq37lQKa9sk" 40 | ], 41 | "summary": "Alcatel-Lucent OmniVista 8770 2.0 through 3.0 exposes different ORBs interfaces, which can be queried using the GIOP protocol on TCP port 30024. An attacker can bypass authentication, and OmniVista invokes methods (AddJobSet, AddJob, and ExecuteNow) that can be used to run arbitrary commands on the server, with the privilege of NT AUTHORITY\\SYSTEM on the server. NOTE: The discoverer states \"The vendor position is to refer to the technical guidelines of the product security deployment to mitigate this issue, which means applying proper firewall rules to prevent unauthorised clients to connect to the OmniVista server.\"", 42 | "vulnerable_configuration": [ 43 | "cpe:2.3:a:alcatel-lucent:omnivista_8770_network_management_system:2.6", 44 | ... 45 | {% endblock %} 46 | -------------------------------------------------------------------------------- /web/templates/documentation/api/search: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set id = "search" %} 3 | {% set title = "/api/search/<vendor>/<product>" %} 4 | {% set method = "GET" %} 5 | {% set args = [('vendor', "Vendor name", "microsoft"), ('product', "Product name", "excel")] %} 6 | 7 | {% block desc %} 8 | When vendor and product are specified, this API call returns a list of CVEs related to the product. 9 | The output of the browse call can be used for this. 10 | {% endblock %} 11 | 12 | {% block output %} 13 | [ 14 | { 15 | "Modified": { 16 | "$date": 1480347506210 17 | }, 18 | "Published": { 19 | "$date": 1478743189440 20 | }, 21 | "access": { 22 | "authentication": "NONE", 23 | "complexity": "MEDIUM", 24 | "vector": "NETWORK" 25 | }, 26 | "cvss": "9.3", 27 | "cvss-time": { 28 | "$date": 1478772824700 29 | }, 30 | "cwe": "CWE-119", 31 | "id": "CVE-2016-7236", 32 | "impact": { 33 | "availability": "COMPLETE", 34 | "confidentiality": "COMPLETE", 35 | "integrity": "COMPLETE" 36 | }, 37 | ... 38 | {% endblock %} 39 | -------------------------------------------------------------------------------- /web/templates/documentation/api/whitelist: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set admin = True %} 3 | {% set id = "whitelist" %} 4 | {% set title = "/api/admin/whitelist" %} 5 | {% set method = "GET" %} 6 | 7 | 8 | {% block desc %} 9 | Returns the content of the whitelist.
    10 | The whitelist is a list of CPEs that will mark a CVE when the CVE applies to the product. 11 | It is intended to be used as a notification/warning mechanism.
    12 | There are three types of CPEs: 13 |
      14 |
    • cpe - A fully qualified CPE code in CPE2.2 or CPE2.3 format
    • 15 |
    • targetsoftware - A software the CPE applies to. Equivalent to cpe:2.3:-:-:-:-:-:-:-:-:<cpe>
    • 16 |
    • targethardware - A hardware the CPE applies to. Equivalent to cpe:2.3:-:-:-:-:-:-:-:-:-:<cpe>
    • 17 |
    18 | Other types are possible, but are not used by the software. 19 | {% endblock %} 20 | 21 | {% block output %} 22 | [ 23 | { 24 | "id": "mediawiki", 25 | "type": "targetsoftware" 26 | }, 27 | { 28 | "id": "cpe:2.3:a:clamav", 29 | "type": "cpe" 30 | }, 31 | { 32 | "id": "cpe:2.3:a:adobe:reader", 33 | "type": "cpe" 34 | } 35 | ] 36 | {% endblock %} 37 | -------------------------------------------------------------------------------- /web/templates/documentation/api/whitelist_add: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set admin = True %} 3 | {% set id = "whitelist_add" %} 4 | {% set title = "/api/admin/whitelist/add" %} 5 | {% set method = "PUT" %} 6 | {% set headers = [('Content-Type', "This field is required to be set to:", "application/x-www-form-urlencoded")]%} 7 | {% set formdata = [('cpe', "CPE code in cpe2.2 or cpe2.3 format", "cpe:2.3:o:gnu:gcc#Comment"), 8 | ('type', "CPE type", "cpe, targetsoftware or targethardware")] %} 9 | 10 | {% block desc %} 11 | Adds a CPE to the whitelist. If the CPE was added to the whitelist, the output will be true. If not, it will be false.
    12 | Comments can be added by appending # 13 | {% endblock %} 14 | 15 | {% block output %} 16 | true 17 | {% endblock %} 18 | -------------------------------------------------------------------------------- /web/templates/documentation/api/whitelist_drop: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set admin = True %} 3 | {% set id = "whiteklist_drop" %} 4 | {% set title = "/api/admin/whitelist/drop" %} 5 | {% set method = "POST" %} 6 | 7 | 8 | {% block desc %} 9 | Drops the content of the whitelist. 10 | {% endblock %} 11 | 12 | {% block output %} 13 | null 14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /web/templates/documentation/api/whitelist_export: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set admin = True %} 3 | {% set id = "whitelist_export" %} 4 | {% set title = "/api/admin/whitelist/export" %} 5 | {% set method = "GET" %} 6 | 7 | 8 | {% block desc %} 9 | See /api/admin/whitelist 10 | {% endblock %} 11 | 12 | {% block output %} 13 | [ 14 | { 15 | "id": "mediawiki", 16 | "type": "targetsoftware" 17 | }, 18 | { 19 | "id": "cpe:2.3:a:clamav", 20 | "type": "cpe" 21 | }, 22 | { 23 | "id": "cpe:2.3:a:adobe:reader", 24 | "type": "cpe" 25 | } 26 | ] 27 | {% endblock %} 28 | -------------------------------------------------------------------------------- /web/templates/documentation/api/whitelist_import: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set admin = True %} 3 | {% set id = "whitelist_import" %} 4 | {% set title = "/api/admin/whitelist/import" %} 5 | {% set method = "PUT" %} 6 | 7 | 8 | {% block desc %} 9 | Imports the whitelist. The whitelist data should be of the same format as the output of 10 | /api/admin/whitelist 11 | and should be put in the request body. 12 | {% endblock %} 13 | 14 | {% block output %} 15 | null 16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /web/templates/documentation/api/whitelist_remove: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/api-accordion-child' %} 2 | {% set admin = True %} 3 | {% set id = "whitelist_remove" %} 4 | {% set title = "/api/admin/whitelist/remove" %} 5 | {% set method = "PUT" %} 6 | {% set headers = [('Content-Type', "This field is required to be set to:", "application/x-www-form-urlencoded")]%} 7 | {% set formdata = [('cpe', "CPE code in cpe2.2 or cpe2.3 format", "cpe:2.3:o:gnu:gcc#Comment")] %} 8 | 9 | {% block desc %} 10 | Remove a CPE from the whitelist. If the CPE was removed from the whitelist, the output will be true. If not, it will be false. 11 | {% endblock %} 12 | 13 | {% block output %} 14 | true 15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /web/templates/documentation/status_codes/authentication_failed: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/status_code_accordion-child' %} 2 | {% set id = "authentication_failed" %} 3 | {% set title = "Authentication Failed" %} 4 | {% set code = 401 %} 5 | {% block desc %} 6 | Authentication failed because the credentials provided were incorrect. 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /web/templates/documentation/status_codes/authentication_needed: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/status_code_accordion-child' %} 2 | {% set id = "authentication_needed" %} 3 | {% set title = "Authentication needed" %} 4 | {% set code = 401 %} 5 | {% block desc %} 6 | This request required authentication. 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /web/templates/documentation/status_codes/authorization_method_not_allowed: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/status_code_accordion-child' %} 2 | {% set id = "authorization_method_not_allowed" %} 3 | {% set title = "Authorization Method Not Allowed" %} 4 | {% set code = 400 %} 5 | {% block desc %} 6 | The specified authentication method (in the Authorization header) is not allowed.
    7 | Allowed authorization methods are: 8 |
      9 |
    • basic (user:password)
    • 10 |
    • token (user:token)
    • 11 |
    • session (user:session_key)
    • 12 |
    13 | {% endblock %} 14 | 15 | 16 | -------------------------------------------------------------------------------- /web/templates/documentation/status_codes/internal_server_error: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/status_code_accordion-child' %} 2 | {% set id = "internal_server_error" %} 3 | {% set title = "Internal Server Error" %} 4 | {% set code = 500 %} 5 | {% block desc %} 6 | These errors get thrown when the server experienced an error it did not expect.
    7 | In case this happens, the server should print the error to the console. 8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /web/templates/documentation/status_codes/limit_must_be_int: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/status_code_accordion-child' %} 2 | {% set id = "limit_must_be_int" %} 3 | {% set title = "'Limit' Must be an Integer" %} 4 | {% set code = 400 %} 5 | {% block desc %} 6 | The limit parameter in your query could not be parsed as an integer. 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /web/templates/documentation/status_codes/malformed_authentication_string: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/status_code_accordion-child' %} 2 | {% set id = "malformed_authentication_string" %} 3 | {% set title = "Malformed Authentication String" %} 4 | {% set code = 400 %} 5 | {% block desc %} 6 | The authentication string provided in the Authorization header could not be parsed correctly.
    7 | Check the "Authentication" section of the documentation. 8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /web/templates/documentation/status_codes/not_found: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/status_code_accordion-child' %} 2 | {% set id = "not_found" %} 3 | {% set title = "Resource Not Found" %} 4 | {% set code = 404 %} 5 | {% block desc %} 6 | The url requested does not exist. You might need to check upper/lowercase, or revert back to the documentation. 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /web/templates/documentation/status_codes/resource_unavailable: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/status_code_accordion-child' %} 2 | {% set id = "resource_unavailable" %} 3 | {% set title = "Server could not connect to the browsing repository" %} 4 | {% set code = 503 %} 5 | {% block desc %} 6 | The browsing repository is currently not available.
    7 | This could be because Redis is not running, the link between CVE-Search and Redis cannot be 8 | established, or other reasons. 9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /web/templates/documentation/status_codes/skip_must_be_int: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/status_code_accordion-child' %} 2 | {% set id = "skip_must_be_int" %} 3 | {% set title = "'Skip' Must be an Integer" %} 4 | {% set code = 400 %} 5 | {% block desc %} 6 | The skip parameter in your query could not be parsed as an integer. 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /web/templates/documentation/status_codes/success: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/status_code_accordion-child' %} 2 | {% set id = "success" %} 3 | {% set title = "Success" %} 4 | {% set code = 200 %} 5 | {% block desc %} 6 | The request was handled correctly. 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /web/templates/documentation/status_codes/unknown_content-type: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/status_code_accordion-child' %} 2 | {% set id = "unknown_content-type" %} 3 | {% set title = "Unknown Content-type Requested" %} 4 | {% set code = 415 %} 5 | {% block desc %} 6 | A content type was requested (in the Accept header) which is not one of the following: 7 |
      8 |
    • json
    • 9 |
    • plain
    • 10 |
    • application/*
    • 11 |
    • text/*
    • 12 |
    • */*
    • 13 |
    14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /web/templates/error.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/master-page' %} 2 | {% block title %}Error{% endblock %} 3 | {% block content %} 4 |
    5 | {% if status['except']=='redis-connection' %} 6 |

    This page can not be displayed due to an error

    7 |

    Unable to connect to Redis. Is it running on {{status['info']['host']}}:{{status['info']['port']}}?

    8 | {% elif status['except']=='cve-not-found' %} 9 |

    This CVE does not exist

    10 |

    {{status['info']['cve']}} could not be found in the CVE-Search database. 11 | This could mean that this CVE is not in the National Vulnerability Database yet, that your database is outdated or that you entered a wrong CVE.

    12 | {% elif status['except']=='textsearch-not-enabled' %} 13 |

    Fulltext search not enabled

    14 |

    The current settings in the database do not allow fulltext search.
    15 | If you feel like this should be enabled, please contact your administrator.

    16 | {% elif status['except']=='plugin-not-loaded' %} 17 |

    Plug-in not loaded

    18 |

    This plug-in is not loaded. You may have spelled the URL wrong, or the plug-in might be missing or not loaded.

    19 | {% elif status['except'] in ['plugin-page-missing', 'plugin-page-corrupt'] %} 20 |

    The plug-in threw an error!

    21 |

    Seems like the plug-in was not developed correctly. Please contact the plug-in developer.

    22 | {% if status['except']=='plugin-page-missing' %}

    Error code 011

    23 | {% elif status['except']=='plugin-page-corrupt' %}

    Error code 012

    24 | {% endif %} 25 | {% elif status['except']=='plugin-page-not-found' %} 26 |

    The plug-in threw an error!

    27 |

    The plug-in could not find the page it was looking for ({{status['page']}}).

    28 |

    Please check if you installed this page correctly. If the error is not at your side, but the developer, please contact them.

    29 |

    Error code 013

    30 | {% elif status['except']=='plugin-not-webplugin' %} 31 |

    Plug-in not a webplugin

    32 |

    This plug-in is not a web plug-in, and has no page to display.

    33 | {% endif %} 34 |
    35 | {% endblock %} 36 | -------------------------------------------------------------------------------- /web/templates/index-minimal.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/master-page' %} 2 | {% block title %}Most recent entries{% endblock %} 3 | {% block head %} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 25 | {% endblock %} 26 | {% block content %} 27 | 28 | {% include 'subpages/filters.html' %} 29 | 30 | {% include 'subpages/pager.html' %} 31 | 32 | {% include 'subpages/table.html' %} 33 | 34 | {% include 'subpages/pager.html' %} 35 | 36 | {% endblock %} 37 | -------------------------------------------------------------------------------- /web/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/master-page' %} 2 | {% block title %}Most recent entries{% endblock %} 3 | {% block head %} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 32 | {% endblock %} 33 | {% block content %} 34 | 35 | {% include 'subpages/filters.html' %} 36 | 37 | {% include 'subpages/pager.html' %} 38 | 39 | {% include 'subpages/table.html' %} 40 | 41 | {% include 'subpages/pager.html' %} 42 | 43 | {% endblock %} 44 | -------------------------------------------------------------------------------- /web/templates/layouts/api-accordion-child: -------------------------------------------------------------------------------- 1 |
    2 | 7 |
    8 |
    9 |
    10 |
    11 |

    Description

    12 | {% block desc %} {% endblock %} 13 |
    14 |
    15 | {% if args is defined or formdata is defined or headers is defined %} 16 |
    17 |
    18 | {% if args is defined %} 19 |
    URL arguments
    20 | 21 | 22 | 23 | 24 | 25 | {% for arg in args %} 26 | 27 | {% endfor %} 28 | 29 |
    Argument Description Example
    {{arg[0]}} {{arg[1]}} {{arg[2]}}
    30 | {% endif %} 31 | {% if headers is defined %} 32 |
    Headers
    33 | 34 | 35 | 36 | 37 | 38 | {% for arg in headers %} 39 | 40 | {% endfor %} 41 | 42 |
    Argument Description Example
    {{arg[0]}} {{arg[1]}} {{arg[2]}}
    43 | {% endif %} 44 | {% if formdata is defined %} 45 |
    Formdata arguments
    46 | 47 | 48 | 49 | 50 | 51 | {% for arg in formdata %} 52 | 53 | {% endfor %} 54 | 55 |
    Argument Description Example
    {{arg[0]}} {{arg[1]}} {{arg[2]}}
    56 | {% endif %} 57 |
    58 |
    59 | {% endif %} 60 |
    61 |
    62 |

    Output

    63 |
    {% block output %}{% endblock %}
    64 |
    65 |
    66 |
    67 |
    68 |
    69 | -------------------------------------------------------------------------------- /web/templates/layouts/master-page: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | {% if not minimal %} 14 | 15 | {% endif %} 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 28 | 29 | {% if not minimal %} 30 | 31 | 32 | {% endif %} 33 | 34 | {% block title %}{% endblock %} - CVE-Search 35 | {% block head %}{% endblock %} 36 | 37 | 38 |
    39 |
    40 |
    41 | 42 | {% if minimal %} 43 | {% include 'subpages/menu-minimal.html' %} 44 | {% else %} 45 | {% include 'subpages/menu.html' %} 46 | {% endif %} 47 | 48 | 49 | {% if not minimal %} 50 | 58 | {% endif %} 59 | 60 | 61 |
    62 | 63 | 64 |
    65 | {% block content %}{% endblock %} 66 |
    67 | Back to Top 68 | 69 |
    70 |
    71 |
    72 | 73 | 74 | -------------------------------------------------------------------------------- /web/templates/layouts/status_code_accordion-child: -------------------------------------------------------------------------------- 1 |
    2 | 7 |
    8 |
    9 |
    10 |
    11 |

    Description

    12 | {% block desc %} {% endblock %} 13 |
    14 |
    15 |
    16 |
    17 |
    18 | -------------------------------------------------------------------------------- /web/templates/linked.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/master-page' %} 2 | {% block title %}CVE's linked by {{field}}{% endblock %} 3 | {% block head %} 4 | 5 | 6 | {% endblock %} 7 | {% block content %} 8 | 9 | 13 | 14 | 15 | 16 | 17 |
    Max CVSS {{stats['maxCVSS']}}Min CVSS {{stats['minCVSS']}}Total Count{{stats['count']}}
    18 | {% include 'subpages/table.html' %} 19 | {% endblock %} 20 | -------------------------------------------------------------------------------- /web/templates/list.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/master-page' %} 2 | {% block title %}{{ listType }} management{% endblock %} 3 | {% block head %} 4 | 5 | {% endblock %} 6 | {% block content %} 7 | 8 | 9 | 10 | 14 | 15 | 16 | 20 | 21 |
    22 |
    23 | 29 | Browse... 30 | 31 |

    or

    32 |
    33 | 45 |
    46 |
    47 | 48 | {% set rulesList = rules|list %} 49 | 50 | 51 | 77 | 110 | 111 |
    52 | CPE Rules 53 | 54 | 55 | 56 | {% for ruleID in rulesList if ruleID['type']=='cpe' %} 57 | 58 | 59 | {% if ruleID['comments'] is defined %} 60 | 61 | {% else %} 62 | 63 | {% endif %} 64 | 65 | 72 | 73 | {% endfor %} 74 | 75 |
    RuleComments
    {{ ruleID['id'] }} 66 |
      67 | {% for comment in ruleID['comments'] %} 68 |
    • {{ comment }}
    • 69 | {% endfor %} 70 |
    71 |
    76 |
    78 | Keywords 79 | 80 | 81 | 82 | {% for ruleID in rulesList if ruleID['type']!='cpe' %} 83 | 84 | 85 | {% if ruleID['comments'] is defined %} 86 | 87 | {% else %} 88 | 89 | {% endif %} 90 | 91 | 98 | 105 | 106 | {% endfor %} 107 | 108 |
    RuleKeywordComments
    {{ ruleID['id'] }} 92 | {% if ruleID['type'] == 'targethardware' %} 93 | Target Hardware 94 | {% elif ruleID['type'] == 'targetsoftware' %} 95 | Target Software 96 | {% endif %} 97 | 99 |
      100 | {% for comment in ruleID['comments'] %} 101 |
    • {{ comment }}
    • 102 | {% endfor %} 103 |
    104 |
    109 |
    112 | {% endblock %} 113 | -------------------------------------------------------------------------------- /web/templates/listmanagement.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/master-page' %} 2 | {% block title %}CPE browser{% endblock %} 3 | {% block head %} 4 | 5 | 6 | {% endblock %} 7 | {% block content %} 8 | 9 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 40 | 41 | 42 | 43 | {% if version != None %} 44 | {% for v in version %} 45 | 46 | 47 | 48 | 49 | 50 | 51 | {% endfor %} 52 | {% elif product != None %} 53 | {% for p in product %} 54 | 55 | 56 | 57 | 58 | 59 | {% endfor %} 60 | {% else %} 61 | {% for v in vendor %} 62 | 63 | 64 | 65 | 66 | 67 | {% endfor %} 68 | {% endif %} 69 | 70 |
    32 | {% if version != None%} 33 | Versions for {{ vendor }} {{ product|htmlDecode }} 34 | {% elif product != None %} 35 | Products for {{ vendor|htmlDecode }} 36 | {% elif product == None %} 37 | Vendors 38 | {% endif %} 39 |
    {{ product|htmlDecode }} {{ v|htmlDecode }} whitelist blacklist
    {{ p|htmlDecode }} whitelist blacklist
    {{ v|htmlDecode }} whitelist blacklist
    71 | {% endblock %} 72 | -------------------------------------------------------------------------------- /web/templates/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/master-page' %} 2 | {% block title %}Login page{% endblock %} 3 | {% block head %} 4 | 7 | {% endblock %} 8 | {% block content %} 9 |
    10 | 24 |
    25 | {% endblock %} 26 | -------------------------------------------------------------------------------- /web/templates/requiresAuth.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/master-page' %} 2 | {% block title %}Authentication Required{% endblock %} 3 | 4 | {% block content %} 5 |
    6 |

    Requires Authentication

    7 |

    You need to authenticate to access this.

    8 |
    9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /web/templates/search.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/master-page' %} 2 | {% block title %}Vendor browsing{% endblock %} 3 | {% block content %} 4 | 5 | {% if vendor %} 6 | 11 | {% endif %} 12 | {% if errors %} 13 |
    14 |

    While searching, the following error(s) occurred:

    15 | {% if 'textsearch' in errors%} 16 | Fulltext search not enabled 17 |

    The current settings in the database do not allow fulltext search.
    18 | If you feel like this should be enabled, please contact your administrator.

    19 | {% endif %} 20 |
    21 | {% endif %} 22 | {% include 'subpages/table.html' %} 23 | {% if not vendor and cve|length == 100 %} 24 |

    Top 100 results

    25 | {% endif %} 26 | {% endblock %} 27 | -------------------------------------------------------------------------------- /web/templates/subpages/filters.html: -------------------------------------------------------------------------------- 1 | 4 | 5 |
    6 | 95 |
    96 | -------------------------------------------------------------------------------- /web/templates/subpages/menu-minimal.html: -------------------------------------------------------------------------------- 1 | 2 | 27 | 28 | -------------------------------------------------------------------------------- /web/templates/subpages/menu.html: -------------------------------------------------------------------------------- 1 | 2 | 30 | 31 | -------------------------------------------------------------------------------- /web/templates/subpages/pager.html: -------------------------------------------------------------------------------- 1 | 5 | {% set length = 5%} 6 | 7 | 8 | {% set page = (r/pageLength)|int %} 9 | {% set middle = (length/2)|int+1 %} 10 | {% if page < middle %} 11 | {% set pre = page %} 12 | {% set post = length-page%} 13 | {% else %} 14 | {% set pre = middle-1 %} 15 | {% set post = middle%} 16 | {% endif %} 17 | 18 |
    19 | 42 |
    43 | -------------------------------------------------------------------------------- /web/templates/subpages/table.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {% for c in cve %} 9 | {% if 'whitelisted' in c %}{%set class="whitelisted"%}{% elif 'blacklisted' in c %}{%set class="blacklisted"%} 10 | {% else %}{%set class=""%}{% endif %} 11 | 12 | 23 | 29 | 32 | 37 | 40 | 43 | 44 | {% endfor %} 45 | 46 |
    IDCVSSSummaryLast (major) updatePublished
    13 | {% if 'icon' in c %} 14 | 15 | {% else %} 16 | {% if 'whitelisted' in c %} 17 | 18 | {% elif 'blacklisted' in c %} 19 | 20 | {% endif %} 21 | {% endif %} 22 | 24 | {{ c['id'] }} 25 | {% if 'reason' in c %} 26 |
    {{c['reason']}} 27 | {% endif %} 28 |
    30 | {{ c['cvss'] }} 31 | 33 |
    34 | {{ c['summary'][:250] }} 35 |
    36 |
    38 | {{ c['Modified'].strftime('%d-%m-%Y - %H:%M') }} 39 | 41 | {{ c['Published'].strftime('%d-%m-%Y - %H:%M') }} 42 |
    47 | Back to Top 48 | Mark selected 49 | --------------------------------------------------------------------------------