from lib.Toolkit import toStringFormattedCPE, toOldCPE, currentTime, isURL, vFeedName, convertDateToDBFormat import lib.CVEs as cves import lib.DatabaseLayer as dbLayer from sbin.db_whitelist import * from sbin.db_blacklist import * # parse command line arguments argparser = argparse.ArgumentParser(description='Start CVE-Search web component') argparser.add_argument('-v', action='store_true', help='verbose output') args = argparser.parse_args() # variables app = Flask(__name__, static_folder='static', static_url_path='/static') app.config['MONGO_DBNAME'] = Configuration.getMongoDB() app.config['SECRET_KEY'] = str(random.getrandbits(256)) pageLength = Configuration.getPageLength() # login manager login_manager = LoginManager() login_manager.init_app(app) # db connectors redisdb = Configuration.getRedisVendorConnection() # functions def getBrowseList(vendor): result = {} if (vendor is None) or type(vendor) == list: v1 = redisdb.smembers("t:/o") v2 = redisdb.smembers("t:/a") v3 = redisdb.smembers("t:/h") vendor = sorted(list(set(list(v1) + list(v2) + list(v3))))
class Minimal(API): ############# # Variables # ############# defaultFilters = { 'timeSelect': 'all', 'startDate': '', 'endDate': '', 'timeTypeSelect': 'Modified', 'cvssSelect': 'all', 'cvss': '', 'rejectedSelect': 'hide' } args = { 'pageLength': Configuration.getPageLength(), 'listLogin': Configuration.listLoginRequired(), 'minimal': True } def __init__(self): self.minimal = True super().__init__() routes = [{ 'r': '/', 'm': ['GET'], 'f': self.index }, { 'r': '/', 'm': ['POST'], 'f': self.index_post }, { 'r': '/r/<int:r>', 'm': ['GET'], 'f': self.index_filter_get }, { 'r': '/r/<int:r>', 'm': ['POST'], 'f': self.index_filter_post }, { 'r': '/cve/<cveid>', 'm': ['GET'], 'f': self.cve }, { 'r': '/cwe', 'm': ['GET'], 'f': self.cwe }, { 'r': '/cwe/<cweid>', 'm': ['GET'], 'f': self.relatedCWE }, { 'r': '/capec/<capecid>', 'm': ['GET'], 'f': self.capec }, { 'r': '/browse', 'm': ['GET'], 'f': self.browse }, { 'r': '/browse/', 'm': ['GET'], 'f': self.browse }, { 'r': '/browse/<vendor>', 'm': ['GET'], 'f': self.browse }, { 'r': '/search/<vendor>/<path:product>', 'm': ['GET'], 'f': self.search }, { 'r': '/search', 'm': ['POST'], 'f': self.freetext_search }, { 'r': '/link/<key>/<value>', 'm': ['GET'], 'f': self.link }] filters = [{ 'n': 'htmlEncode', 'f': self.htmlEncode }, { 'n': 'htmlDecode', 'f': self.htmlDecode }, { 'n': 'sortIntLikeStr', 'f': self.sortIntLikeStr }] context_processors = [self.JSON2HTMLTable] error_handlers = [{'e': 404, 'f': self.page_not_found}] for route in routes: self.addRoute(route) for _filter in filters: self.addFilter(_filter) for context in context_processors: self.addContextProcessors(context) for handler in error_handlers: self.app.register_error_handler(handler['e'], handler['f']) ############# # Functions # ############# def addFilter(self, _filter): self.app.add_template_filter(_filter['f'], _filter['n']) def addContextProcessors(self, context_processor): self.app.context_processor(context_processor) def generate_minimal_query(self, f): query = [] # retrieving lists if f['rejectedSelect'] == "hide": exp = "^(?!\*\* REJECT \*\*\s+DO NOT USE THIS CANDIDATE NUMBER.*)" query.append({'summary': re.compile(exp)}) # cvss logic if f['cvssSelect'] == "above": query.append({'cvss': {'$gt': float(f['cvss'])}}) elif f['cvssSelect'] == "equals": query.append({'cvss': float(f['cvss'])}) elif f['cvssSelect'] == "below": query.append({'cvss': {'$lt': float(f['cvss'])}}) # date logic if f['timeSelect'] != "all": if f['startDate']: startDate = parse_datetime(f['startDate'], ignoretz=True, dayfirst=True) if f['endDate']: endDate = parse_datetime(f['endDate'], ignoretz=True, dayfirst=True) if f['timeSelect'] == "from": query.append({f['timeTypeSelect']: {'$gt': startDate}}) elif f['timeSelect'] == "until": query.append({f['timeTypeSelect']: {'$lt': endDate}}) elif f['timeSelect'] == "between": query.append( {f['timeTypeSelect']: { '$gt': startDate, '$lt': endDate }}) elif f['timeSelect'] == "outside": query.append({ '$or': [{ f['timeTypeSelect']: { '$lt': startDate } }, { f['timeTypeSelect']: { '$gt': endDate } }] }) return query def filter_logic(self, filters, skip): query = self.generate_minimal_query(filters) limit = self.args['pageLength'] return db.getCVEs(limit=limit, skip=skip, query=query) def getFilterSettingsFromPost(self, r): filters = dict(request.form) filters = {x: filters[x][0] for x in filters.keys()} errors = False # retrieving data try: cve = self.filter_logic(filters, r) except Exception as e: print(e) cve = db.getCVEs(limit=self.args['pageLength'], skip=r) errors = True return {'filters': filters, 'cve': cve, 'errors': errors} return (filters, cve, errors) ########## # ROUTES # ########## # / def index(self): cve = self.filter_logic(self.defaultFilters, 0) return render_template('index.html', cve=cve, r=0, **self.args) # / def index_post(self): args = dict(self.getFilterSettingsFromPost(0), **self.args) return render_template('index.html', r=0, **args) # /r/<r> def index_filter_get(self, r): if not r or r < 0: r = 0 cve = self.filter_logic(self.defaultFilters, r) return render_template('index.html', cve=cve, r=r, **self.args) # /r/<r> def index_filter_post(self, r): if not r or r < 0: r = 0 args = dict(self.getFilterSettingsFromPost(r), **self.args) return render_template('index.html', r=r, **args) # /cve/<cveid> def cve(self, cveid): cveid = cveid.upper() cvesp = cves.last(rankinglookup=True, namelookup=True, via4lookup=True, capeclookup=True, subscorelookup=True) cve = cvesp.getcve(cveid=cveid) if cve is None: return render_template('error.html', status={ 'except': 'cve-not-found', 'info': { 'cve': cveid } }, minimal=self.minimal) return render_template('cve.html', cve=cve, minimal=self.minimal) # /cwe def cwe(self): cwes = [x for x in db.getCWEs() if x["weaknessabs"].lower() == "class"] return render_template('cwe.html', cwes=cwes, capec=None, minimal=self.minimal) # /cwe/<cweid> def relatedCWE(self, cweid): cwes = {x["id"]: x["name"] for x in db.getCWEs()} return render_template('cwe.html', cwes=cwes, cwe=cweid, capec=db.getCAPECFor(cweid), minimal=self.minimal) # /capec/<capecid> def capec(self, capecid): cwes = {x["id"]: x["name"] for x in db.getCWEs()} return render_template('capec.html', cwes=cwes, capec=db.getCAPEC(capecid), minimal=self.minimal) # /browse # /browse/ # /browse/<vendor> def browse(self, vendor=None): try: if vendor is not None: vendor = urllib.parse.quote_plus(vendor).lower() browseList = query.getBrowseList(vendor) vendor = browseList["vendor"] product = browseList["product"] return render_template('browse.html', product=product, vendor=vendor, minimal=self.minimal) except redisExceptions.ConnectionError: return render_template('error.html', minimal=self.minimal, status={ 'except': 'redis-connection', 'info': { 'host': Configuration.getRedisHost(), 'port': Configuration.getRedisPort() } }) # /search/<vendor>/<product> def search(self, vendor=None, product=None): search = vendor + ":" + product cve = db.cvesForCPE(search) return render_template('search.html', vendor=vendor, product=product, cve=cve, minimal=self.minimal) # /search def freetext_search(self): search = request.form.get('search') result = db.getSearchResults(search) cve = result['data'] errors = result['errors'] if 'errors' in result else [] return render_template('search.html', cve=cve, errors=errors, minimal=self.minimal) # /link/<key>/<value> def link(self, key=None, value=None): key = self.htmlDecode(key) value = self.htmlDecode(value) regex = re.compile(re.escape(value), re.I) cve = db.via4Linked(key, regex) cvssList = [float(x['cvss']) for x in cve if 'cvss' in x] if cvssList: stats = { 'maxCVSS': max(cvssList), 'minCVSS': min(cvssList), 'count': len(cve) } else: stats = {'maxCVSS': 0, 'minCVSS': 0, 'count': len(cve)} return render_template('linked.html', via4map=key.split(".")[0], field='.'.join(key.split(".")[1:]), value=value, cve=cve, stats=stats, minimal=self.minimal) ########### # Filters # ########### def htmlEncode(self, string): return urllib.parse.quote_plus(string).lower() def htmlDecode(self, string): return urllib.parse.unquote_plus(string) def sortIntLikeStr(self, datalist): return sorted(datalist, key=lambda k: int(k)) def JSON2HTMLTable(self): # Doublequote, because we have to |safe the content for the tags def doublequote(data): return urllib.parse.quote_plus(urllib.parse.quote_plus(data)) def JSON2HTMLTableFilter(data, stack=None): _return = "" if type(stack) == str: stack = [stack] if type(data) == list: if len(data) == 1: _return += JSON2HTMLTableFilter(data[0], stack) else: _return += '<ul class="via4">' for item in data: _return += ('<li>%s</li>' % JSON2HTMLTableFilter(item, stack)) _return += '</ul>' elif type(data) == dict: _return += '<table class="invisiTable">' for key, val in sorted(data.items()): _return += '<tr><td><b>%s</b></td><td>%s</td></tr>' % ( key, JSON2HTMLTableFilter(val, stack + [key])) _return += '</table>' elif type(data) == str: if stack: _return += "<a href='/link/" + doublequote('.'.join( stack)) + "/" + doublequote(data) + "'>" #link opening _return += "<span class='glyphicon glyphicon-link' aria-hidden='true'></span> </a>" _return += "<a target='_blank' href='%s'>%s</a>" % ( data, data) if tk.isURL(data) else data _return += "" return _return return dict(JSON2HTMLTable=JSON2HTMLTableFilter) ################## # Error Messages # ################## def page_not_found(self, e): return render_template('404.html', minimal=self.minimal), 404
class Minimal(API): ############# # Variables # ############# defaultFilters = { 'timeSelect': 'all', 'startDate': '', 'endDate': '', 'timeTypeSelect': 'Modified', 'cvssSelect': 'all', 'cvss': '', 'rejectedSelect': 'hide' } args = { 'pageLength': Configuration.getPageLength(), 'listLogin': Configuration.listLoginRequired(), 'minimal': True } def __init__(self): self.minimal = True super().__init__() routes = [{ 'r': '/', 'm': ['GET'], 'f': self.index }, { 'r': '/', 'm': ['POST'], 'f': self.index_post }, { 'r': '/r/<int:r>', 'm': ['GET'], 'f': self.index_filter_get }, { 'r': '/r/<int:r>', 'm': ['POST'], 'f': self.index_filter_post }, { 'r': '/cve/<cveid>', 'm': ['GET'], 'f': self.cve }, { 'r': '/cwe', 'm': ['GET'], 'f': self.cwe }, { 'r': '/cwe/<cweid>', 'm': ['GET'], 'f': self.relatedCWE }, { 'r': '/capec/<capecid>', 'm': ['GET'], 'f': self.capec }, { 'r': '/browse', 'm': ['GET'], 'f': self.browse }, { 'r': '/browse/', 'm': ['GET'], 'f': self.browse }, { 'r': '/browse/<vendor>', 'm': ['GET'], 'f': self.browse }, { 'r': '/search/<vendor>/<path:product>', 'm': ['GET'], 'f': self.search }, { 'r': '/search', 'm': ['POST'], 'f': self.freetext_search }, { 'r': '/link/<key>/<value>', 'm': ['GET'], 'f': self.link }, { 'r': '/privacy_info', 'm': ['GET'], 'f': self.generate_privacy_info }, { 'r': '/subscription', 'm': ['GET'], 'f': self.generate_subscription_form }, { 'r': '/subscribe', 'm': ['POST'], 'f': self.save_user_subscription }, { 'r': '/send-subscription-report/<email>', 'm': ['GET'], 'f': self.send_subscription_report }, { 'r': '/check_subscription_email/<email>', 'm': ['GET'], 'f': self.check_subscription_email }, { 'r': '/unsubscribe/<email>', 'm': ['GET'], 'f': self.unsubscribe }, { 'r': '/activate', 'm': ['GET'], 'f': self.activate_user }, { 'r': '/deactivate', 'm': ['GET'], 'f': self.deactivate_user }] filters = [{ 'n': 'htmlEncode', 'f': self.htmlEncode }, { 'n': 'htmlDecode', 'f': self.htmlDecode }, { 'n': 'sortIntLikeStr', 'f': self.sortIntLikeStr }] context_processors = [self.JSON2HTMLTable] error_handlers = [{'e': 404, 'f': self.page_not_found}] for route in routes: self.addRoute(route) for _filter in filters: self.addFilter(_filter) for context in context_processors: self.addContextProcessors(context) for handler in error_handlers: self.app.register_error_handler(handler['e'], handler['f']) ############# # Functions # ############# # def body_from_template2(self,template_file, urls, token, today): # templateLoader = jinja2.FileSystemLoader( searchpath=TEMPLATE_DIR ) # templateEnv = jinja2.Environment( loader=templateLoader ) # template = templateEnv.get_template( template_file ) # return template.render( urls = urls, token=token, today=today) # def send_report2(self,MAIL_LIST,urls,token,template_file,subject): # body = self.body_from_template2(template_file,urls,token,today) # msg = MIMEText(body,"html")# # msg.add_header('Content-Type','text/html') # msg['Subject'] = subject # msg['From'] = FROM # msg['To'] = MAIL_LIST # s = smtplib.SMTP('localhost') # s.sendmail(FROM, MAIL_LIST, msg.as_string()) # s.quit # def sendSubConfLink(self, mail, token): # self.send_report(mail,None,token,"ncert_conf_mail.html","NCERT - mail potvrde") # def activate_user(self,token): # if token == status['token'] and status['status'] == False: # update_status(token) # status=user_status(token) # subscription_form = form_class.SubscriptionForm() # return render_template('activation.html',form=subscription_form, message=status, r=0, **self.args) def addFilter(self, _filter): self.app.add_template_filter(_filter['f'], _filter['n']) def addContextProcessors(self, context_processor): self.app.context_processor(context_processor) def getFilterSettingsFromPost(self, r): filters = dict(request.form) filters = {x: filters[x][0] for x in filters.keys()} errors = False # retrieving data try: cve = self.filter_logic(filters, r) except Exception as e: cve = db.getCVEs(limit=self.args['pageLength'], skip=r) errors = True return {'filters': filters, 'cve': cve, 'errors': errors} return (filters, cve, errors) def body_from_template(self, template_file, data, today): templateLoader = jinja2.FileSystemLoader(searchpath=TEMPLATE_DIR) templateEnv = jinja2.Environment(loader=templateLoader) template = templateEnv.get_template(template_file) #ubacujemo adresu u e_mail za potvrdu pretplate i odjavu config_test = Configuration() host_test = "https://" + config_test.default["flaskHost"] + "/activate?" host_test_deactivate = "https://" + config_test.default[ "flaskHost"] + "/deactivate?" return template.render(data=data, today=today, host_test=host_test, host_test_deactivate=host_test_deactivate) def send_report(self, MAIL_LIST, data, template_file, subject): body = self.body_from_template(template_file, data, today) msg = MIMEText(body, "html") # msg.add_header('Content-Type', 'text/html') msg['Subject'] = subject msg['From'] = FROM msg['To'] = MAIL_LIST s = smtplib.SMTP('localhost') s.sendmail(FROM, MAIL_LIST, msg.as_string()) s.quit def popispretplata(self, mail): inform = ncert_db.getInfo(mail) v = [] p = [] c = [] for i in inform["choice"]: v.append(i["vendor"]) p.append(i["product"]) c.append(i["cvss"]) rez = zip(v, p, c) return (rez) def sendPopisPretplata(self, email): self.send_report(email, {"list": self.popispretplata(email)}, "ncert_popis_template.html", "NCERT - popis pretplata") def send_sub_conf_link(self, data): self.send_report(data["email"], { "id": data["id"], "token": data["token"] }, "ncert_sub_conf_mail.html", "NCERT - mail potvrde prijave na liste") def send_unsub_conf_link(self, data): self.send_report(data["email"], { "id": data["id"], "token": data["token"] }, "ncert_unsub_conf_mail.html", "NCERT - mail potvrde odjave sa lista") def confirm_param(self, param, expiration=86400): serializer = URLSafeTimedSerializer(Configuration.getSecretKey()) param = serializer.loads(param, salt=Configuration.getSecurityPasswordSalt(), max_age=expiration) return param def activate_user(self): message = None token = None try: email = self.confirm_param(request.args.get('id')) except: message = 'Link za potvrdu preplata je neispravan ili je istekao.' try: token = self.confirm_param(request.args.get('token')) except: message = 'Link za potvrdu preplata je neispravan ili je istekao.' result = user_data(token) # message = result for idx, value in enumerate(result): if value["choice"]["activated"] == "true": message = 'Već ste se preplatili na selektiranu listu ranjivosti.' token = None else: update_data(token, value["choice"]["vendor"], value["choice"]["product"]) message = 'Uspješno ste se preplatili na selektiranu listu ranjivosti!' #data=user_data(token) # #upit vraca sve zapise ne samo za taj token, nadodati vendor i product #ovaj gornji dohvat treba biti promijenjen u slucaju da stavljamo vise pretplata odjednom #if za slucaj kad je vise i kad je 1 # # for d in data: # subscription_form = form_class.SubscriptionForm() # return render_template('activate.html',form=subscription_form, message=data, r=data, **self.args) #if token == data['choice'][0]['token'] and data['choice'][0]['activated'] == 'false': # update_data(token) # #update radi za svaki zapis pojedinacno #treba prilagoditi za multi ili staviti u for petlju #message="Uspješno ste se pretplatili na listu ranjivosti:" subscription_form = form_class.SubscriptionForm() return render_template('activate.html', form=subscription_form, message=message, r=None, **self.args) def deactivate_user(self): message = None token = None try: email = self.confirm_param(request.args.get('id')) except: message = 'Link za odjavu sa preplata je neispravan ili je istekao.' try: token = self.confirm_param(request.args.get('token')) except: message = 'Link za odjavu za preplata je neispravan ili je istekao.' result = get_unsub_choice_list(token) message = result if not result: message = 'Već ste se odjavili sa odabranih lista ili ste odabrali kombinaciju proizvođača i proizvoda na koje niste preplaćeni!' else: for idx, value in enumerate(result): remove_choice(email, value["choice"]["vendor"], value["choice"]["product"]) message = 'Uspješno ste se odjavili sa selektirane liste ranjivosti!' subscription_form = form_class.SubscriptionForm() return render_template('deactivate.html', form=subscription_form, message=message, r=None, **self.args) ########## # ROUTES # ########## # / def index(self): cve = self.filter_logic(self.defaultFilters, 0) message = None return render_template('index.html', cve=cve, message=message, r=0, **self.args) # / def index_post(self): args = dict(self.getFilterSettingsFromPost(0), **self.args) message = None return render_template('index.html', message=message, r=0, **args) # /r/<r> def index_filter_get(self, r): if not r or r < 0: r = 0 cve = self.filter_logic(self.defaultFilters, r) message = None return render_template('index.html', cve=cve, message=message, r=r, **self.args) # /r/<r> def index_filter_post(self, r): if not r or r < 0: r = 0 args = dict(self.getFilterSettingsFromPost(r), **self.args) message = None return render_template('index.html', message=message, r=r, **args) # /cve/<cveid> def cve(self, cveid): cve = self.api_cve(cveid) if not cve: return render_template('error.html', status={ 'except': 'cve-not-found', 'info': { 'cve': cveid } }, minimal=self.minimal) return render_template('cve.html', cve=cve, minimal=self.minimal) # /cwe def cwe(self): cwes = [ x for x in self.api_cwe() if x["weaknessabs"].lower() == "class" ] return render_template('cwe.html', cwes=cwes, capec=None, minimal=self.minimal) # /cwe/<cweid> def relatedCWE(self, cweid): cwes = {x["id"]: x["name"] for x in self.api_cwe()} return render_template('cwe.html', cwes=cwes, cwe=cweid, capec=db.getCAPECFor(cweid), minimal=self.minimal) # /capec/<capecid> def capec(self, capecid): cwes = {x["id"]: x["name"] for x in self.api_cwe()} return render_template('capec.html', cwes=cwes, capec=db.getCAPEC(capecid), minimal=self.minimal) # /browse # /browse/ # /browse/<vendor> def browse(self, vendor=None): try: data = self.api_browse(vendor) if 'product' in data and 'vendor' in data: return render_template('browse.html', product=data["product"], vendor=data["vendor"], minimal=self.minimal) else: return render_template('error.html', minimal=self.minimal, status={ 'except': 'browse_exception', 'info': 'No CPE' }) except APIError as e: return render_template('error.html', minimal=self.minimal, status={ 'except': 'browse_exception', 'info': e.message }) # /search/<vendor>/<product> def search(self, vendor=None, product=None): search = vendor + ":" + product cve = db.cvesForCPE(search) return render_template('search.html', vendor=vendor, product=product, cve=cve, minimal=self.minimal) # /search def freetext_search(self): search = request.form.get('search') if search == '': return self.index() result = db.getSearchResults(search) cve = {'results': result['data'], 'total': len(result['data'])} errors = result['errors'] if 'errors' in result else [] return render_template('search.html', cve=cve, errors=errors, freetextsearch=search, minimal=self.minimal) # /link/<key>/<value> def link(self, key=None, value=None): key = self.htmlDecode(key) value = self.htmlDecode(value) regex = re.compile(re.escape(value), re.I) cve = db.via4Linked(key, regex) cvssList = [float(x['cvss']) for x in cve['results'] if x.get('cvss')] if cvssList: stats = { 'maxCVSS': max(cvssList), 'minCVSS': min(cvssList), 'count': len(cve) } else: stats = {'maxCVSS': 0, 'minCVSS': 0, 'count': len(cve)} return render_template('linked.html', via4map=key.split(".")[0], field='.'.join(key.split(".")[1:]), value=value, cve=cve, stats=stats, minimal=self.minimal) # /subscription def generate_privacy_info(self): #search = request.form.get('search') #result = db.getSearchResults(search) #cve=result['data'] #errors=result['errors'] if 'errors' in result else [] message = None return render_template('privacy_info.html', subscription_data=request, message=message, minimal=self.minimal) # /subscription def generate_subscription_form(self): #search = request.form.get('search') #result = db.getSearchResults(search) #cve=result['data'] #errors=result['errors'] if 'errors' in result else [] message = None subscription_form = form_class.SubscriptionForm() return render_template('subscription.html', form=subscription_form, subscription_data=request, message=message, minimal=self.minimal) def my_random_string(self, string_length=10): """Returns a random string of length string_length.""" random = str(uuid.uuid4()) # Convert UUID format to a Python string. random = random.upper() # Make all characters uppercase. random = random.replace("-", "") # Remove the UUID '-'. return random[0:string_length] # Return the random string. def generate_confirmation_param(self, param): serializer = URLSafeTimedSerializer(Configuration.getSecretKey()) return serializer.dumps(param, salt=Configuration.getSecurityPasswordSalt()) def setupUnconfirmToken( self, mail, vendor, product, unconfirm_token): #update verztije po vendoru, productu collection.update( { 'mail': mail, "choice": { "$elemMatch": { "vendor": vendor, "product": product } } }, {"$set": { "choice.$.unconfirm_token": unconfirm_token }}) def save_user_subscription(self): data = request.form.to_dict() subscription_form = form_class.SubscriptionForm() # token = uuid.uuid4() # token = str(random.randrange(50)) token = self.my_random_string(40) data.update({'token': token}) data.update({'activated': 'false'}) # #prosiriti sa datumom unosa kako bi znali obrisati zapise koji nemaju status true unutar 20h # # return render_template('subscription.html',form=subscription_form, message=data, r=0, **self.args) if data["email"] == "": error = "Molimo unesite e-mail adresu." return render_template('subscription.html', form=subscription_form, message=error, r=0, **self.args) if not re.match(r"^[\w\.\+\-]+\@[\w]+\.[a-z]{2,10}$", data["email"]): error = "Neispravan format e-mail adrese." return render_template('subscription.html', form=subscription_form, message=error, r=0, **self.args) #return data for i in range(0, int(data["vendor-product-number"])): if data["vpc-" + str(i) + "-vendorField"] not in redis_query.vendors(): error = "Uneseni proizvođač ne postoji." return render_template('subscription.html', form=subscription_form, message=redis_query.vendors(), r=0, **self.args) if data["vpc-" + str(i) + "-productField"] != "": if data["vpc-" + str(i) + "-productField"] not in redis_query.vendor_products( data["vpc-" + str(i) + "-vendorField"]): error = "Proizvod " + data[ "vpc-" + str(i) + "-productField"] + " ne odgovara proizvođaču " + data[ "vpc-" + str(i) + "-vendorField"] + "." return render_template('subscription.html', form=subscription_form, message=error, r=0, **self.args) selected_product = None selected_cvss = None if data["vpc-" + str(i) + "-productField"] != "": print("hello") selected_product = data["vpc-" + str(i) + "-productField"] # print(data["vpc-" + str(i) + "-productField"]) if data["vpc-" + str(i) + "-cvssField"] != "": selected_cvss = data["vpc-" + str(i) + "-cvssField"] if data["vendor-product-action"] == "1": ncert_db.addMail(data["email"], data["vpc-" + str(i) + "-vendorField"], data["token"], data["activated"], selected_product, selected_cvss) if data["vendor-product-action"] == "0": ncert_db.setupUnconfirmToken( data["email"], data["vpc-" + str(i) + "-vendorField"], selected_product, data["token"]) # ncert_db.addMail(data["email"], data["vpc-" + str(i) + "-vendorField"], selected_product, selected_cvss) #send mail for conf id = self.generate_confirmation_param(data["email"]) token = self.generate_confirmation_param(data["token"]) if data["vendor-product-action"] == "1": self.send_sub_conf_link({ "email": data["email"], "id": id, "token": token }) if data["vendor-product-action"] == "0": self.send_unsub_conf_link({ "email": data["email"], "id": id, "token": token }) subscription_form = form_class.SubscriptionForm() cve = self.filter_logic(self.defaultFilters, 0) # message = "Uspješno ste se preplatili na zadane liste ranjivosti proizvođača i proizvoda" message = "Na e-mail adresu Vam je poslan e-mail za potvrdu odabrane radnje." return render_template('index.html', cve=cve, message=message, r=0, **self.args) def check_subscription_email(self, email): existed_email = ncert_db.checkEmail(email) return json.dumps({"email_existed": existed_email}) def send_subscription_report(self, email): self.sendPopisPretplata(email) return json.dumps({"email_sent": True}) def unsubscribe(self, email): ncert_db.removeMail(email) return json.dumps({"email_deleted": True}) ########### # Filters # ########### def htmlEncode(self, string): return urllib.parse.quote_plus(string).lower() def htmlDecode(self, string): return urllib.parse.unquote_plus(string) def sortIntLikeStr(self, datalist): return sorted(datalist, key=lambda k: int(k)) def JSON2HTMLTable(self): # Doublequote, because we have to |safe the content for the tags def doublequote(data): return urllib.parse.quote_plus(urllib.parse.quote_plus(data)) def JSON2HTMLTableFilter(data, stack=None): _return = "" if type(stack) == str: stack = [stack] if type(data) == list: if len(data) == 1: _return += JSON2HTMLTableFilter(data[0], stack) else: _return += '<ul class="via4">' for item in data: _return += ('<li>%s</li>' % JSON2HTMLTableFilter(item, stack)) _return += '</ul>' elif type(data) == dict: _return += '<table class="invisiTable">' for key, val in sorted(data.items()): _return += '<tr><td><b>%s</b></td><td>%s</td></tr>' % ( key, JSON2HTMLTableFilter(val, stack + [key])) _return += '</table>' elif type(data) == str: if stack: _return += "<a href='/link/" + doublequote('.'.join( stack)) + "/" + doublequote(data) + "'>" #link opening _return += "<span class='glyphicon glyphicon-link' aria-hidden='true'></span> </a>" _return += "<a target='_blank' href='%s'>%s</a>" % ( data, data) if tk.isURL(data) else data _return += "" return _return return dict(JSON2HTMLTable=JSON2HTMLTableFilter) ################## # Error Messages # ################## def page_not_found(self, e): return render_template('404.html', minimal=self.minimal), 404
from lib.Config import Configuration from lib.Toolkit import toStringFormattedCPE, toOldCPE, currentTime, isURL, vFeedName, convertDateToDBFormat import lib.CVEs as cves import lib.DatabaseLayer as dbLayer # parse command line arguments argparser = argparse.ArgumentParser( description='Start CVE-Search web component') argparser.add_argument('-v', action='store_true', help='verbose output') args = argparser.parse_args() # variables app = Flask(__name__, static_folder='static', static_url_path='/static') app.config['MONGO_DBNAME'] = Configuration.getMongoDB() app.config['SECRET_KEY'] = str(random.getrandbits(256)) pageLength = Configuration.getPageLength() # db connectors redisdb = Configuration.getRedisVendorConnection() # functions def getBrowseList(vendor): result = {} if (vendor is None) or type(vendor) == list: v1 = redisdb.smembers("t:/o") v2 = redisdb.smembers("t:/a") v3 = redisdb.smembers("t:/h") vendor = sorted(list(set(list(v1) + list(v2) + list(v3)))) cpe = None else:
plugManager = PluginManager() plugManager.loadPlugins() defaultFilters = { "timeSelect": "all", "startDate": "", "endDate": "", "timeTypeSelect": "Modified", "cvssSelect": "all", "cvss": "0", "rejectedSelect": "hide", } config_args = { "pageLength": config.getPageLength(), "listLogin": config.listLoginRequired(), "minimal": True, } pluginArgs = { "current_user": current_user, "plugin_manager": plugManager, } def get_plugins(): if ( not current_user.is_authenticated ): # Don't show plugins requiring auth if not authenticated plugins = [
class Minimal(API): ############# # Variables # ############# defaultFilters={'timeSelect': 'all', 'startDate': '', 'endDate': '', 'timeTypeSelect': 'Modified', 'cvssSelect': 'all', 'cvss': '', 'rejectedSelect': 'hide'} args = {'pageLength': Configuration.getPageLength(), 'listLogin': Configuration.listLoginRequired(), 'minimal': True} def __init__(self): self.minimal = True super().__init__() routes = [{'r': '/', 'm': ['GET'], 'f': self.index}, {'r': '/', 'm': ['POST'], 'f': self.index_post}, {'r': '/r/<int:r>', 'm': ['GET'], 'f': self.index_filter_get}, {'r': '/r/<int:r>', 'm': ['POST'], 'f': self.index_filter_post}, {'r': '/cve/<cveid>', 'm': ['GET'], 'f': self.cve}, {'r': '/cwe', 'm': ['GET'], 'f': self.cwe}, {'r': '/cwe/<cweid>', 'm': ['GET'], 'f': self.relatedCWE}, {'r': '/capec/<capecid>', 'm': ['GET'], 'f': self.capec}, {'r': '/browse', 'm': ['GET'], 'f': self.browse}, {'r': '/browse/', 'm': ['GET'], 'f': self.browse}, {'r': '/browse/<vendor>', 'm': ['GET'], 'f': self.browse}, {'r': '/search/<vendor>/<path:product>', 'm': ['GET'], 'f': self.search}, {'r': '/search', 'm': ['POST'], 'f': self.freetext_search}, {'r': '/link/<key>/<value>', 'm': ['GET'], 'f': self.link}] filters = [{'n': 'htmlEncode', 'f': self.htmlEncode}, {'n': 'htmlDecode', 'f': self.htmlDecode}, {'n': 'sortIntLikeStr', 'f': self.sortIntLikeStr}] context_processors = [self.JSON2HTMLTable] error_handlers = [{'e': 404, 'f': self.page_not_found}] for route in routes: self.addRoute(route) for _filter in filters: self.addFilter(_filter) for context in context_processors: self.addContextProcessors(context) for handler in error_handlers: self.app.register_error_handler(handler['e'], handler['f']) ############# # Functions # ############# def addFilter(self, _filter): self.app.add_template_filter(_filter['f'], _filter['n']) def addContextProcessors(self, context_processor): self.app.context_processor(context_processor) def getFilterSettingsFromPost(self, r): filters = dict(request.form) errors = False # retrieving data try: cve = self.filter_logic(filters, r) except Exception as e: cve = db.getCVEs(limit=self.args['pageLength'], skip=r) errors = True return {'filters': filters, 'cve': cve, 'errors': errors} ########## # ROUTES # ########## # / def index(self): cve = self.filter_logic(self.defaultFilters, 0) return render_template('index.html', cve=cve, r=0, **self.args) # / def index_post(self): args = dict(self.getFilterSettingsFromPost(0), **self.args) return render_template('index.html', r=0, **args) # /r/<r> def index_filter_get(self, r): if not r or r < 0: r = 0 cve = self.filter_logic(self.defaultFilters, r) return render_template('index.html', cve=cve, r=r, **self.args) # /r/<r> def index_filter_post(self, r): if not r or r < 0: r = 0 args = dict(self.getFilterSettingsFromPost(r), **self.args) return render_template('index.html', r=r, **args) # /cve/<cveid> def cve(self, cveid): cve = self.api_cve(cveid) if not cve: return render_template('error.html',status={'except':'cve-not-found','info':{'cve':cveid}},minimal=self.minimal) return render_template('cve.html', cve=cve, minimal=self.minimal) # /cwe def cwe(self): cwes=[x for x in self.api_cwe() if x["weaknessabs"].lower()=="class"] return render_template('cwe.html', cwes=cwes, capec=None, minimal=self.minimal) # /cwe/<cweid> def relatedCWE(self, cweid): cwes={x["id"]: x["name"] for x in self.api_cwe()} return render_template('cwe.html', cwes=cwes, cwe=cweid, capec=db.getCAPECFor(cweid), minimal=self.minimal) # /capec/<capecid> def capec(self, capecid): cwes={x["id"]: x["name"] for x in self.api_cwe()} return render_template('capec.html', cwes=cwes, capec=db.getCAPEC(capecid), minimal=self.minimal) # /browse # /browse/ # /browse/<vendor> def browse(self, vendor=None): try: data = self.api_browse(vendor) if 'product' in data and 'vendor' in data: return render_template('browse.html', product=data["product"], vendor=data["vendor"], minimal=self.minimal) else: return render_template('error.html', minimal=self.minimal, status={'except':'browse_exception', 'info': 'No CPE'}) except APIError as e: return render_template('error.html', minimal=self.minimal, status={'except':'browse_exception', 'info':e.message}) # /search/<vendor>/<product> def search(self, vendor=None, product=None): search = vendor + ":" + product cve = db.cvesForCPE(search) return render_template('search.html', vendor=vendor, product=product, cve=cve, minimal=self.minimal) # /search def freetext_search(self): search = request.form.get('search') if search == '': return self.index() result = db.getSearchResults(search) cve={'results': result['data'], 'total': len(result['data'])} errors=result['errors'] if 'errors' in result else [] return render_template('search.html', cve=cve, errors=errors, freetextsearch=search, minimal=self.minimal) # /link/<key>/<value> def link(self, key=None,value=None): key=self.htmlDecode(key) value=self.htmlDecode(value) regex = re.compile(re.escape(value), re.I) cve=db.via4Linked(key, regex) cvssList=[float(x['cvss']) for x in cve['results'] if x.get('cvss')] if cvssList: stats={'maxCVSS': max(cvssList), 'minCVSS': min(cvssList),'count':len(cve)} else: stats={'maxCVSS': 0, 'minCVSS': 0, 'count':len(cve)} return render_template('linked.html', via4map=key.split(".")[0], field='.'.join(key.split(".")[1:]), value=value, cve=cve, stats=stats, minimal=self.minimal) ########### # Filters # ########### def htmlEncode(self, string): return urllib.parse.quote_plus(string).lower() def htmlDecode(self, string): return urllib.parse.unquote_plus(string) def sortIntLikeStr(self, datalist): return sorted(datalist, key=lambda k: int(k)) def JSON2HTMLTable(self): # Doublequote, because we have to |safe the content for the tags def doublequote(data): return urllib.parse.quote_plus(urllib.parse.quote_plus(data)) def JSON2HTMLTableFilter(data, stack = None): _return = "" if type(stack) == str: stack = [stack] if type(data) == list: if len(data) == 1: _return += JSON2HTMLTableFilter(data[0], stack) else: _return += '<ul class="via4">' for item in data: _return += ('<li>%s</li>'%JSON2HTMLTableFilter(item, stack)) _return += '</ul>' elif type(data) == dict: _return += '<table class="invisiTable">' for key, val in sorted(data.items()): _return += '<tr><td><b>%s</b></td><td>%s</td></tr>'%(key, JSON2HTMLTableFilter(val, stack+[key])) _return += '</table>' elif type(data) == str: if stack: _return += "<a href='/link/"+doublequote('.'.join(stack))+"/"+doublequote(data)+"'>" #link opening _return += "<span class='glyphicon glyphicon-link' aria-hidden='true'></span> </a>" _return += "<a target='_blank' href='%s'>%s</a>"%(data, data) if tk.isURL(data) else data _return += "" return _return return dict(JSON2HTMLTable=JSON2HTMLTableFilter) ################## # Error Messages # ################## def page_not_found(self, e): return render_template('404.html', minimal=self.minimal), 404
class Minimal(API): ############# # Variables # ############# defaultFilters = { "timeSelect": "all", "startDate": "", "endDate": "", "timeTypeSelect": "Modified", "cvssSelect": "all", "cvss": "", "rejectedSelect": "hide", } args = { "pageLength": Configuration.getPageLength(), "listLogin": Configuration.listLoginRequired(), "minimal": True, } def __init__(self): self.minimal = True super().__init__() routes = [ { "r": "/", "m": ["GET"], "f": self.index }, { "r": "/", "m": ["POST"], "f": self.index_post }, { "r": "/r/<int:r>", "m": ["GET"], "f": self.index_filter_get }, { "r": "/r/<int:r>", "m": ["POST"], "f": self.index_filter_post }, { "r": "/cve/<cveid>", "m": ["GET"], "f": self.cve }, { "r": "/cwe", "m": ["GET"], "f": self.cwe }, { "r": "/cwe/<cweid>", "m": ["GET"], "f": self.relatedCWE }, { "r": "/capec/<capecid>", "m": ["GET"], "f": self.capec }, { "r": "/browse", "m": ["GET"], "f": self.browse }, { "r": "/browse/", "m": ["GET"], "f": self.browse }, { "r": "/browse/<vendor>", "m": ["GET"], "f": self.browse }, { "r": "/search/<vendor>/<path:product>", "m": ["GET"], "f": self.search }, { "r": "/search", "m": ["POST"], "f": self.freetext_search }, { "r": "/link/<key>/<value>", "m": ["GET"], "f": self.link }, ] filters = [ { "n": "htmlEncode", "f": self.htmlEncode }, { "n": "htmlDecode", "f": self.htmlDecode }, { "n": "sortIntLikeStr", "f": self.sortIntLikeStr }, ] context_processors = [self.JSON2HTMLTable] error_handlers = [{"e": 404, "f": self.page_not_found}] for route in routes: self.addRoute(route) for _filter in filters: self.addFilter(_filter) for context in context_processors: self.addContextProcessors(context) for handler in error_handlers: self.app.register_error_handler(handler["e"], handler["f"]) ############# # Functions # ############# def addFilter(self, _filter): self.app.add_template_filter(_filter["f"], _filter["n"]) def addContextProcessors(self, context_processor): self.app.context_processor(context_processor) def getFilterSettingsFromPost(self, r): filters = dict(request.form) errors = False # retrieving data try: cve = self.filter_logic(filters, r) except Exception as e: cve = getCVEs(limit=self.args["pageLength"], skip=r) errors = True return {"filters": filters, "cve": cve, "errors": errors} ########## # ROUTES # ########## # / def index(self): cve = self.filter_logic(self.defaultFilters, 0) return render_template("index.html", cve=cve, r=0, **self.args) # / def index_post(self): args = dict(self.getFilterSettingsFromPost(0), **self.args) return render_template("index.html", r=0, **args) # /r/<r> def index_filter_get(self, r): if not r or r < 0: r = 0 cve = self.filter_logic(self.defaultFilters, r) return render_template("index.html", cve=cve, r=r, **self.args) # /r/<r> def index_filter_post(self, r): if not r or r < 0: r = 0 args = dict(self.getFilterSettingsFromPost(r), **self.args) return render_template("index.html", r=r, **args) # /cve/<cveid> def cve(self, cveid): cve = self.api_cve(cveid) if not cve: return render_template( "error.html", status={ "except": "cve-not-found", "info": { "cve": cveid } }, minimal=self.minimal, ) return render_template("cve.html", cve=cve, minimal=self.minimal) # /cwe def cwe(self): cwes = [ x for x in self.api_cwe() if x["weaknessabs"].lower() == "class" ] return render_template("cwe.html", cwes=cwes, capec=None, minimal=self.minimal) # /cwe/<cweid> def relatedCWE(self, cweid): cwes = {x["id"]: x["name"] for x in self.api_cwe()} return render_template( "cwe.html", cwes=cwes, cwe=cweid, capec=getCAPECFor(cweid), minimal=self.minimal, ) # /capec/<capecid> def capec(self, capecid): cwes = {x["id"]: x["name"] for x in self.api_cwe()} req_capec = getCAPEC(capecid) rel_capecs = defaultdict(dict) if len(req_capec["related_capecs"]) != 0: for each in req_capec["related_capecs"]: rel_capecs[each] = getCAPEC(each)["summary"] return render_template( "capec.html", cwes=cwes, capecs=dict(rel_capecs), capec=req_capec, minimal=self.minimal, ) # /browse # /browse/ # /browse/<vendor> def browse(self, vendor=None): try: data = self.api_browse(vendor) if "product" in data and "vendor" in data: return render_template( "browse.html", product=data["product"], vendor=data["vendor"], minimal=self.minimal, ) else: return render_template( "error.html", minimal=self.minimal, status={ "except": "browse_exception", "info": "No CPE" }, ) except APIError as e: return render_template( "error.html", minimal=self.minimal, status={ "except": "browse_exception", "info": e.message }, ) # /search/<vendor>/<product> def search(self, vendor=None, product=None): search = vendor + ":" + product cve = cvesForCPE(search) return render_template("search.html", vendor=vendor, product=product, cve=cve, minimal=self.minimal) # /search def freetext_search(self): search = request.form.get("search") if search == "": return self.index() result = getSearchResults(search) cve = {"results": result["data"], "total": len(result["data"])} errors = result["errors"] if "errors" in result else [] return render_template( "search.html", cve=cve, errors=errors, freetextsearch=search, minimal=self.minimal, ) # /link/<key>/<value> def link(self, key=None, value=None): key = self.htmlDecode(key) value = self.htmlDecode(value) regex = re.compile(re.escape(value), re.I) cve = via4Linked(key, regex) cvssList = [float(x["cvss"]) for x in cve["results"] if x.get("cvss")] if cvssList: stats = { "maxCVSS": max(cvssList), "minCVSS": min(cvssList), "count": len(cve), } else: stats = {"maxCVSS": 0, "minCVSS": 0, "count": len(cve)} return render_template( "linked.html", via4map=key.split(".")[0], field=".".join(key.split(".")[1:]), value=value, cve=cve, stats=stats, minimal=self.minimal, ) ########### # Filters # ########### def htmlEncode(self, string): return urllib.parse.quote_plus(string).lower() def htmlDecode(self, string): return urllib.parse.unquote_plus(string) def sortIntLikeStr(self, datalist): return sorted(datalist, key=lambda k: int(k)) def JSON2HTMLTable(self): # Doublequote, because we have to |safe the content for the tags def doublequote(data): return urllib.parse.quote_plus(urllib.parse.quote_plus(data)) def JSON2HTMLTableFilter(data, stack=None): _return = "" if type(stack) == str: stack = [stack] if type(data) == list: if len(data) == 1: _return += JSON2HTMLTableFilter(data[0], stack) else: _return += '<ul class="via4">' for item in data: _return += "<li>%s</li>" % JSON2HTMLTableFilter( item, stack) _return += "</ul>" elif type(data) == dict: _return += '<table class="invisiTable">' for key, val in sorted(data.items()): _return += "<tr><td><b>%s</b></td><td>%s</td></tr>" % ( key, JSON2HTMLTableFilter(val, stack + [key]), ) _return += "</table>" elif type(data) == str: if stack: _return += ("<a href='/link/" + doublequote(".".join(stack)) + "/" + doublequote(data) + "'>") # link opening _return += "<span class='glyphicon glyphicon-link' aria-hidden='true'></span> </a>" _return += ("<a target='_blank' href='%s'>%s</a>" % (data, data) if isURL(data) else data) _return += "" return _return return dict(JSON2HTMLTable=JSON2HTMLTableFilter) ################## # Error Messages # ################## def page_not_found(self, e): return render_template("404.html", minimal=self.minimal), 404
from lib.Config import Configuration from lib.Toolkit import toStringFormattedCPE, toOldCPE, isURL, vFeedName import lib.CVEs as cves import lib.DatabaseLayer as dbLayer # parse command line arguments argparser = argparse.ArgumentParser( description='Start CVE-Search web component') argparser.add_argument('-v', action='store_true', help='verbose output') args = argparser.parse_args() # variables app = Flask(__name__, static_folder='static', static_url_path='/static') app.config['MONGO_DBNAME'] = Configuration.getMongoDB() app.config['SECRET_KEY'] = str(random.getrandbits(256)) pageLength = Configuration.getPageLength() # db connectors redisdb = Configuration.getRedisVendorConnection() pageSettings = { 'pageLength': Configuration.getPageLength(), 'listLogin': Configuration.listLoginRequired(), 'minimal': True } # functions def getBrowseList(vendor): result = {} if (vendor is None) or type(vendor) == list:
from lib.Config import Configuration from lib.Toolkit import toStringFormattedCPE, toOldCPE, isURL, vFeedName import lib.CVEs as cves import lib.DatabaseLayer as dbLayer # parse command line arguments argparser = argparse.ArgumentParser(description='Start CVE-Search web component') argparser.add_argument('-v', action='store_true', help='verbose output') args = argparser.parse_args() # variables app = Flask(__name__, static_folder='static', static_url_path='/static') app.config['MONGO_DBNAME'] = Configuration.getMongoDB() app.config['SECRET_KEY'] = str(random.getrandbits(256)) pageLength = Configuration.getPageLength() # db connectors redisdb = Configuration.getRedisVendorConnection() pageSettings = {'pageLength': Configuration.getPageLength(), 'listLogin': Configuration.listLoginRequired(), 'minimal': True} # functions def getBrowseList(vendor): result = {} if (vendor is None) or type(vendor) == list: v1 = redisdb.smembers("t:/o") v2 = redisdb.smembers("t:/a") v3 = redisdb.smembers("t:/h")