")
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 |
Collection
Source
Description
22 |
23 |
cves
NVD NIST
All the official vulnerabilities, released by NIST. Items in this collection have all info related to each CVE
24 |
cpe
NVD NIST
All the official products, released by NIST. Some of these have a human readable title.
25 |
cpeother
CVE-Search
CVE-Search has a script to fill this database, using the original CPE's and generating titles for them.
26 |
cwe
NVD NIST
Information about Common Weaknesses, as published by NIST
27 |
d2sec
d2sec.com
Information about CVE's, as released by d2sec
28 |
vendor
NVD NIST
Vendor statements, released by NIST
29 |
info
CVE-Search
Information about the Mongo Database updates.
30 |
31 |
32 | These are the management collections:
33 |
34 |
35 |
Collection
Description
36 |
37 |
ranking
Self-set ranking for specific CPE's that are more important to specific groups
38 |
mgmt_blacklist
List of CPE's that have to be excluded from the web view. More about this here
39 |
mgmt_whitelist
List of CPE's that have to be marked in the web view. More about this here
40 |
mgmt_users
List of users who have access to the administrative panel. More about this here
41 |
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("
", "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.
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 |
{{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.
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 |
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 |
23 |
24 | {{ c['id'] }}
25 | {% if 'reason' in c %}
26 | {{c['reason']}}
27 | {% endif %}
28 |