├── README.md ├── bin ├── Nmap2CVE-Search.py ├── analyzer.py ├── converter.py └── visualizer.py ├── etc ├── configuration.ini └── configuration.ini.sample ├── example.xml ├── lib ├── Config.py ├── PDFParser.py ├── TermDisplay.py ├── Toolkit.py ├── WebDisplay.py ├── static │ ├── css │ │ ├── bootstrap.min.css │ │ ├── flaticon.css │ │ ├── pdf.css │ │ └── style.css │ ├── fonts │ │ ├── flaticon.eot │ │ ├── flaticon.svg │ │ ├── flaticon.ttf │ │ ├── flaticon.woff │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ └── glyphicons-halflings-regular.woff │ └── js │ │ ├── bootstrap.min.js │ │ ├── custom │ │ ├── cve.js │ │ └── scripts.js │ │ └── jquery-1.11.2.min.js └── templates │ ├── 404.html │ ├── cve.html │ ├── defaultHead.html │ ├── index.html │ ├── menu.html │ └── pdf.html ├── license.txt └── requirements.txt /README.md: -------------------------------------------------------------------------------- 1 | # CVE-Scan 2 | Scan systems with NMap and parse the output to a list of CVE's, CWE's and DPE's 3 | 4 | ## Goals: 5 | * Scan a system with NMap or any other scanning tool and use the scan to analyse the systems for vulnerabilities 6 | * Have the posibility for multiple input formats (NMap scan, xml, Json, etc) 7 | * Use CVE-Search to enhance the scan to add more information 8 | * Have multiple export formats as well as webbrowser component 9 | 10 | ### Optional: 11 | * Automatically download known scripts to use on exploits 12 | 13 | ## Installation: 14 | Warning, this tutorial is for Linux systems (developed and tested on Ubuntu 14.10). 15 | This program should run under Windows (and probably Mac) systems as well. 16 | 17 | ### Requirements 18 | CVE-Scan uses the CVE-Search API to enhance your nmap scans.
19 | **Warning** CVE-Search is not included in CVE-Scan
20 | You can use [CIRCL](http://circl.lu)s [public API] 21 | (http://cve.circl.lu), or install CVE-Search localy, or on another accessible machine. 22 | You can install [CVE-Search](https://github.com/PidgeyL/cve-search) from the git repo. 23 | For now, CVE-Search does not have a "core" package yet (Without the webpages), but I will add this later on. 24 | Once you installed CVE-Search, in the configuration file, make sure you set the correct URL to it. 25 | 26 | CVE-Scan needs some aditional packages to work. Install them using: 27 | 28 | ```sudo apt-get install -y nmap``` (or your package manager of choice) 29 | 30 | ```pip3 install -r requirements.txt``` 31 | 32 | Weasyprint has a set of sub-requirements. Please find the details [here](http://weasyprint.readthedocs.org/en/latest/install.html) 33 | 34 | ## Usage: 35 | To use CVE-Scan, first run an nmap scan on a system. You can modify the 36 | parameters however you want, however, you'd want to include Service Detection 37 | and OS detection. Below, you can find a default nmap scan that will output to 38 | an xml file. 39 | 40 | ```nmap -A -O 192.168.0.1 -oX output.xml``` 41 | 42 | CVE-Scan is composed of 3 major functions: 43 | * **converter.py** - Converts the nmap xml to the CVE-Scan json format 44 | * **analyzer.py** - Analyses either an nmap xml or a CVE-Scan json and 45 | queries CVE-Search to obtain vulnerability information 46 | * **visualizer.py** - Visualizes the results of analyzer.py 47 | 48 | and **Nmap2CVE-Search.py**, which does all of the above in 1 go. 49 | 50 | You can either run ```python3 Nmap2CVE-Search.py output.xml``` to 51 | enhance and visualize the report, or 52 | ```python3 analyzer.py -x output.xml enhanced.json```, to create the 53 | enhanced report, followed by ```python3 visualizer.py enhanced.json``` 54 | to visualize the report (default webserver on localhost:5050. 55 | Add -t for terminal view) 56 | 57 | All scripts in the `bin` folder can be called with the -h flag, to get more information about it. 58 | 59 | ## Online Demo 60 | If you want to try our [online demo](http://northernsec.eu/cve-scan), 61 | please visit our [website](http://northernsec.eu). 62 | 63 | Since we don't have a large budget, the website might not be available all the time. 64 | 65 | ## Support us 66 | If you like this tool, please consider donating, so we can keep our servers up and running. 67 | You can support us on [Subscribestar](https://www.subscribestar.com/pidgey) 68 | 69 | ## Licencing 70 | This software is licensed under the "Original BSD License". 71 | ``` 72 | (C) 2015 NorthernSec https://github.com/NorthernSec 73 | (c) 2015 Pieter-Jan Moreels https://github.com/pidgeyl 74 | ``` 75 | -------------------------------------------------------------------------------- /bin/Nmap2CVE-Search.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.3 2 | # -*- coding: utf8 -*- 3 | # 4 | # Read input from NMap and use the information from cve-search and 5 | # Toolswatch DPE (Default Password Enumeration) list to provide a list of 6 | # possible ways a system might be misconfigured or vulnerable. 7 | 8 | # Copyright (c) 2015 NorthernSec 9 | # Copyright (c) 2015 Pieter-Jan Moreels 10 | # This software is licensed under the Original BSD License 11 | 12 | # Imports 13 | import os 14 | import sys 15 | runpath=os.path.dirname(os.path.realpath(__file__)) 16 | sys.path.append(os.path.join(runpath, '..')) 17 | 18 | import argparse 19 | 20 | from lib.Config import Configuration 21 | 22 | from bin.converter import parseNMap 23 | from bin.analyzer import enhance 24 | from bin.visualizer import filtersFromArgs, displayTypeFromArgs, visualize 25 | 26 | description='''Read Nmap scans of services or systems and use the 27 | cve-search core to get information about these cpes.''' 28 | 29 | parser = argparse.ArgumentParser(description=description) 30 | parser.add_argument('-t', action='store_true', help='Use terminal GUI') 31 | parser.add_argument('-p', action='store_true', help='Print results to PDF') 32 | parser.add_argument('-fE', action='store_true', help='Filter: Exploit scripts/frameworks available') 33 | parser.add_argument('-fN', action='store_true', help='Filter: Exploitable via network') 34 | parser.add_argument('-fL', action='store_true', help='Filter: Exploitable locally') 35 | parser.add_argument('-fAN',action='store_true', help='Filter: Exploitable via adjecent network') 36 | parser.add_argument('-fC', action='store_true', help='Filter: Impacts Confidentiality') 37 | parser.add_argument('-fI', action='store_true', help='Filter: Impacts Integrity') 38 | parser.add_argument('-fA', action='store_true', help='Filter: Impacts Availability') 39 | parser.add_argument('file',metavar='xml', type=str, help='NMap XML file' ) 40 | args = parser.parse_args() 41 | 42 | if __name__ == '__main__': 43 | syslist=parseNMap(file=args.file) 44 | try: 45 | syslist=enhance(syslist) 46 | except: 47 | sys.exit("Could not connect to the CVE-Search API on %s:%s"%(Configuration.getCVESearch())) 48 | filters=filtersFromArgs(args) 49 | display=displayTypeFromArgs(args) 50 | visualize(syslist, args.fE, filters, display) 51 | -------------------------------------------------------------------------------- /bin/analyzer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.3 2 | # -*- coding: utf8 -*- 3 | # 4 | # Read input from NMap and use the information from cve-search to find 5 | # potential vulnerabilities in the recognized systems and their services 6 | 7 | # Copyright (c) 2015-2017 NorthernSec 8 | # Copyright (c) 2015-2017 Pieter-Jan Moreels 9 | # This software is licensed under the Original BSD License 10 | 11 | # Imports 12 | import argparse 13 | import json 14 | import os 15 | import sys 16 | 17 | runpath=os.path.dirname(os.path.realpath(__file__)) 18 | sys.path.append(os.path.join(runpath, '..')) 19 | 20 | from datetime import datetime 21 | 22 | from bin.converter import parseNMap 23 | from lib.Config import Configuration 24 | from lib.Toolkit import writeJson, queryAPI 25 | 26 | def enhance(scan): 27 | for system in scan['systems']: 28 | cpe=system['cpes'] if 'cpes' in system else None 29 | if cpe: 30 | cpes=[] 31 | for c in cpe: 32 | try: 33 | c = c.lower() 34 | cpes.append({'cpe': c, 'cves': queryAPI(c)}) 35 | except Exception as e: 36 | print(e) 37 | pass 38 | system['cpes']=cpes 39 | #TODO get possible dpe info and store in dpe 40 | for service in system['services']: 41 | if 'cpe' in service: 42 | try: 43 | service['cves']=queryAPI( service['cpe'].lower() ) 44 | except Exception as e: 45 | print(e) 46 | pass 47 | #TODO get dpe info for service 48 | scan['enhanced']={"time": int(datetime.now().strftime('%s'))} 49 | return scan 50 | 51 | 52 | if __name__ == '__main__': 53 | # argument parser 54 | description='''Read input from NMap and use the information from 55 | cve-search to find potential vulnerabilities in the 56 | recognized systems and their services''' 57 | parser = argparse.ArgumentParser(description=description) 58 | parser.add_argument('-j', metavar='json', type=str, help='Read Json file in Nmap2CVE format' ) 59 | parser.add_argument('-x', metavar='xml', type=str, help='Read NMap XML file' ) 60 | parser.add_argument('out', metavar='output', type=str, help='Output file') 61 | args = parser.parse_args() 62 | 63 | # input 64 | if not args.x and not args.j: sys.exit("No input selected!") 65 | if args.x: 66 | syslist=parseNMap(file=args.x) 67 | elif args.j: 68 | try: 69 | syslist=json.loads(open(args.j).read()) 70 | except: 71 | sys.exit("Invalid JSon format!") 72 | #output 73 | 74 | #CVE-Scan magic 75 | try: 76 | syslist=enhance(syslist) 77 | writeJson(args.out, syslist) 78 | except Exception as e: 79 | print(e) 80 | sys.exit("Could not connect to the CVE-Search API on %s:%s"%(Configuration.getCVESearch())) 81 | -------------------------------------------------------------------------------- /bin/converter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.3 2 | # -*- coding: utf8 -*- 3 | # 4 | # Converts the nmap xml file to the stripped down CVE-Search json 5 | # format 6 | 7 | # Copyright (c) 2015 NorthernSec 8 | # Copyright (c) 2015 Pieter-Jan Moreels 9 | # This software is licensed under the Original BSD License 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 | try: 18 | from libnmap.parser import NmapParser 19 | except: 20 | sys.exit("Missing dependencies!") 21 | 22 | import argparse 23 | 24 | from lib.Toolkit import writeJson 25 | 26 | def parseNMap(file=None, string=None): 27 | try: 28 | if file: report = NmapParser.parse_fromfile(file) 29 | elif string: report = NmapParser.parse_fromstring(string) 30 | else: raise(Exception) 31 | except: 32 | raise(Exception) 33 | systems = [] 34 | for h in report.hosts: 35 | system = {'mac':h.mac, 'ip':h.address, 'status':h.status, 'hostnames': h.hostnames, 36 | 'vendor':h.vendor, 'distance':h.distance} 37 | cpeList = [] 38 | for c in h.os_match_probabilities(): 39 | for x in c.get_cpe(): 40 | cpeList.append(x) 41 | cpeList=list(set(cpeList)) 42 | if len(cpeList)>0: 43 | system['cpes']=cpeList 44 | services = [] 45 | for s in h.services: 46 | service={'port':s.port, 'banner':s.banner, 'protocol':s.protocol, 'name':s.service, 47 | 'state':s.state, 'reason':s.reason} 48 | if s.cpelist: 49 | service['cpe'] = s.cpelist[0].cpestring 50 | services.append(service) 51 | system['services']=services 52 | systems.append(system) 53 | scan={"systems":systems, "scan": {"time": report.endtime, 54 | "type": report._nmaprun["args"]}} 55 | return scan 56 | 57 | if __name__ == '__main__': 58 | # argument parser 59 | description='''Converts the nmap xml file to the stripped down 60 | CVE-Search json format''' 61 | parser = argparse.ArgumentParser(description=description) 62 | parser.add_argument('inp', metavar='input', type=str, help='Input nmap xml file') 63 | parser.add_argument('out', metavar='output', type=str, help='Output file') 64 | args = parser.parse_args() 65 | 66 | # input 67 | try: 68 | syslist=parseNMap(file=args.inp) 69 | except: 70 | exit("Invalid Nmap xml!") 71 | writeJson(args.out, syslist) 72 | -------------------------------------------------------------------------------- /bin/visualizer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.3 2 | # -*- coding: utf8 -*- 3 | # 4 | # Visualizes the enhanced nmap results 5 | 6 | # Copyright (c) 2015 NorthernSec 7 | # Copyright (c) 2015 Pieter-Jan Moreels 8 | # This software is licensed under the Original BSD License 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 argparse 17 | import json 18 | 19 | visuals={'web': {'import': 'from lib.WebDisplay import WebDisplay', 20 | 'exec': 'WebDisplay.start(scan=data)'}, 21 | 'term': {'import': 'from lib.TermDisplay import TermDisplay', 22 | 'exec': 'TermDisplay.start(scan=data)'}, 23 | 'pdf': {'import': 'from lib.PDFParser import pdfify', 24 | 'exec': 'pdfify(data, args.p)'} } 25 | 26 | def filtersFromArgs(args): 27 | # populate filters 28 | filters={'access':[],'impact':[]} 29 | if args.fL: filters['access'].append('LOCAL') 30 | if args.fAN: filters['access'].append('ADJECENT_NETWORK') 31 | if args.fN: filters['access'].append('NETWORK') 32 | if args.fC: filters['impact'].append('confidentiality') 33 | if args.fI: filters['impact'].append('integrity') 34 | if args.fA: filters['impact'].append('availability') 35 | return filters 36 | 37 | def filter(vulns, exploitsOnly=False, filters={}): 38 | if 'access' in filters and len(filters['access'])!=0: # access filters 39 | vulns=[x for x in vulns if 'access' in x and x['access']['vector'] in filters['access']] 40 | if 'impact' in filters and len(filters['impact'])!=0: # impact filters 41 | for fil in filters['impact']: vulns=[x for x in vulns if 'impact' in x and x['impact'][fil] !='NONE'] 42 | # exploits only 43 | if exploitsOnly: vulns=[x for x in vulns if ('map_cve_exploitdb' in x or 'map_cve_msf' in x)] 44 | return vulns 45 | 46 | def displayTypeFromArgs(args): 47 | if args.t: return "term" 48 | elif args.p: return "pdf" 49 | else: return "web" 50 | 51 | def visualize(data, exploitOnly=False, filters={}, display="web"): 52 | # do the filtering on the data 53 | for system in data['systems']: 54 | if 'cpes' in system: 55 | for cpe in system['cpes']: 56 | cpe['cves']=filter(cpe['cves'], exploitOnly, filters) 57 | for service in system['services']: 58 | if "cves" in service: 59 | service['cves']=filter(service['cves'], exploitOnly, filters) 60 | # display using the correct method 61 | try: 62 | if not display in visuals.keys(): 63 | sys.exit("Could not visualize: Unknown display (%s)"%display) 64 | # try to import requirements 65 | try: 66 | exec(visuals[display]['import']) 67 | except: 68 | sys.exit("Could not visualize due to missing dependencies") 69 | exec(visuals[display]['exec']) 70 | except KeyboardInterrupt: 71 | pass 72 | 73 | if __name__ == '__main__': 74 | # argument parser 75 | description='''Visualizes the enhanced nmap results''' 76 | parser = argparse.ArgumentParser(description=description) 77 | parser.add_argument('-t', action='store_true', help='Use terminal GUI') 78 | parser.add_argument('-p', metavar='location', help='Parse to PDF to location') 79 | parser.add_argument('-fE', action='store_true', help='Filter: Exploit scripts/frameworks available') 80 | parser.add_argument('-fN', action='store_true', help='Filter: Exploitable via network') 81 | parser.add_argument('-fL', action='store_true', help='Filter: Exploitable locally') 82 | parser.add_argument('-fAN',action='store_true', help='Filter: Exploitable via adjecent network') 83 | parser.add_argument('-fC', action='store_true', help='Filter: Impacts Confidentiality') 84 | parser.add_argument('-fI', action='store_true', help='Filter: Impacts Integrity') 85 | parser.add_argument('-fA', action='store_true', help='Filter: Impacts Availability') 86 | parser.add_argument('inp', metavar='input', help='output file from analyzer' ) 87 | args = parser.parse_args() 88 | 89 | # intakes 90 | try: 91 | syslist=json.loads(open(args.inp).read()) 92 | except: 93 | sys.exit("Invalid JSon format!") 94 | 95 | filters = filtersFromArgs(args) 96 | display = displayTypeFromArgs(args) 97 | visualize(syslist, args.fE, filters, display) 98 | -------------------------------------------------------------------------------- /etc/configuration.ini: -------------------------------------------------------------------------------- 1 | [Webserver] 2 | Host: 127.0.0.1 3 | Port: 5050 4 | Debug: True 5 | 6 | [CVE-Search] 7 | Host: cve.circl.lu 8 | Port: 443 9 | ssl: True 10 | -------------------------------------------------------------------------------- /etc/configuration.ini.sample: -------------------------------------------------------------------------------- 1 | [Webserver] 2 | Host: 127.0.0.1 3 | Port: 5050 4 | Debug: True 5 | 6 | [CVE-Search] 7 | Host: cve.circl.lu 8 | Port: 80 9 | -------------------------------------------------------------------------------- /example.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | cpe:/a:openbsd:openssh:5.3p1 26 | cpe:/o:linux:kernel 27 | 28 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 | 17 | {% include 'menu.html' %} 18 | 19 | 20 |
21 | 22 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 48 | 49 | 50 | 51 | 69 | 70 | 71 | 72 | 79 | 80 | {% if 'cwe' in cve%} 81 | {% if cve['cwe'] != 'Unknown' %} 82 | 83 | 84 | 85 | 86 | {% endif %} 87 | {% endif %} 88 | {% if 'capec' in cve%} 89 | {% if cve['cwe']|length != 0 %} 90 | 91 | 92 | 114 | 115 | {% endif %} 116 | {% endif %} 117 | {% if 'access' in cve %} 118 | 119 | 120 | 130 | 131 | {% endif %} 132 | {% if 'impact' in cve %} 133 | 134 | 135 | 145 | 146 | {% endif %} 147 | {% set keytype = ['vulnerable_configuration_cpe_2_2','impactCVSS','exploitCVSS' ,'cvss', 'capec', 'access', 'impact', 'cvss-time', 'Modified', 'Published', 'summary', 'vulnerable_configuration', 'references', '_id', 'id', 'last-modified', 'ranking', 'cwe'] %} 148 | {% for k in cve|dictsort %} 149 | {% if not k[0] in keytype %} 150 | 151 | 152 | 173 | 174 | {% endif %} 175 | {% endfor %} 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | {% if 'last-modified' in cve%} 185 | 186 | 187 | 188 | 189 | {% endif %} 190 | 191 |
ID{{ cve['id'] }}
Summary{{ cve['summary'] }}
References 40 |
41 |
    42 | {% for ref in cve['references'] %} 43 |
  • {{ ref }}
  • 44 | {% endfor %} 45 |
46 |
47 |
Vulnerable Configurations 52 |
53 |
    54 | {% for vulconf in cve['vulnerable_configuration'] %} 55 |
  • 62 | {{ vulconf['title'] }} 63 |
    {{ vulconf['id'] }}
    64 |
  • 65 | {% endfor %} 66 |
67 |
68 |
CVSS 73 | 74 | 75 | 76 | 77 |
Base: {{ cve['cvss'] }} {% if 'cvss-time' in cve %}(as of {{ cve['cvss-time']|currentTime }}){% endif %}
Impact: {{ cve['impactCVSS'] }}
Exploitability:{{ cve['exploitCVSS'] }}
78 |
CWE{{ cve['cwe'] }}
CAPEC 93 |
94 |
    95 | {% for c in cve['capec'] %} 96 |
  • 97 | {{c['name']}} 98 |
    99 | {% if c['summary']|length>1 %} 100 |
      101 | {% for s in c['summary'] %} 102 |
    • {{ s }}
    • 103 | {% endfor %} 104 |
    105 | {% else %} 106 | {{c['summary'][0]}} 107 | {% endif%} 108 |
    109 |
  • 110 | {% endfor %} 111 |
112 |
113 |
Access 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 |
VectorComplexityAuthentication
{{cve['access']['vector']}}{{cve['access']['complexity']}}{{cve['access']['authentication']}}
129 |
Impact 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 |
ConfidentialityIntegrityAvailability
{{cve['impact']['confidentiality']}}{{cve['impact']['integrity']}}{{cve['impact']['availability']}}
144 |
{{ k[0]|vFeedName }} vFeed 153 | 154 | {% for item in k[1]|dictsort %} 155 | 156 | 162 | 169 | 170 | {% endfor %} 171 |
157 | 158 | 159 | 160 | {{item[0]}} 161 | 163 | {% if item[1]|isURL%} 164 | {{ item[1] }} 165 | {% else %} 166 | {{ item[1] }} 167 | {% endif %} 168 |
172 |
Last major update{{ cve['Modified']|currentTime }}
Published{{ cve['Published']|currentTime }}
Last modified{{ cve['last-modified']|currentTime }}
192 | Back to Top 193 |
194 | 195 |
196 |
197 |
198 | 199 | 200 | -------------------------------------------------------------------------------- /lib/templates/defaultHead.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /lib/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Vulnerabilities for scanned systems 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 |
27 |
28 | 29 | {% include 'menu.html' %} 30 | 31 | 32 |
33 | 34 | 35 | 36 | 37 |
Scanned on {{scan['scan']['time']|fromEpoch}}
Scan Type {{scan['scan']['type']}}
Enhanced on{{scan['enhanced']['time']|fromEpoch}}
38 |
39 |
40 | {% if scan['systems']|length == 0 %} 41 |
42 | No hosts were scanned. 43 |
44 | {% else %} 45 | {% for sys in scan['systems'] %} 46 | {% set outer_loop = loop %} 47 |
48 | 49 | 50 | 51 | 52 | 53 | 104 | {% if sys['status']=='up'%} 105 | 106 | 107 | 114 | 115 | 116 | 117 | 185 | 186 | {% endif %} 187 |
IP {{sys['ip']}}
MAC {{sys['mac']}}
Status {{sys['status']}}
Possible CPEs 54 | {% if sys['cpes']|length == 0 %} 55 | System not recognized 56 | {% else %} 57 | {%for cpe in sys['cpes'] %} 58 |
59 | {{ cpe['cpe']|toHuman }} 60 | {% if cpe['cves']|length!=0 %} 61 | 62 | 63 | 64 | {% endif %} 65 |
66 | {% for v in cpe['cves'] %} 67 | {{v['id']}} 68 | {% if 'impact' in v %} - 69 | 70 | C 71 | I 72 | A 73 | 74 | {% endif %} 75 | {% if 'access' in v %} 76 | {% if v['access']['vector']|lower == 'local'%} 77 | 78 | {% elif v['access']['vector']|lower == 'network'%} 79 | 80 | {% elif v['access']['vector']|lower == 'adjacent_network'%} 81 | 82 | {% endif %} 83 | {% if v['access']['complexity']|lower == 'low'%} 84 | 85 | {% elif v['access']['complexity']|lower == 'medium'%} 86 | 87 | {% elif v['access']['complexity']|lower == 'high'%} 88 | 89 | {% endif %} 90 | {% endif %} 91 | {% if 'map_cve_exploitdb' in v %} 92 | 93 | {% endif %} 94 | {% if 'map_cve_msf' in v %} 95 | 96 | {% endif %} 97 |
98 | {% endfor %} 99 |
100 |
101 | {% endfor %} 102 | {% endif %} 103 |
Vendor {{sys['vendor']}}
Hostnames 108 |
    109 | {% for h in sys['hostnames'] %} 110 |
  • {{h}}
  • 111 | {% endfor %} 112 |
113 |
Distance {{sys['distance']}}
Services 118 | {% if sys['services']|length == 0 %} 119 | No services found for this host 120 | {% else %} 121 | 122 | 123 | 124 | 125 | 126 | {% for s in sys['services'] %} 127 | 128 | 129 | 133 | 134 | 135 | 142 | 143 | 144 | 180 | 181 | {% endfor %} 182 |
ServiceProductPort/ProtocolStatus
{{s['name']}} 130 | 131 | {{s['banner']|product}} 132 | port {{s['port']}}/{{s['protocol']}}{{s['state']}} 136 | {% if s['cves']|length!=0 %} 137 | 138 | 139 | 140 | {% endif %} 141 |
145 | {% for v in s['cves'] %} 146 | {{v['id']}} 147 | {% if 'impact' in v %} - 148 | 149 | C 150 | I 151 | A 152 | 153 | {% endif %} 154 | {% if 'access' in v %} 155 | {% if v['access']['vector']|lower == 'local'%} 156 | 157 | {% elif v['access']['vector']|lower == 'network'%} 158 | 159 | {% elif v['access']['vector']|lower == 'adjacent_network'%} 160 | 161 | {% endif %} 162 | 163 | {% if v['access']['complexity']|lower == 'low'%} 164 | 165 | {% elif v['access']['complexity']|lower == 'medium'%} 166 | 167 | {% elif v['access']['complexity']|lower == 'high'%} 168 | 169 | {% endif %} 170 | {% endif %} 171 | {% if 'map_cve_exploitdb' in v %} 172 | 173 | {% endif %} 174 | {% if 'map_cve_msf' in v %} 175 | 176 | {% endif %} 177 |
178 | {% endfor %} 179 |
183 | {% endif %} 184 |
188 |
189 | {% endfor %} 190 | {% endif %} 191 | 192 |
193 |
194 |
195 |
196 | 197 | 198 | -------------------------------------------------------------------------------- /lib/templates/menu.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NorthernSec/CVE-Scan/cf919a67b156fef057835cdde0951e527c486a62/lib/templates/menu.html -------------------------------------------------------------------------------- /lib/templates/pdf.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Vulnerabilities for scanned systems 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Scan Info 13 |
14 | 15 | 16 | 17 | 18 |
Scanned on {{scan['time']}}
Scan Type {{scan['type']}}
Enhanced on{{enhanced['time']}}
19 |
20 | System List 21 | {% if systems|length == 0 %} 22 |
No hosts were scanned.
23 | {% else %} 24 | {% for sys in systems %} 25 | 26 | 27 | 28 | 29 | 30 | 44 | 45 | {% if sys['status']=='up'%} 46 | 47 | 48 | 53 | 54 | 55 | 56 | 78 | 79 | {% endif %} 80 |
IP {{sys['ip']}}
MAC {{sys['mac']}}
Status {{sys['status']}}
Possible CPEs 31 | {% if sys['cpes']|length == 0 %} 32 | System not recognized 33 | {% else %} 34 |
    35 | {%for cpe in sys['cpes'] %} 36 |
  • {{ cpe['cpe'] }} 37 | {% if "appendix" in cpe %} 38 | * Vulns in Appendix {{ cpe["appendix"] }} 39 | {% endif %}
  • 40 | {% endfor %} 41 |
42 | {% endif %} 43 |
Vendor {{sys['vendor']}}
Hostnames 49 |
    50 | {% for h in sys['hostnames'] %}
  • {{h}}
  • {% endfor %} 51 |
52 |
Distance {{sys['distance']}}
Services 57 | {% if sys['services']|length == 0 %} 58 | No services found for this host 59 | {% else %} 60 | 61 | 62 | 63 | 64 | {% for s in sys['services'] %} 65 | 66 | 67 | 68 | 69 | 70 | 73 | 74 | {% endfor %} 75 |
ServiceProductPort/ProtocolStatusAppendix
{{s['name']}}{{s['banner']}}port {{s['port']}}/{{s['protocol']}}{{s['state']}} 71 | {% if "appendix" in s %} {{ s["appendix"] }} {% endif %} 72 |
76 | {% endif %} 77 |
81 | {% endfor %} 82 | {% if appendixes %} 83 | {% for appendix in appendixes %} 84 |

85 |

Appendix {{ loop.index }}

86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | {% for cve in appendix %} 99 | 100 | 101 | {% if "impact" in cve %} 102 | 103 | 104 | 105 | {% else %} 106 | 107 | {% endif %} 108 | {% if "access" in cve %} 109 | 110 | 111 | 112 | {% else %} 113 | 114 | {% endif %} 115 | {% if "map_cve_exploitdb" in cve %} {% else %}{% endif %} 116 | {% if "map_cve_msf" in cve %} {% else %}{% endif %} 117 | 118 | {% endfor %} 119 |
CVE
Confidentiality
Integrity
Availability
Complexity
Authentication
Vector
Exploit DB
MSF
{{ cve["id"] }}{{ cve["impact"]["confidentiality"][0] }}{{ cve["impact"]["integrity"][0] }}{{ cve["impact"]["availability"][0] }}???{{ cve["access"]["complexity"][0] }}{{ cve["access"]["authentication"][0] }}{{ cve["access"]["vector"][0] }}???xx
120 |
121 | 122 | 123 | 124 | 132 | 133 | 134 | 154 | 155 |
Impact 125 |
126 | Confidentiality, Integrity & Availability
127 |
[N]
None
128 |
[P]
Partial
129 |
[C]
Complete
130 |
131 |
Access 135 |
136 | Complexity
137 |
[L]
Low
138 |
[M]
Medium
139 |
[H]
High
140 |
141 |
142 | Authentication
143 |
[N]
None
144 |
[S]
Single Instance
145 |
[M]
Multiple Instances
146 |
147 |
148 | Vector
149 |
[L]
Local
150 |
[A]
Ajecent Network
151 |
[N]
Network
152 |
153 |
156 |
157 | {% endfor %} 158 | {% endif %} 159 | {% endif %} 160 | 161 | 162 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, NorthernSec 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 1. Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | 3. All advertising materials mentioning features or use of this software 12 | must display the following acknowledgement: 13 | This product includes software developed by the NorthernSec. 14 | 4. Neither the name of the NorthernSec organisation nor the 15 | names of its contributors may be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY NorthernSec ''AS IS'' AND ANY 19 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL NorthernSec BE LIABLE FOR ANY 22 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # this should already be installed 2 | PyMongo 3 | python-dateutil 4 | flask 5 | flask-pymongo 6 | 7 | # new dependencies 8 | git+git://github.com/savon-noir/python-libnmap 9 | git+git://github.com/pidgeyl/specter 10 | 11 | weasyprint 12 | --------------------------------------------------------------------------------