├── harvester ├── __init__.py └── core.py ├── py-scripts ├── __init__.py └── vgluware.py ├── samples ├── 102018 │ ├── txt │ │ ├── Glue Networks.txt │ │ ├── Continents_top.txt │ │ ├── Fatpipe.txt │ │ ├── Viprinet.txt │ │ ├── Huawei.txt │ │ ├── Sonus .txt │ │ ├── VMWare.txt │ │ ├── Versa.txt │ │ ├── Arista.txt │ │ ├── Barracuda Networks.txt │ │ ├── Cisco.txt │ │ ├── Citrix.txt │ │ ├── Nuage.txt │ │ ├── Talari.txt │ │ ├── Riverbed.txt │ │ ├── Silver Peak Systems.txt │ │ ├── Vulnerabilities_top.txt │ │ ├── Products_top.txt │ │ ├── Result_top.txt │ │ └── Countries_top.txt │ ├── png │ │ ├── Arista.png │ │ ├── Cisco.png │ │ ├── Citrix.png │ │ ├── Huawei.png │ │ ├── Nuage.png │ │ ├── Sonus .png │ │ ├── Talari.png │ │ ├── VMWare.png │ │ ├── Versa.png │ │ ├── Fatpipe.png │ │ ├── Products.png │ │ ├── Riverbed.png │ │ ├── Vendors.png │ │ ├── Viprinet.png │ │ ├── Continents.png │ │ ├── Countries.png │ │ ├── Glue Networks.png │ │ ├── Vulnerabilities.png │ │ ├── Barracuda Networks.png │ │ └── Silver Peak Systems.png │ └── map │ │ ├── maps │ │ ├── images │ │ │ ├── pin24.png │ │ │ └── pin48.png │ │ └── leaf-demo.js │ │ └── index.html └── 112018 │ ├── png │ ├── Arista.png │ ├── Cisco.png │ ├── Citrix.png │ ├── Huawei.png │ ├── Nuage.png │ ├── Sonus .png │ ├── Talari.png │ ├── VMWare.png │ ├── Versa.png │ ├── Fatpipe.png │ ├── Fortinet.png │ ├── Products.png │ ├── Riverbed.png │ ├── Vendors.png │ ├── Viprinet.png │ ├── Continents.png │ ├── Countries.png │ ├── Cradlepoint.png │ ├── Glue Networks.png │ ├── Vulnerabilities.png │ ├── Barracuda Networks.png │ └── Silver Peak Systems.png │ ├── map │ ├── maps │ │ ├── images │ │ │ ├── pin24.png │ │ │ └── pin48.png │ │ └── leaf-demo.js │ └── index.html │ └── txt │ ├── Fatpipe.txt │ ├── Glue Networks.txt │ ├── Continents_top.txt │ ├── Versa.txt │ ├── Fortinet.txt │ ├── Huawei.txt │ ├── Arista.txt │ ├── Cradlepoint.txt │ ├── Sonus .txt │ ├── Viprinet.txt │ ├── Barracuda Networks.txt │ ├── Citrix.txt │ ├── Talari.txt │ ├── VMWare.txt │ ├── Nuage.txt │ ├── Riverbed.txt │ ├── Cisco.txt │ ├── Products_top.txt │ ├── Silver Peak Systems.txt │ ├── Vulnerabilities_top.txt │ ├── Result_top.txt │ └── Countries_top.txt ├── map ├── maps │ ├── images │ │ ├── pin24.png │ │ └── pin48.png │ └── leaf-demo.js └── index.html ├── .gitignore ├── requirements.txt ├── nse-scripts ├── vsilverpeak.nse ├── vriverbed.nse ├── vnuage.nse ├── vtalari.nse ├── vfatpipe.nse ├── vvmware_nsx.nse ├── vcitrix.nse ├── vsonus_edge.nse ├── vversa_flex.nse ├── vsonus_mgmt.nse ├── vcradlepoint.nse ├── vbrain.nse ├── vversa_analytics.nse ├── vversa_analytics_server.nse └── vfortinet.nse ├── harvester.py ├── README.md ├── shodan_queries.json └── LICENSE /harvester/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /py-scripts/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /samples/102018/txt/Glue Networks.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2017-15906, found - 6 2 | -------------------------------------------------------------------------------- /map/maps/images/pin24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/map/maps/images/pin24.png -------------------------------------------------------------------------------- /map/maps/images/pin48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/map/maps/images/pin48.png -------------------------------------------------------------------------------- /samples/102018/png/Arista.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/Arista.png -------------------------------------------------------------------------------- /samples/102018/png/Cisco.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/Cisco.png -------------------------------------------------------------------------------- /samples/102018/png/Citrix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/Citrix.png -------------------------------------------------------------------------------- /samples/102018/png/Huawei.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/Huawei.png -------------------------------------------------------------------------------- /samples/102018/png/Nuage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/Nuage.png -------------------------------------------------------------------------------- /samples/102018/png/Sonus .png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/Sonus .png -------------------------------------------------------------------------------- /samples/102018/png/Talari.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/Talari.png -------------------------------------------------------------------------------- /samples/102018/png/VMWare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/VMWare.png -------------------------------------------------------------------------------- /samples/102018/png/Versa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/Versa.png -------------------------------------------------------------------------------- /samples/112018/png/Arista.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Arista.png -------------------------------------------------------------------------------- /samples/112018/png/Cisco.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Cisco.png -------------------------------------------------------------------------------- /samples/112018/png/Citrix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Citrix.png -------------------------------------------------------------------------------- /samples/112018/png/Huawei.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Huawei.png -------------------------------------------------------------------------------- /samples/112018/png/Nuage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Nuage.png -------------------------------------------------------------------------------- /samples/112018/png/Sonus .png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Sonus .png -------------------------------------------------------------------------------- /samples/112018/png/Talari.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Talari.png -------------------------------------------------------------------------------- /samples/112018/png/VMWare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/VMWare.png -------------------------------------------------------------------------------- /samples/112018/png/Versa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Versa.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | results 3 | harvester/.env 4 | harvester/results 5 | harvester/__pycache__ 6 | py-scripts/__pycache__ -------------------------------------------------------------------------------- /samples/102018/png/Fatpipe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/Fatpipe.png -------------------------------------------------------------------------------- /samples/102018/png/Products.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/Products.png -------------------------------------------------------------------------------- /samples/102018/png/Riverbed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/Riverbed.png -------------------------------------------------------------------------------- /samples/102018/png/Vendors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/Vendors.png -------------------------------------------------------------------------------- /samples/102018/png/Viprinet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/Viprinet.png -------------------------------------------------------------------------------- /samples/112018/png/Fatpipe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Fatpipe.png -------------------------------------------------------------------------------- /samples/112018/png/Fortinet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Fortinet.png -------------------------------------------------------------------------------- /samples/112018/png/Products.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Products.png -------------------------------------------------------------------------------- /samples/112018/png/Riverbed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Riverbed.png -------------------------------------------------------------------------------- /samples/112018/png/Vendors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Vendors.png -------------------------------------------------------------------------------- /samples/112018/png/Viprinet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Viprinet.png -------------------------------------------------------------------------------- /samples/102018/png/Continents.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/Continents.png -------------------------------------------------------------------------------- /samples/102018/png/Countries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/Countries.png -------------------------------------------------------------------------------- /samples/112018/png/Continents.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Continents.png -------------------------------------------------------------------------------- /samples/112018/png/Countries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Countries.png -------------------------------------------------------------------------------- /samples/112018/png/Cradlepoint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Cradlepoint.png -------------------------------------------------------------------------------- /samples/102018/png/Glue Networks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/Glue Networks.png -------------------------------------------------------------------------------- /samples/112018/png/Glue Networks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Glue Networks.png -------------------------------------------------------------------------------- /samples/102018/png/Vulnerabilities.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/Vulnerabilities.png -------------------------------------------------------------------------------- /samples/112018/png/Vulnerabilities.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Vulnerabilities.png -------------------------------------------------------------------------------- /samples/102018/map/maps/images/pin24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/map/maps/images/pin24.png -------------------------------------------------------------------------------- /samples/102018/map/maps/images/pin48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/map/maps/images/pin48.png -------------------------------------------------------------------------------- /samples/102018/png/Barracuda Networks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/Barracuda Networks.png -------------------------------------------------------------------------------- /samples/112018/map/maps/images/pin24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/map/maps/images/pin24.png -------------------------------------------------------------------------------- /samples/112018/map/maps/images/pin48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/map/maps/images/pin48.png -------------------------------------------------------------------------------- /samples/112018/png/Barracuda Networks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Barracuda Networks.png -------------------------------------------------------------------------------- /samples/102018/png/Silver Peak Systems.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/102018/png/Silver Peak Systems.png -------------------------------------------------------------------------------- /samples/112018/png/Silver Peak Systems.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdnewhop/sdwan-harvester/HEAD/samples/112018/png/Silver Peak Systems.png -------------------------------------------------------------------------------- /samples/112018/txt/Fatpipe.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2017-15906, found - 34 2 | Vulnerability: CVE-2018-15473, found - 33 3 | Vulnerability: CWE-798, found - 24 4 | Vulnerability: CVE-2018-15919, found - 16 5 | Vulnerability: CVE-2016-8858, found - 4 6 | -------------------------------------------------------------------------------- /samples/112018/txt/Glue Networks.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2018-15473, found - 14 2 | Vulnerability: CVE-2017-15906, found - 14 3 | Vulnerability: CVE-2018-15919, found - 6 4 | Vulnerability: CVE-2016-8612, found - 1 5 | Vulnerability: CVE-2017-9798, found - 1 6 | -------------------------------------------------------------------------------- /samples/102018/txt/Continents_top.txt: -------------------------------------------------------------------------------- 1 | Continent: North America, found - 1300 2 | Continent: Europe, found - 456 3 | Continent: Oceania, found - 74 4 | Continent: Asia, found - 313 5 | Continent: Africa, found - 87 6 | Continent: South and Central America, found - 29 7 | -------------------------------------------------------------------------------- /samples/102018/txt/Fatpipe.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2017-15906, found - 30 2 | Vulnerability: CWE-798, found - 19 3 | Vulnerability: CVE-2016-8858, found - 5 4 | Vulnerability: CVE-2016-0777, found - 1 5 | Vulnerability: CVE-2016-0778, found - 1 6 | Vulnerability: CVE-2016-10708, found - 1 7 | -------------------------------------------------------------------------------- /samples/112018/txt/Continents_top.txt: -------------------------------------------------------------------------------- 1 | Continent: North America, found - 4905 2 | Continent: Europe, found - 2950 3 | Continent: Oceania, found - 456 4 | Continent: Asia, found - 1407 5 | Continent: Africa, found - 292 6 | Continent: South and Central America, found - 108 7 | Continent: Asia/Pacific Region, found - 1 8 | -------------------------------------------------------------------------------- /samples/102018/txt/Viprinet.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CWE-798, found - 35 2 | Vulnerability: CVE-2017-15906, found - 2 3 | Vulnerability: CVE-2010-1256, found - 1 4 | Vulnerability: CVE-2010-2730, found - 1 5 | Vulnerability: CVE-2010-3972, found - 1 6 | Vulnerability: CVE-2010-1899, found - 1 7 | Vulnerability: CVE-2012-2531, found - 1 8 | -------------------------------------------------------------------------------- /samples/112018/txt/Versa.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CWE-798, found - 7 2 | Vulnerability: CVE-2017-15710, found - 6 3 | Vulnerability: CVE-2017-7679, found - 6 4 | Vulnerability: CVE-2017-9788, found - 6 5 | Vulnerability: CVE-2016-0736, found - 6 6 | Vulnerability: CVE-2018-1283, found - 6 7 | Vulnerability: CVE-2017-9798, found - 6 8 | Vulnerability: CVE-2016-8743, found - 6 9 | Vulnerability: CVE-2016-4975, found - 6 10 | Vulnerability: CVE-2018-1312, found - 6 11 | -------------------------------------------------------------------------------- /samples/102018/txt/Huawei.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2014-0117, found - 3 2 | Vulnerability: CVE-2014-0118, found - 3 3 | Vulnerability: CVE-2016-0736, found - 3 4 | Vulnerability: CVE-2015-3185, found - 3 5 | Vulnerability: CVE-2015-3184, found - 3 6 | Vulnerability: CVE-2018-1312, found - 3 7 | Vulnerability: CVE-2016-8612, found - 3 8 | Vulnerability: CVE-2014-0226, found - 3 9 | Vulnerability: CVE-2014-3523, found - 3 10 | Vulnerability: CVE-2017-15710, found - 3 11 | -------------------------------------------------------------------------------- /samples/102018/txt/Sonus .txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2017-15906, found - 5 2 | Vulnerability: CVE-2017-15710, found - 4 3 | Vulnerability: CVE-2016-8612, found - 4 4 | Vulnerability: CVE-2017-7679, found - 4 5 | Vulnerability: CVE-2017-9788, found - 4 6 | Vulnerability: CVE-2016-0736, found - 4 7 | Vulnerability: CVE-2014-3583, found - 4 8 | Vulnerability: CVE-2014-8109, found - 4 9 | Vulnerability: CVE-2018-1283, found - 4 10 | Vulnerability: CVE-2015-3185, found - 4 11 | -------------------------------------------------------------------------------- /samples/102018/txt/VMWare.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2016-8858, found - 31 2 | Vulnerability: CVE-2017-15906, found - 8 3 | Vulnerability: CVE-2016-10708, found - 8 4 | Vulnerability: CVE-2016-0777, found - 8 5 | Vulnerability: CVE-2014-1692, found - 6 6 | Vulnerability: CVE-2010-5107, found - 6 7 | Vulnerability: CVE-2011-5000, found - 5 8 | Vulnerability: CVE-2010-4478, found - 5 9 | Vulnerability: CVE-2011-4327, found - 5 10 | Vulnerability: CVE-2010-4755, found - 5 11 | -------------------------------------------------------------------------------- /samples/102018/txt/Versa.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2018-1053, found - 3 2 | Vulnerability: CVE-2018-1115, found - 3 3 | Vulnerability: CVE-2017-7548, found - 3 4 | Vulnerability: CVE-2018-1058, found - 3 5 | Vulnerability: CVE-2017-12172, found - 3 6 | Vulnerability: CVE-2017-7484, found - 3 7 | Vulnerability: CVE-2017-7485, found - 3 8 | Vulnerability: CVE-2017-7486, found - 3 9 | Vulnerability: CVE-2017-7547, found - 3 10 | Vulnerability: CVE-2017-7546, found - 3 11 | -------------------------------------------------------------------------------- /samples/112018/txt/Fortinet.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2016-4975, found - 2 2 | Vulnerability: CVE-2016-8612, found - 2 3 | Vulnerability: CVE-2013-6438, found - 2 4 | Vulnerability: CVE-2017-7679, found - 2 5 | Vulnerability: CVE-2014-0231, found - 2 6 | Vulnerability: CVE-2014-0098, found - 2 7 | Vulnerability: CVE-2014-0117, found - 1 8 | Vulnerability: CVE-2014-0118, found - 1 9 | Vulnerability: CVE-2016-0736, found - 1 10 | Vulnerability: CVE-2015-3185, found - 1 11 | -------------------------------------------------------------------------------- /samples/112018/txt/Huawei.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2014-0117, found - 1 2 | Vulnerability: CVE-2017-15906, found - 1 3 | Vulnerability: CVE-2014-0118, found - 1 4 | Vulnerability: CVE-2016-0736, found - 1 5 | Vulnerability: CVE-2015-3185, found - 1 6 | Vulnerability: CVE-2015-3184, found - 1 7 | Vulnerability: CVE-2018-1312, found - 1 8 | Vulnerability: CVE-2016-4975, found - 1 9 | Vulnerability: CVE-2016-8612, found - 1 10 | Vulnerability: CVE-2014-0226, found - 1 11 | -------------------------------------------------------------------------------- /samples/102018/txt/Arista.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CWE-798, found - 456 2 | Vulnerability: CVE-2011-5000, found - 28 3 | Vulnerability: CVE-2017-15906, found - 28 4 | Vulnerability: CVE-2014-1692, found - 28 5 | Vulnerability: CVE-2010-5107, found - 28 6 | Vulnerability: CVE-2016-10708, found - 28 7 | Vulnerability: CVE-2010-4478, found - 28 8 | Vulnerability: CVE-2016-0777, found - 28 9 | Vulnerability: CVE-2011-4327, found - 28 10 | Vulnerability: CVE-2010-4755, found - 28 11 | -------------------------------------------------------------------------------- /samples/102018/txt/Barracuda Networks.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2008-1446, found - 3 2 | Vulnerability: CVE-2009-2521, found - 3 3 | Vulnerability: CVE-2010-1899, found - 3 4 | Vulnerability: CVE-2010-1256, found - 3 5 | Vulnerability: CVE-2009-1535, found - 2 6 | Vulnerability: CVE-2009-4444, found - 2 7 | Vulnerability: CVE-2009-3023, found - 2 8 | Vulnerability: CVE-2009-3555, found - 1 9 | Vulnerability: CVE-2008-0074, found - 1 10 | Vulnerability: MS17-010, found - 1 11 | -------------------------------------------------------------------------------- /samples/112018/txt/Arista.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CWE-798, found - 538 2 | Vulnerability: CVE-2011-5000, found - 34 3 | Vulnerability: CVE-2017-15906, found - 34 4 | Vulnerability: CVE-2014-1692, found - 34 5 | Vulnerability: CVE-2010-5107, found - 34 6 | Vulnerability: CVE-2016-10708, found - 34 7 | Vulnerability: CVE-2010-4478, found - 34 8 | Vulnerability: CVE-2016-0777, found - 34 9 | Vulnerability: CVE-2011-4327, found - 34 10 | Vulnerability: CVE-2010-4755, found - 34 11 | -------------------------------------------------------------------------------- /samples/112018/txt/Cradlepoint.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2010-1256, found - 3 2 | Vulnerability: CVE-2010-2730, found - 3 3 | Vulnerability: CVE-2010-3972, found - 3 4 | Vulnerability: CVE-2010-1899, found - 3 5 | Vulnerability: CVE-2012-2531, found - 3 6 | Vulnerability: CVE-2016-10708, found - 1 7 | Vulnerability: CVE-2016-0777, found - 1 8 | Vulnerability: CVE-2016-0778, found - 1 9 | Vulnerability: CVE-2018-15473, found - 1 10 | Vulnerability: CVE-2017-15906, found - 1 11 | -------------------------------------------------------------------------------- /samples/112018/txt/Sonus .txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2017-15906, found - 11 2 | Vulnerability: CVE-2018-15473, found - 11 3 | Vulnerability: CVE-2017-15710, found - 7 4 | Vulnerability: CVE-2016-8612, found - 7 5 | Vulnerability: CVE-2017-7679, found - 7 6 | Vulnerability: CVE-2017-9788, found - 7 7 | Vulnerability: CVE-2016-0736, found - 7 8 | Vulnerability: CVE-2014-3583, found - 7 9 | Vulnerability: CVE-2014-8109, found - 7 10 | Vulnerability: CVE-2018-1283, found - 7 11 | -------------------------------------------------------------------------------- /samples/112018/txt/Viprinet.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CWE-798, found - 114 2 | Vulnerability: CVE-2017-15906, found - 81 3 | Vulnerability: CVE-2018-15473, found - 79 4 | Vulnerability: CVE-2018-15919, found - 36 5 | Vulnerability: CVE-2010-1256, found - 9 6 | Vulnerability: CVE-2010-2730, found - 9 7 | Vulnerability: CVE-2010-3972, found - 9 8 | Vulnerability: CVE-2010-1899, found - 9 9 | Vulnerability: CVE-2012-2531, found - 9 10 | Vulnerability: CVE-2018-1312, found - 5 11 | -------------------------------------------------------------------------------- /samples/102018/txt/Cisco.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2017-15906, found - 20 2 | Vulnerability: CVE-2016-8858, found - 18 3 | Vulnerability: CVE-2016-10708, found - 18 4 | Vulnerability: CVE-2016-10011, found - 16 5 | Vulnerability: CVE-2016-10010, found - 16 6 | Vulnerability: CVE-2016-10012, found - 16 7 | Vulnerability: CVE-2016-10009, found - 16 8 | Vulnerability: CVE-2016-1907, found - 2 9 | Vulnerability: CVE-2016-0777, found - 2 10 | Vulnerability: CVE-2016-0778, found - 2 11 | -------------------------------------------------------------------------------- /samples/102018/txt/Citrix.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2017-7679, found - 61 2 | Vulnerability: CVE-2012-4558, found - 61 3 | Vulnerability: CVE-2013-1896, found - 61 4 | Vulnerability: CVE-2016-8612, found - 61 5 | Vulnerability: CVE-2013-5704, found - 61 6 | Vulnerability: CVE-2017-7668, found - 61 7 | Vulnerability: CVE-2013-6438, found - 61 8 | Vulnerability: CVE-2012-2687, found - 61 9 | Vulnerability: CVE-2012-3499, found - 61 10 | Vulnerability: CVE-2013-2249, found - 61 11 | -------------------------------------------------------------------------------- /samples/102018/txt/Nuage.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2017-15906, found - 31 2 | Vulnerability: CVE-2014-0117, found - 24 3 | Vulnerability: CVE-2014-0118, found - 24 4 | Vulnerability: CVE-2016-0736, found - 24 5 | Vulnerability: CVE-2015-3185, found - 24 6 | Vulnerability: CVE-2015-3184, found - 24 7 | Vulnerability: CVE-2018-1312, found - 24 8 | Vulnerability: CVE-2016-8612, found - 24 9 | Vulnerability: CVE-2014-0226, found - 24 10 | Vulnerability: CVE-2014-3523, found - 24 11 | -------------------------------------------------------------------------------- /samples/102018/txt/Talari.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2017-7668, found - 44 2 | Vulnerability: CVE-2017-3167, found - 44 3 | Vulnerability: CVE-2017-3169, found - 44 4 | Vulnerability: CVE-2017-7679, found - 44 5 | Vulnerability: CVE-2016-8612, found - 44 6 | Vulnerability: CVE-2017-15710, found - 35 7 | Vulnerability: CVE-2017-9788, found - 35 8 | Vulnerability: CVE-2018-1283, found - 35 9 | Vulnerability: CVE-2017-9798, found - 35 10 | Vulnerability: CVE-2016-8743, found - 35 11 | -------------------------------------------------------------------------------- /samples/112018/txt/Barracuda Networks.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2016-8612, found - 2 2 | Vulnerability: CVE-2017-7679, found - 2 3 | Vulnerability: CVE-2016-4975, found - 2 4 | Vulnerability: CVE-2017-3167, found - 2 5 | Vulnerability: CVE-2017-7668, found - 2 6 | Vulnerability: CVE-2017-3169, found - 2 7 | Vulnerability: CVE-2010-1256, found - 2 8 | Vulnerability: CVE-2010-1899, found - 2 9 | Vulnerability: CVE-2009-2521, found - 2 10 | Vulnerability: CVE-2009-1535, found - 2 11 | -------------------------------------------------------------------------------- /samples/112018/txt/Citrix.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2012-4558, found - 82 2 | Vulnerability: CVE-2013-1896, found - 82 3 | Vulnerability: CVE-2012-3499, found - 82 4 | Vulnerability: CVE-2014-0231, found - 82 5 | Vulnerability: CVE-2017-7679, found - 82 6 | Vulnerability: CVE-2013-2249, found - 82 7 | Vulnerability: CVE-2013-5704, found - 82 8 | Vulnerability: CVE-2017-7668, found - 82 9 | Vulnerability: CVE-2013-6438, found - 82 10 | Vulnerability: CVE-2012-2687, found - 82 11 | -------------------------------------------------------------------------------- /samples/112018/txt/Talari.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2016-8612, found - 50 2 | Vulnerability: CVE-2017-7679, found - 50 3 | Vulnerability: CVE-2017-3167, found - 50 4 | Vulnerability: CVE-2017-7668, found - 50 5 | Vulnerability: CVE-2017-3169, found - 50 6 | Vulnerability: CVE-2016-4975, found - 48 7 | Vulnerability: CVE-2017-15710, found - 41 8 | Vulnerability: CVE-2017-9788, found - 41 9 | Vulnerability: CVE-2018-1283, found - 41 10 | Vulnerability: CVE-2017-9798, found - 41 11 | -------------------------------------------------------------------------------- /samples/112018/txt/VMWare.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2016-8858, found - 75 2 | Vulnerability: CVE-2017-15906, found - 23 3 | Vulnerability: CVE-2016-10708, found - 23 4 | Vulnerability: CVE-2016-0777, found - 23 5 | Vulnerability: CVE-2018-15473, found - 22 6 | Vulnerability: CVE-2014-1692, found - 20 7 | Vulnerability: CVE-2010-5107, found - 20 8 | Vulnerability: CVE-2011-5000, found - 17 9 | Vulnerability: CVE-2010-4478, found - 17 10 | Vulnerability: CVE-2011-4327, found - 17 11 | -------------------------------------------------------------------------------- /samples/102018/txt/Riverbed.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2017-15906, found - 433 2 | Vulnerability: CVE-2016-10708, found - 302 3 | Vulnerability: CVE-2016-8858, found - 255 4 | Vulnerability: CVE-2016-0777, found - 166 5 | Vulnerability: CVE-2016-0778, found - 164 6 | Vulnerability: CWE-798, found - 157 7 | Vulnerability: CVE-2016-10011, found - 136 8 | Vulnerability: CVE-2016-10010, found - 136 9 | Vulnerability: CVE-2016-10012, found - 136 10 | Vulnerability: CVE-2016-10009, found - 136 11 | -------------------------------------------------------------------------------- /samples/112018/txt/Nuage.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2018-1312, found - 146 2 | Vulnerability: CVE-2016-8612, found - 146 3 | Vulnerability: CVE-2017-15710, found - 146 4 | Vulnerability: CVE-2017-15715, found - 146 5 | Vulnerability: CVE-2017-7679, found - 146 6 | Vulnerability: CVE-2017-9788, found - 146 7 | Vulnerability: CVE-2017-9798, found - 146 8 | Vulnerability: CVE-2018-1283, found - 146 9 | Vulnerability: CVE-2016-8743, found - 146 10 | Vulnerability: CVE-2014-0117, found - 144 11 | -------------------------------------------------------------------------------- /samples/112018/txt/Riverbed.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2017-15906, found - 966 2 | Vulnerability: CVE-2018-15473, found - 923 3 | Vulnerability: CVE-2016-10708, found - 709 4 | Vulnerability: CVE-2016-8858, found - 546 5 | Vulnerability: CVE-2018-15919, found - 459 6 | Vulnerability: CVE-2016-0777, found - 401 7 | Vulnerability: CWE-798, found - 401 8 | Vulnerability: CVE-2016-0778, found - 383 9 | Vulnerability: CVE-2016-10011, found - 307 10 | Vulnerability: CVE-2016-10010, found - 307 11 | -------------------------------------------------------------------------------- /samples/102018/txt/Silver Peak Systems.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2011-5000, found - 43 2 | Vulnerability: CVE-2017-15906, found - 43 3 | Vulnerability: CVE-2014-1692, found - 43 4 | Vulnerability: CVE-2010-5107, found - 43 5 | Vulnerability: CVE-2016-10708, found - 43 6 | Vulnerability: CVE-2010-4478, found - 43 7 | Vulnerability: CVE-2016-0777, found - 43 8 | Vulnerability: CVE-2011-4327, found - 43 9 | Vulnerability: CVE-2010-4755, found - 43 10 | Vulnerability: CVE-2012-0814, found - 43 11 | -------------------------------------------------------------------------------- /samples/112018/txt/Cisco.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2017-15906, found - 204 2 | Vulnerability: CVE-2018-15473, found - 196 3 | Vulnerability: CVE-2016-8858, found - 183 4 | Vulnerability: CVE-2016-10708, found - 183 5 | Vulnerability: CVE-2016-10011, found - 177 6 | Vulnerability: CVE-2016-10010, found - 177 7 | Vulnerability: CVE-2016-10012, found - 177 8 | Vulnerability: CVE-2016-10009, found - 177 9 | Vulnerability: CVE-2018-15919, found - 92 10 | Vulnerability: CVE-2016-1907, found - 6 11 | -------------------------------------------------------------------------------- /samples/102018/txt/Vulnerabilities_top.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CWE-798, found - 683 2 | Vulnerability: CVE-2017-15906, found - 626 3 | Vulnerability: CVE-2016-10708, found - 424 4 | Vulnerability: CVE-2016-8858, found - 353 5 | Vulnerability: CVE-2016-0777, found - 268 6 | Vulnerability: CVE-2016-0778, found - 203 7 | Vulnerability: CVE-2014-1692, found - 160 8 | Vulnerability: CVE-2010-5107, found - 159 9 | Vulnerability: CVE-2016-10011, found - 154 10 | Vulnerability: CVE-2016-10010, found - 154 11 | -------------------------------------------------------------------------------- /samples/102018/txt/Products_top.txt: -------------------------------------------------------------------------------- 1 | Product: Riverbed SteelHead, found - 493 2 | Product: VMWare VeloCloud, found - 452 3 | Product: Arista Networks EOS, found - 255 4 | Product: Sonus SBC Edge, found - 188 5 | Product: Silver Peak Systems Unity Orchestrator, found - 168 6 | Product: Fatpipe SYMPHONY SD-WAN, found - 166 7 | Product: Versa Flex, found - 104 8 | Product: Viprinet Virtual VPN Hub, found - 68 9 | Product: Nuage Networks SD-WAN (VNS), found - 67 10 | Product: Versa Director, found - 67 11 | -------------------------------------------------------------------------------- /samples/112018/txt/Products_top.txt: -------------------------------------------------------------------------------- 1 | Product: VMWare VeloCloud, found - 1469 2 | Product: Viprinet Virtual VPN Hub, found - 1065 3 | Product: Riverbed SteelHead, found - 847 4 | Product: Silver Peak Unity EdgeConnect, found - 595 5 | Product: Cradlepoint SD-WAN, found - 431 6 | Product: Cisco SD-WAN, found - 402 7 | Product: Sonus SBC Edge, found - 306 8 | Product: Arista Networks EOS, found - 274 9 | Product: Fatpipe SYMPHONY SD-WAN, found - 265 10 | Product: Nuage Networks SD-WAN (VNS), found - 258 11 | -------------------------------------------------------------------------------- /samples/112018/txt/Silver Peak Systems.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2017-15906, found - 252 2 | Vulnerability: CVE-2011-5000, found - 248 3 | Vulnerability: CVE-2014-1692, found - 248 4 | Vulnerability: CVE-2010-5107, found - 248 5 | Vulnerability: CVE-2016-10708, found - 248 6 | Vulnerability: CVE-2010-4478, found - 248 7 | Vulnerability: CVE-2011-4327, found - 248 8 | Vulnerability: CVE-2010-4755, found - 248 9 | Vulnerability: CVE-2012-0814, found - 248 10 | Vulnerability: CVE-2016-0777, found - 246 11 | -------------------------------------------------------------------------------- /samples/112018/txt/Vulnerabilities_top.txt: -------------------------------------------------------------------------------- 1 | Vulnerability: CVE-2017-15906, found - 1733 2 | Vulnerability: CVE-2018-15473, found - 1667 3 | Vulnerability: CVE-2016-10708, found - 1251 4 | Vulnerability: CWE-798, found - 1154 5 | Vulnerability: CVE-2016-8858, found - 852 6 | Vulnerability: CVE-2016-0777, found - 758 7 | Vulnerability: CVE-2018-15919, found - 653 8 | Vulnerability: CVE-2014-1692, found - 515 9 | Vulnerability: CVE-2010-5107, found - 514 10 | Vulnerability: CVE-2016-10011, found - 486 11 | -------------------------------------------------------------------------------- /samples/102018/txt/Result_top.txt: -------------------------------------------------------------------------------- 1 | Vendor: Riverbed Found unique pairs (hosts + port): 520 2 | Vendor: VMWare Found unique pairs (hosts + port): 452 3 | Vendor: Arista Found unique pairs (hosts + port): 255 4 | Vendor: Sonus Found unique pairs (hosts + port): 240 5 | Vendor: Silver Peak Systems Found unique pairs (hosts + port): 234 6 | Vendor: Versa Found unique pairs (hosts + port): 203 7 | Vendor: Fatpipe Found unique pairs (hosts + port): 166 8 | Vendor: Viprinet Found unique pairs (hosts + port): 68 9 | Vendor: Nuage Found unique pairs (hosts + port): 67 10 | Vendor: Cisco Found unique pairs (hosts + port): 60 11 | -------------------------------------------------------------------------------- /samples/112018/txt/Result_top.txt: -------------------------------------------------------------------------------- 1 | Vendor: VMWare Found unique pairs (hosts + port): 1469 2 | Vendor: Viprinet Found unique pairs (hosts + port): 1065 3 | Vendor: Riverbed Found unique pairs (hosts + port): 899 4 | Vendor: Silver Peak Systems Found unique pairs (hosts + port): 770 5 | Vendor: Versa Found unique pairs (hosts + port): 481 6 | Vendor: Cradlepoint Found unique pairs (hosts + port): 431 7 | Vendor: Sonus Found unique pairs (hosts + port): 421 8 | Vendor: Cisco Found unique pairs (hosts + port): 402 9 | Vendor: Arista Found unique pairs (hosts + port): 274 10 | Vendor: Fatpipe Found unique pairs (hosts + port): 265 11 | -------------------------------------------------------------------------------- /samples/102018/txt/Countries_top.txt: -------------------------------------------------------------------------------- 1 | Country: United States, found - 1247 2 | Country: United Kingdom, found - 120 3 | Country: Netherlands, found - 75 4 | Country: Australia, found - 72 5 | Country: Germany, found - 63 6 | Country: France, found - 56 7 | Country: Singapore, found - 46 8 | Country: Canada, found - 46 9 | Country: China, found - 45 10 | Country: India, found - 39 11 | Country: Belgium, found - 36 12 | Country: Hong Kong, found - 32 13 | Country: South Africa, found - 27 14 | Country: Japan, found - 23 15 | Country: Brazil, found - 20 16 | Country: Taiwan, found - 19 17 | Country: Philippines, found - 18 18 | Country: Malaysia, found - 16 19 | Country: Thailand, found - 15 20 | Country: Italy, found - 14 21 | -------------------------------------------------------------------------------- /samples/112018/txt/Countries_top.txt: -------------------------------------------------------------------------------- 1 | Country: United States, found - 4705 2 | Country: Germany, found - 1050 3 | Country: United Kingdom, found - 582 4 | Country: Australia, found - 439 5 | Country: Netherlands, found - 378 6 | Country: Singapore, found - 323 7 | Country: China, found - 243 8 | Country: France, found - 173 9 | Country: Canada, found - 164 10 | Country: India, found - 157 11 | Country: Hong Kong, found - 153 12 | Country: Austria, found - 119 13 | Country: Belgium, found - 98 14 | Country: Switzerland, found - 96 15 | Country: South Africa, found - 95 16 | Country: Japan, found - 81 17 | Country: Poland, found - 73 18 | Country: Greece, found - 73 19 | Country: Thailand, found - 72 20 | Country: Brazil, found - 66 21 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | atomicwrites==1.2.1 2 | attrs==18.2.0 3 | certifi==2018.10.15 4 | cffi==1.11.5 5 | chardet==3.0.4 6 | Click==7.0 7 | click-plugins==1.0.4 8 | colorama==0.4.0 9 | coverage==4.5.2 10 | cycler==0.10.0 11 | gevent==1.3.7 12 | greenlet==0.4.15 13 | idna==2.7 14 | kiwisolver==1.0.1 15 | matplotlib==3.0.2 16 | more-itertools==4.3.0 17 | numpy==1.15.4 18 | pluggy==0.8.0 19 | pprintpp==0.4.0 20 | py==1.7.0 21 | pycountry==18.5.26 22 | pycountry-convert==0.7.2 23 | pycparser==2.19 24 | pyparsing==2.3.0 25 | pytest==3.10.1 26 | pytest-cov==2.6.0 27 | pytest-mock==1.10.0 28 | python-dateutil==2.7.5 29 | python-nmap==0.6.1 30 | repoze.lru==0.7 31 | requests==2.20.1 32 | shodan==1.10.4 33 | six==1.11.0 34 | urllib3==1.24.2 35 | virtualenv==16.1.0 36 | websocket==0.2.1 37 | websocket-client==0.54.0 38 | XlsxWriter==1.1.2 39 | -------------------------------------------------------------------------------- /py-scripts/vgluware.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | from json import loads 4 | from ssl import CERT_NONE 5 | 6 | from websocket import WebSocket 7 | from websocket import _exceptions as ws_exception 8 | 9 | 10 | def main(addr): 11 | """ 12 | Get gluware version with websocket 13 | 14 | :param addr: ip address of host (str) 15 | :return: version (str) 16 | """ 17 | 18 | # Turn off SSL certificate checking 19 | ssl_cert_off = {"cert_reqs": CERT_NONE} 20 | ws = WebSocket(sslopt=ssl_cert_off) 21 | 22 | try: 23 | ws.connect( 24 | 'wss://{address}/ControlApi/socket.io/?EIO=3&transport=websocket'.format( 25 | address=addr)) 26 | except ws_exception.WebSocketBadStatusException: 27 | return 28 | except Exception: 29 | return 30 | 31 | ws.send('421["request",{"service":"DocsService","method":"getVersion","payload":{}}]') 32 | 33 | while True: 34 | message = ws.recv() 35 | if not message: 36 | return 37 | if 'gluware_version' in message: 38 | break 39 | 40 | json_string = message[4:-1] 41 | json_payload = loads(json_string)['payload'] 42 | payload = loads(json_payload) 43 | return payload['gluware_version']['semver'] 44 | -------------------------------------------------------------------------------- /map/maps/leaf-demo.js: -------------------------------------------------------------------------------- 1 | // See post: http://asmaloney.com/2015/06/code/clustering-markers-on-leaflet-maps 2 | 3 | var map = L.map( 'map', { 4 | center: [10.0, 5.0], 5 | minZoom: 2, 6 | zoom: 2 7 | }); 8 | 9 | L.tileLayer( 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { 10 | attribution: '© OpenStreetMap', 11 | subdomains: ['a','b','c'] 12 | }).addTo( map ); 13 | 14 | var myURL = jQuery( 'script[src$="leaf-demo.js"]' ).attr( 'src' ).replace( 'leaf-demo.js', '' ); 15 | 16 | var myIcon = L.icon({ 17 | iconUrl: myURL + 'images/pin24.png', 18 | iconRetinaUrl: myURL + 'images/pin48.png', 19 | iconSize: [29, 24], 20 | iconAnchor: [9, 21], 21 | popupAnchor: [0, -14] 22 | }); 23 | 24 | var markerClusters = L.markerClusterGroup(); 25 | 26 | for ( var i = 0; i < markers.length; ++i ) 27 | { 28 | var popup = 'Vendor: ' + markers[i].vendor + 29 | '
Product: ' + markers[i].product + 30 | '
Version: ' + markers[i].additional_info + 31 | '
IP: ' + markers[i].ip + 32 | '
Port: ' + markers[i].port + 33 | '
Protocol: ' + markers[i].proto; 34 | 35 | var m = L.marker( [markers[i].lat, markers[i].lng], {icon: myIcon} ) 36 | .bindPopup( popup ); 37 | 38 | markerClusters.addLayer( m ); 39 | } 40 | 41 | map.addLayer( markerClusters ); 42 | -------------------------------------------------------------------------------- /samples/102018/map/maps/leaf-demo.js: -------------------------------------------------------------------------------- 1 | // See post: http://asmaloney.com/2015/06/code/clustering-markers-on-leaflet-maps 2 | 3 | var map = L.map( 'map', { 4 | center: [10.0, 5.0], 5 | minZoom: 2, 6 | zoom: 2 7 | }); 8 | 9 | L.tileLayer( 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { 10 | attribution: '© OpenStreetMap', 11 | subdomains: ['a','b','c'] 12 | }).addTo( map ); 13 | 14 | var myURL = jQuery( 'script[src$="leaf-demo.js"]' ).attr( 'src' ).replace( 'leaf-demo.js', '' ); 15 | 16 | var myIcon = L.icon({ 17 | iconUrl: myURL + 'images/pin24.png', 18 | iconRetinaUrl: myURL + 'images/pin48.png', 19 | iconSize: [29, 24], 20 | iconAnchor: [9, 21], 21 | popupAnchor: [0, -14] 22 | }); 23 | 24 | var markerClusters = L.markerClusterGroup(); 25 | 26 | for ( var i = 0; i < markers.length; ++i ) 27 | { 28 | var popup = 'Vendor: ' + markers[i].vendor + 29 | '
Product: ' + markers[i].product + 30 | '
Version: ' + markers[i].additional_info + 31 | '
IP: ' + markers[i].ip + 32 | '
Port: ' + markers[i].port + 33 | '
Protocol: ' + markers[i].proto; 34 | 35 | var m = L.marker( [markers[i].lat, markers[i].lng], {icon: myIcon} ) 36 | .bindPopup( popup ); 37 | 38 | markerClusters.addLayer( m ); 39 | } 40 | 41 | map.addLayer( markerClusters ); 42 | -------------------------------------------------------------------------------- /samples/112018/map/maps/leaf-demo.js: -------------------------------------------------------------------------------- 1 | // See post: http://asmaloney.com/2015/06/code/clustering-markers-on-leaflet-maps 2 | 3 | var map = L.map( 'map', { 4 | center: [10.0, 5.0], 5 | minZoom: 2, 6 | zoom: 2 7 | }); 8 | 9 | L.tileLayer( 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { 10 | attribution: '© OpenStreetMap', 11 | subdomains: ['a','b','c'] 12 | }).addTo( map ); 13 | 14 | var myURL = jQuery( 'script[src$="leaf-demo.js"]' ).attr( 'src' ).replace( 'leaf-demo.js', '' ); 15 | 16 | var myIcon = L.icon({ 17 | iconUrl: myURL + 'images/pin24.png', 18 | iconRetinaUrl: myURL + 'images/pin48.png', 19 | iconSize: [29, 24], 20 | iconAnchor: [9, 21], 21 | popupAnchor: [0, -14] 22 | }); 23 | 24 | var markerClusters = L.markerClusterGroup(); 25 | 26 | for ( var i = 0; i < markers.length; ++i ) 27 | { 28 | var popup = 'Vendor: ' + markers[i].vendor + 29 | '
Product: ' + markers[i].product + 30 | '
Version: ' + markers[i].additional_info + 31 | '
IP: ' + markers[i].ip + 32 | '
Port: ' + markers[i].port + 33 | '
Protocol: ' + markers[i].proto; 34 | 35 | var m = L.marker( [markers[i].lat, markers[i].lng], {icon: myIcon} ) 36 | .bindPopup( popup ); 37 | 38 | markerClusters.addLayer( m ); 39 | } 40 | 41 | map.addLayer( markerClusters ); 42 | -------------------------------------------------------------------------------- /nse-scripts/vsilverpeak.nse: -------------------------------------------------------------------------------- 1 | local http = require "http" 2 | local url = require "url" 3 | local stdnse = require "stdnse" 4 | local table = require "table" 5 | local string = require "string" 6 | local shortport = require "shortport" 7 | 8 | description = [[ 9 | The script for getting the product version of Silver Peak SD-WAN 10 | ]] 11 | 12 | 13 | author = {"afr"} 14 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 15 | categories = {"discovery", "safe"} 16 | 17 | portrule = shortport.http 18 | 19 | local function fail (err) return stdnse.format_output(false, err) end 20 | 21 | action = function(host, port) 22 | local path = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/" 23 | local response 24 | local output_info = {} 25 | local vsdwan = "" 26 | local urlp = path 27 | 28 | response = http.generic_request(host, port, "GET", path) 29 | 30 | output_info = stdnse.output_table() 31 | 32 | if response == nil then 33 | return fail("Request failed") 34 | end 35 | 36 | if response.status == 302 then 37 | 38 | found, matches = http.response_contains(response, "http.*/([.0-9]+)/", false) 39 | if found == true then vsdwan = matches[1] else return nil end 40 | 41 | output_info.vsdwan_version = {} 42 | table.insert(output_info.vsdwan_version, "SilverPeak Version: " .. vsdwan) 43 | end 44 | 45 | return output_info, stdnse.format_output(true, output_info) 46 | 47 | end 48 | 49 | -------------------------------------------------------------------------------- /nse-scripts/vriverbed.nse: -------------------------------------------------------------------------------- 1 | local http = require "http" 2 | local url = require "url" 3 | local stdnse = require "stdnse" 4 | local table = require "table" 5 | local string = require "string" 6 | local shortport = require "shortport" 7 | 8 | description = [[ 9 | The script for getting the product version of Riverbed SD-WAN 10 | ]] 11 | 12 | 13 | author = {"afr"} 14 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 15 | categories = {"discovery", "safe"} 16 | 17 | portrule = shortport.http 18 | 19 | local function fail (err) return stdnse.format_output(false, err) end 20 | 21 | action = function(host, port) 22 | local path = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/" 23 | local response 24 | local output_info = {} 25 | local vsdwan = "" 26 | local urlp = path 27 | 28 | response = http.generic_request(host, port, "GET", path) 29 | 30 | if response.status == 301 or response.status == 302 then 31 | local url_parse_res = url.parse(response.header.location) 32 | urlp = url_parse_res.path 33 | stdnse.print_debug("Status code: " .. response.status) 34 | response = http.generic_request(host,port,"GET", urlp) 35 | end 36 | 37 | output_info = stdnse.output_table() 38 | 39 | if response == nil then 40 | return fail("Request failed") 41 | end 42 | 43 | local try_counter = 1 44 | 45 | while try_counter < 6 and response.status ~= 200 do 46 | response = http.generic_request(host, port, "GET", urlp) 47 | try_counter = try_counter + 1 48 | end 49 | 50 | if response.status == 200 then 51 | 52 | found, matches = http.response_contains(response, "web3 v([.0-9]+)", false) 53 | if found == true then vsdwan = matches[1] else return nil end 54 | 55 | output_info.vsdwan_version = {} 56 | table.insert(output_info.vsdwan_version, "Riverbed Version: " .. vsdwan) 57 | end 58 | 59 | return output_info, stdnse.format_output(true, output_info) 60 | 61 | end 62 | 63 | -------------------------------------------------------------------------------- /nse-scripts/vnuage.nse: -------------------------------------------------------------------------------- 1 | local http = require "http" 2 | local url = require "url" 3 | local stdnse = require "stdnse" 4 | local table = require "table" 5 | local string = require "string" 6 | local shortport = require "shortport" 7 | 8 | description = [[ 9 | The script for getting the product version of Nuage Networks SD-WAN 10 | ]] 11 | 12 | 13 | author = {"afr"} 14 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 15 | categories = {"discovery", "safe"} 16 | 17 | portrule = shortport.http 18 | 19 | local function fail (err) return stdnse.format_output(false, err) end 20 | 21 | action = function(host, port) 22 | local path = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/" 23 | local response 24 | local output_info = {} 25 | local vsdwan = "" 26 | local urlp = path 27 | 28 | response = http.generic_request(host, port, "GET", path) 29 | 30 | if response.status == 301 or response.status == 302 then 31 | local url_parse_res = url.parse(response.header.location) 32 | urlp = url_parse_res.path 33 | stdnse.print_debug("Status code: " .. response.status) 34 | response = http.generic_request(host,port,"GET", urlp) 35 | end 36 | 37 | output_info = stdnse.output_table() 38 | 39 | if response == nil then 40 | return fail("Request failed") 41 | end 42 | 43 | local try_counter = 1 44 | 45 | while try_counter < 6 and response.status ~= 200 do 46 | response = http.generic_request(host, port, "GET", urlp) 47 | try_counter = try_counter + 1 48 | end 49 | 50 | if response.status == 200 then 51 | 52 | found, matches = http.response_contains(response, 'ng%-version="([.0-9]+)"', false) 53 | if found == true then vsdwan = matches[1] else return nil end 54 | 55 | output_info.vsdwan_version = {} 56 | table.insert(output_info.vsdwan_version, "Nuage Version: " .. vsdwan) 57 | end 58 | 59 | return output_info, stdnse.format_output(true, output_info) 60 | 61 | end 62 | 63 | -------------------------------------------------------------------------------- /nse-scripts/vtalari.nse: -------------------------------------------------------------------------------- 1 | local http = require "http" 2 | local url = require "url" 3 | local stdnse = require "stdnse" 4 | local table = require "table" 5 | local string = require "string" 6 | local shortport = require "shortport" 7 | 8 | description = [[ 9 | The script for getting the product version of Talari SD-WAN 10 | ]] 11 | 12 | 13 | author = {"afr"} 14 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 15 | categories = {"discovery", "safe"} 16 | 17 | portrule = shortport.http 18 | 19 | local function fail (err) return stdnse.format_output(false, err) end 20 | 21 | action = function(host, port) 22 | local path = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/" 23 | local response 24 | local output_info = {} 25 | local vsdwan = "" 26 | local urlp = path 27 | 28 | response = http.generic_request(host, port, "GET", path) 29 | 30 | if response.status == 301 or response.status == 302 then 31 | local url_parse_res = url.parse(response.header.location) 32 | urlp = url_parse_res.path 33 | stdnse.print_debug("Status code: " .. response.status) 34 | response = http.generic_request(host,port,"GET", urlp) 35 | end 36 | 37 | output_info = stdnse.output_table() 38 | 39 | if response == nil then 40 | return fail("Request failed") 41 | end 42 | 43 | local try_counter = 1 44 | 45 | while try_counter < 6 and response.status ~= 200 do 46 | response = http.generic_request(host, port, "GET", urlp) 47 | try_counter = try_counter + 1 48 | end 49 | 50 | if response.status == 200 then 51 | 52 | found, matches = http.response_contains(response, 'talari%.css%?([_.0-9A-Za-z]+)"', false) 53 | if found == true then vsdwan = matches[1] else return nil end 54 | 55 | output_info.vsdwan_version = {} 56 | table.insert(output_info.vsdwan_version, "Talari Version: " .. vsdwan) 57 | end 58 | 59 | return output_info, stdnse.format_output(true, output_info) 60 | 61 | end 62 | 63 | -------------------------------------------------------------------------------- /nse-scripts/vfatpipe.nse: -------------------------------------------------------------------------------- 1 | local http = require "http" 2 | local url = require "url" 3 | local stdnse = require "stdnse" 4 | local table = require "table" 5 | local string = require "string" 6 | local shortport = require "shortport" 7 | 8 | description = [[ 9 | The script for getting the product version of Fatpipe Symphony SD-WAN 10 | ]] 11 | 12 | 13 | author = {"afr"} 14 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 15 | categories = {"discovery", "safe"} 16 | 17 | portrule = shortport.http 18 | 19 | local function fail (err) return stdnse.format_output(false, err) end 20 | 21 | action = function(host, port) 22 | local path = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/" 23 | local response 24 | local output_info = {} 25 | local vsdwan = "" 26 | local urlp = path 27 | 28 | response = http.generic_request(host, port, "GET", path) 29 | 30 | if response.status == 301 or response.status == 302 then 31 | local url_parse_res = url.parse(response.header.location) 32 | urlp = url_parse_res.path 33 | stdnse.print_debug("Status code: " .. response.status) 34 | response = http.generic_request(host,port,"GET", urlp) 35 | end 36 | 37 | output_info = stdnse.output_table() 38 | 39 | if response == nil then 40 | return fail("Request failed") 41 | end 42 | 43 | local try_counter = 1 44 | 45 | while try_counter < 6 and response.status ~= 200 do 46 | response = http.generic_request(host, port, "GET", urlp) 47 | try_counter = try_counter + 1 48 | end 49 | 50 | if response.status == 200 then 51 | 52 | found, matches = http.response_contains(response, "
([r.0-9]+)
", false) 53 | if found == true then vsdwan = matches[1] else return nil end 54 | 55 | output_info.vsdwan_version = {} 56 | table.insert(output_info.vsdwan_version, "Fatpipe Version: " .. vsdwan) 57 | end 58 | 59 | return output_info, stdnse.format_output(true, output_info) 60 | 61 | end 62 | 63 | -------------------------------------------------------------------------------- /nse-scripts/vvmware_nsx.nse: -------------------------------------------------------------------------------- 1 | local http = require "http" 2 | local url = require "url" 3 | local stdnse = require "stdnse" 4 | local table = require "table" 5 | local string = require "string" 6 | local shortport = require "shortport" 7 | 8 | description = [[ 9 | The script for getting the product version of VMWare NSX SD-WAN 10 | ]] 11 | 12 | 13 | author = {"afr"} 14 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 15 | categories = {"discovery", "safe"} 16 | 17 | portrule = shortport.http 18 | 19 | local function fail (err) return stdnse.format_output(false, err) end 20 | 21 | action = function(host, port) 22 | local path = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/" 23 | local response 24 | local output_info = {} 25 | local vsdwan = "" 26 | local urlp = path 27 | 28 | response = http.generic_request(host, port, "GET", path) 29 | 30 | if response.status == 301 or response.status == 302 then 31 | local url_parse_res = url.parse(response.header.location) 32 | urlp = url_parse_res.path 33 | stdnse.print_debug("Status code: " .. response.status) 34 | response = http.generic_request(host,port,"GET", urlp) 35 | end 36 | 37 | output_info = stdnse.output_table() 38 | 39 | if response == nil then 40 | return fail("Request failed") 41 | end 42 | 43 | local try_counter = 1 44 | 45 | while try_counter < 6 and response.status ~= 200 do 46 | response = http.generic_request(host, port, "GET", urlp) 47 | try_counter = try_counter + 1 48 | end 49 | 50 | if response.status == 200 then 51 | 52 | found, matches = http.response_contains(response, "%/vco%-ui.([0-9.]+).", false) 53 | if found == true then vsdwan = matches[1] else return nil end 54 | 55 | output_info.vsdwan_version = {} 56 | table.insert(output_info.vsdwan_version, "VMware NSX Version: " .. vsdwan) 57 | end 58 | 59 | return output_info, stdnse.format_output(true, output_info) 60 | 61 | end 62 | 63 | -------------------------------------------------------------------------------- /nse-scripts/vcitrix.nse: -------------------------------------------------------------------------------- 1 | local http = require "http" 2 | local url = require "url" 3 | local stdnse = require "stdnse" 4 | local table = require "table" 5 | local string = require "string" 6 | local shortport = require "shortport" 7 | 8 | description = [[ 9 | The script for getting the product version of Citrix NetScaler SD-WAN 10 | ]] 11 | 12 | 13 | author = {"afr"} 14 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 15 | categories = {"discovery", "safe"} 16 | 17 | portrule = shortport.http 18 | 19 | local function fail (err) return stdnse.format_output(false, err) end 20 | 21 | action = function(host, port) 22 | local path = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/" 23 | local response 24 | local output_info = {} 25 | local vsdwan = "" 26 | local urlp = path 27 | 28 | response = http.generic_request(host, port, "GET", path) 29 | 30 | if response.status == 301 or response.status == 302 then 31 | local url_parse_res = url.parse(response.header.location) 32 | urlp = url_parse_res.path 33 | -- stdnse.print_debug("Status code: " .. response.status) 34 | response = http.generic_request(host,port,"GET", urlp) 35 | end 36 | 37 | output_info = stdnse.output_table() 38 | 39 | if response == nil then 40 | return fail("Request failed") 41 | end 42 | 43 | local try_counter = 1 44 | 45 | while try_counter < 30 and response.status ~= 200 do 46 | response = http.generic_request(host, port, "GET", urlp) 47 | try_counter = try_counter + 1 48 | end 49 | 50 | if response.status == 200 then 51 | 52 | found, matches = http.response_contains(response, "css%?v%=([.0-9]+)", false) 53 | if found == true then vsdwan = matches[1] else return nil end 54 | 55 | output_info.vsdwan_version = {} 56 | table.insert(output_info.vsdwan_version, "Citrix NetScaler Version: " .. vsdwan) 57 | end 58 | 59 | return output_info, stdnse.format_output(true, output_info) 60 | 61 | end 62 | 63 | -------------------------------------------------------------------------------- /nse-scripts/vsonus_edge.nse: -------------------------------------------------------------------------------- 1 | local http = require "http" 2 | local url = require "url" 3 | local stdnse = require "stdnse" 4 | local table = require "table" 5 | local string = require "string" 6 | local shortport = require "shortport" 7 | 8 | description = [[ 9 | The script for getting the product version of Sonus SBC Edge 10 | ]] 11 | 12 | 13 | author = {"afr"} 14 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 15 | categories = {"discovery", "safe"} 16 | 17 | portrule = shortport.http 18 | 19 | local function fail (err) return stdnse.format_output(false, err) end 20 | 21 | action = function(host, port) 22 | local path = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/cgi/index.php" 23 | local response 24 | local output_info = {} 25 | local vsdwan = "" 26 | local urlp = path 27 | 28 | response = http.generic_request(host, port, "GET", path) 29 | 30 | if response.status == 301 or response.status == 302 then 31 | local url_parse_res = url.parse(response.header.location) 32 | urlp = url_parse_res.path 33 | stdnse.print_debug("Status code: " .. response.status) 34 | response = http.generic_request(host,port,"GET", urlp) 35 | end 36 | 37 | output_info = stdnse.output_table() 38 | 39 | if response == nil then 40 | return fail("Request failed") 41 | end 42 | 43 | local try_counter = 1 44 | 45 | while try_counter < 6 and response.status ~= 200 do 46 | response = http.generic_request(host, port, "GET", urlp) 47 | try_counter = try_counter + 1 48 | end 49 | 50 | if response.status == 200 then 51 | 52 | found, matches = http.response_contains(response, "/style/([.0-9]+)%-[0-9]+%_rel", false) 53 | if found == true then vsdwan = matches[1] else return nil end 54 | 55 | output_info.vsdwan_version = {} 56 | table.insert(output_info.vsdwan_version, "Sonus Edge Version: " .. vsdwan) 57 | end 58 | 59 | return output_info, stdnse.format_output(true, output_info) 60 | 61 | end 62 | 63 | -------------------------------------------------------------------------------- /nse-scripts/vversa_flex.nse: -------------------------------------------------------------------------------- 1 | local http = require "http" 2 | local url = require "url" 3 | local stdnse = require "stdnse" 4 | local table = require "table" 5 | local string = require "string" 6 | local shortport = require "shortport" 7 | 8 | description = [[ 9 | The script for getting the product version of Versa Flex VNF 10 | ]] 11 | 12 | 13 | author = {"afr"} 14 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 15 | categories = {"discovery", "safe"} 16 | 17 | portrule = shortport.http 18 | 19 | local function fail (err) return stdnse.format_output(false, err) end 20 | 21 | action = function(host, port) 22 | local path = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/scripts/main-layout/main-layout-controller.js" 23 | local response 24 | local output_info = {} 25 | local vsdwan = "" 26 | local urlp = path 27 | 28 | response = http.generic_request(host, port, "GET", path) 29 | 30 | if response.status == 301 or response.status == 302 then 31 | local url_parse_res = url.parse(response.header.location) 32 | urlp = url_parse_res.path 33 | stdnse.print_debug("Status code: " .. response.status) 34 | response = http.generic_request(host,port,"GET", urlp) 35 | end 36 | 37 | output_info = stdnse.output_table() 38 | 39 | if response == nil then 40 | return fail("Request failed") 41 | end 42 | 43 | local try_counter = 1 44 | 45 | while try_counter < 6 and response.status ~= 200 do 46 | response = http.generic_request(host, port, "GET", urlp) 47 | try_counter = try_counter + 1 48 | end 49 | 50 | if response.status == 200 then 51 | 52 | found, matches = http.response_contains(response, '"versa%-flexvnf%-([.0-9%-a-zA-Z]+)', false) 53 | if found == true then vsdwan = matches[1] else return nil end 54 | 55 | output_info.vsdwan_version = {} 56 | table.insert(output_info.vsdwan_version, "Versa Flex Version: " .. vsdwan) 57 | end 58 | 59 | return output_info, stdnse.format_output(true, output_info) 60 | 61 | end 62 | 63 | -------------------------------------------------------------------------------- /nse-scripts/vsonus_mgmt.nse: -------------------------------------------------------------------------------- 1 | local http = require "http" 2 | local url = require "url" 3 | local stdnse = require "stdnse" 4 | local table = require "table" 5 | local string = require "string" 6 | local shortport = require "shortport" 7 | 8 | description = [[ 9 | The script for getting the product version of Sonus SBC Management Application 10 | ]] 11 | 12 | 13 | author = {"afr"} 14 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 15 | categories = {"discovery", "safe"} 16 | 17 | portrule = shortport.http 18 | 19 | local function fail (err) return stdnse.format_output(false, err) end 20 | 21 | action = function(host, port) 22 | local path = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/" 23 | local response 24 | local output_info = {} 25 | local vsdwan = "" 26 | local urlp = path 27 | 28 | response = http.generic_request(host, port, "GET", path) 29 | 30 | if response.status == 301 or response.status == 302 then 31 | local url_parse_res = url.parse(response.header.location) 32 | urlp = url_parse_res.path 33 | stdnse.print_debug("Status code: " .. response.status) 34 | response = http.generic_request(host,port,"GET", urlp) 35 | end 36 | 37 | output_info = stdnse.output_table() 38 | 39 | if response == nil then 40 | return fail("Request failed") 41 | end 42 | 43 | local try_counter = 1 44 | 45 | while try_counter < 6 and (response.status ~= 503 or response.status ~= 200) do 46 | response = http.generic_request(host, port, "GET", urlp) 47 | try_counter = try_counter + 1 48 | end 49 | 50 | if response.status == 503 or response.status == 200 then 51 | 52 | found, matches = http.response_contains(response, "EMA ([.0-9]+)", false) 53 | if found == true then vsdwan = matches[1] else return nil end 54 | 55 | output_info.vsdwan_version = {} 56 | table.insert(output_info.vsdwan_version, "Sonus Mgmt App Version: " .. vsdwan) 57 | end 58 | 59 | return output_info, stdnse.format_output(true, output_info) 60 | 61 | end 62 | 63 | -------------------------------------------------------------------------------- /nse-scripts/vcradlepoint.nse: -------------------------------------------------------------------------------- 1 | local http = require "http" 2 | local url = require "url" 3 | local stdnse = require "stdnse" 4 | local table = require "table" 5 | local string = require "string" 6 | local shortport = require "shortport" 7 | 8 | description = [[ 9 | The script for getting the product version of Cradlepoint SD-WAN CR4250* solutions 10 | ]] 11 | 12 | 13 | author = {"sdnewhop"} 14 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 15 | categories = {"discovery", "safe"} 16 | 17 | portrule = shortport.http 18 | 19 | local function fail (err) return stdnse.format_output(false, err) end 20 | 21 | action = function(host, port) 22 | local path = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/login/?referer=/admin/" 23 | local response 24 | local output_info = {} 25 | local vsdwan = "" 26 | local urlp = path 27 | 28 | response = http.generic_request(host, port, "GET", path) 29 | 30 | if response.status == 301 or response.status == 302 then 31 | local url_parse_res = url.parse(response.header.location) 32 | urlp = url_parse_res.path 33 | stdnse.print_debug("Status code: " .. response.status) 34 | response = http.generic_request(host,port,"GET", urlp) 35 | end 36 | 37 | output_info = stdnse.output_table() 38 | 39 | if response == nil then 40 | return fail("Request failed") 41 | end 42 | 43 | local try_counter = 1 44 | 45 | while try_counter < 6 and response.status ~= 200 do 46 | response = http.generic_request(host, port, "GET", urlp) 47 | try_counter = try_counter + 1 48 | end 49 | 50 | if response.status == 200 then 51 | found, matches = http.response_contains(response, "([0-9.]+[0-9]) .[a-zA-Z]+.[a-zA-Z]+.[0-9]+.[0-9]+:[0-9]+:[0-9]+", false) 52 | if found == true then vsdwan = matches[1] else return nil end 53 | 54 | output_info.vsdwan_version = {} 55 | table.insert(output_info.vsdwan_version, "Cradlepoint App Version: " .. vsdwan) 56 | end 57 | 58 | return output_info, stdnse.format_output(true, output_info) 59 | end -------------------------------------------------------------------------------- /nse-scripts/vbrain.nse: -------------------------------------------------------------------------------- 1 | local http = require "http" 2 | local url = require "url" 3 | local stdnse = require "stdnse" 4 | local table = require "table" 5 | local string = require "string" 6 | local shortport = require "shortport" 7 | 8 | description = [[ 9 | The script for getting the product version of Brain4Net Orchestrator 10 | ]] 11 | 12 | 13 | author = {"sdnewhop"} 14 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 15 | categories = {"discovery", "safe"} 16 | 17 | portrule = shortport.http 18 | 19 | local function fail (err) return stdnse.format_output(false, err) end 20 | 21 | action = function(host, port) 22 | local path = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/api/version" 23 | local response 24 | local output_info = {} 25 | local vsdwan = "" 26 | local urlp = path 27 | 28 | response = http.generic_request(host, port, "GET", path) 29 | 30 | if response.status == 301 or response.status == 302 then 31 | local url_parse_res = url.parse(response.header.location) 32 | urlp = url_parse_res.path 33 | stdnse.print_debug("Status code: " .. response.status) 34 | response = http.generic_request(host,port,"GET", urlp) 35 | end 36 | 37 | output_info = stdnse.output_table() 38 | 39 | if response == nil then 40 | return fail("Request failed") 41 | end 42 | 43 | local try_counter = 1 44 | 45 | while try_counter < 6 and response.status ~= 200 do 46 | response = http.generic_request(host, port, "GET", urlp) 47 | 48 | found, matches = http.response_contains(response, '0;url%=(.*)"%/%>') 49 | 50 | if found == true then 51 | local urltmp = url.parse(matches[1]) 52 | urlp = urltmp.path 53 | response = http.generic_request(host, port, "GET", urlp) 54 | try_counter = 1 55 | end 56 | try_counter = try_counter + 1 57 | end 58 | 59 | if response.status == 200 then 60 | 61 | found, matches = http.response_contains(response, '"build":"(.+)",', false) 62 | if found == true then vsdwan = matches[1] else return nil end 63 | 64 | output_info.vsdwan_version = {} 65 | table.insert(output_info.vsdwan_version, "Brain4Net Orchestrator Version: " .. vsdwan) 66 | end 67 | 68 | return output_info, stdnse.format_output(true, output_info) 69 | 70 | end 71 | 72 | -------------------------------------------------------------------------------- /nse-scripts/vversa_analytics.nse: -------------------------------------------------------------------------------- 1 | local http = require "http" 2 | local url = require "url" 3 | local stdnse = require "stdnse" 4 | local table = require "table" 5 | local string = require "string" 6 | local shortport = require "shortport" 7 | 8 | description = [[ 9 | The script for getting the product version of Versa Analytics 10 | ]] 11 | 12 | 13 | author = {"afr"} 14 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 15 | categories = {"discovery", "safe"} 16 | 17 | portrule = shortport.http 18 | 19 | local function fail (err) return stdnse.format_output(false, err) end 20 | 21 | action = function(host, port) 22 | local path = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/versa/app/js/common/constants.js" 23 | local response 24 | local output_info = {} 25 | local vsdwan = "" 26 | local urlp = path 27 | 28 | response = http.generic_request(host, port, "GET", path) 29 | 30 | if response.status == 301 or response.status == 302 then 31 | local url_parse_res = url.parse(response.header.location) 32 | urlp = url_parse_res.path 33 | stdnse.print_debug("Status code: " .. response.status) 34 | response = http.generic_request(host,port,"GET", urlp) 35 | end 36 | 37 | output_info = stdnse.output_table() 38 | 39 | if response == nil then 40 | return fail("Request failed") 41 | end 42 | 43 | local try_counter = 1 44 | 45 | while try_counter < 6 and response.status ~= 200 do 46 | response = http.generic_request(host, port, "GET", urlp) 47 | 48 | found, matches = http.response_contains(response, '0;url%=(.*)"%/%>') 49 | 50 | if found == true then 51 | local urltmp = url.parse(matches[1]) 52 | urlp = urltmp.path 53 | response = http.generic_request(host, port, "GET", urlp) 54 | try_counter = 1 55 | end 56 | try_counter = try_counter + 1 57 | end 58 | 59 | if response.status == 200 then 60 | 61 | found, matches = http.response_contains(response, "%/analytics%/([v.0-9]+)%/", false) 62 | if found == true then vsdwan = matches[1] else return nil end 63 | 64 | output_info.vsdwan_version = {} 65 | table.insert(output_info.vsdwan_version, "Versa Analytics Version: " .. vsdwan) 66 | end 67 | 68 | return output_info, stdnse.format_output(true, output_info) 69 | 70 | end 71 | 72 | -------------------------------------------------------------------------------- /nse-scripts/vversa_analytics_server.nse: -------------------------------------------------------------------------------- 1 | local http = require "http" 2 | local url = require "url" 3 | local stdnse = require "stdnse" 4 | local table = require "table" 5 | local string = require "string" 6 | local shortport = require "shortport" 7 | 8 | description = [[ 9 | The script for getting the product version of Versa Analytics Server 10 | ]] 11 | 12 | 13 | author = {"sdnewhop"} 14 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 15 | categories = {"discovery", "safe"} 16 | 17 | portrule = shortport.http 18 | 19 | local function fail (err) return stdnse.format_output(false, err) end 20 | 21 | action = function(host, port) 22 | local path = stdnse.get_script_args(SCRIPT_NAME .. ".path") or "/versa/analytics/version" 23 | local response 24 | local output_info = {} 25 | local vsdwan = "" 26 | local urlp = path 27 | 28 | response = http.generic_request(host, port, "GET", path) 29 | 30 | if response.status == 301 or response.status == 302 then 31 | local url_parse_res = url.parse(response.header.location) 32 | urlp = url_parse_res.path 33 | stdnse.print_debug("Status code: " .. response.status) 34 | response = http.generic_request(host,port,"GET", urlp) 35 | end 36 | 37 | output_info = stdnse.output_table() 38 | 39 | if response == nil then 40 | return fail("Request failed") 41 | end 42 | 43 | local try_counter = 1 44 | 45 | while try_counter < 6 and response.status ~= 200 do 46 | response = http.generic_request(host, port, "GET", urlp) 47 | 48 | found, matches = http.response_contains(response, '0;url%=(.*)"%/%>') 49 | 50 | if found == true then 51 | local urltmp = url.parse(matches[1]) 52 | urlp = urltmp.path 53 | response = http.generic_request(host, port, "GET", urlp) 54 | try_counter = 1 55 | end 56 | try_counter = try_counter + 1 57 | end 58 | 59 | if response.status == 200 then 60 | 61 | found, matches = http.response_contains(response, '"release":"([%w.]+)",', false) 62 | if found == true then vsdwan = matches[1] else return nil end 63 | 64 | output_info.vsdwan_version = {} 65 | table.insert(output_info.vsdwan_version, "Versa Analytics Server Version: " .. vsdwan) 66 | end 67 | 68 | return output_info, stdnse.format_output(true, output_info) 69 | 70 | end 71 | -------------------------------------------------------------------------------- /nse-scripts/vfortinet.nse: -------------------------------------------------------------------------------- 1 | local http = require "http" 2 | local url = require "url" 3 | local stdnse = require "stdnse" 4 | local table = require "table" 5 | local string = require "string" 6 | local shortport = require "shortport" 7 | 8 | description = [[ 9 | The script for getting the product version of Fortinet FortiGate SD-WAN 10 | ]] 11 | 12 | 13 | author = {"sdnewhop"} 14 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 15 | categories = {"discovery", "safe"} 16 | 17 | portrule = shortport.http 18 | 19 | local function fail (err) return stdnse.format_output(false, err) end 20 | 21 | action = function(host, port) 22 | local resp_js_path, js_path, resp_js 23 | local conf_build, conf_model, conf_label 24 | local output_info = {} 25 | local version 26 | 27 | local resp = http.get(host, port, "/") 28 | local version = nil 29 | 30 | -- make redirect if needed 31 | if resp.status == 301 or resp.status == 302 then 32 | local url = url.parse( resp.header.location ) 33 | if url.host == host.targetname or url.host == ( host.name ~= '' and host.name ) or url.host == host.ip then 34 | stdnse.print_debug("Redirect: " .. host.ip .. " -> " .. url.scheme.. "://" .. url.authority .. url.path) 35 | -- extract redirect port 36 | redir_port = string.match(url.authority, ":(%d+)") 37 | stdnse.print_debug("Redirect port is: " .. redir_port) 38 | stdnse.print_debug("Trying to get " .. host.ip .. " at " .. redir_port .. " port") 39 | -- get Fortinet login page at custom port 40 | resp = http.get(host.ip, tonumber(redir_port), "/login") 41 | end 42 | end 43 | 44 | if not resp.body then 45 | return nil 46 | end 47 | 48 | -- check if it Fortinet or not 49 | if not string.match(resp.body:lower(), "fortinet") then 50 | return nil 51 | end 52 | stdnse.print_debug("Found Fortinet SD-WAN") 53 | 54 | -- trigger 401 error to find path to js file with version 55 | resp_js_path = http.get(host.ip, tonumber(redir_port), "/api") 56 | if not resp_js_path.body then 57 | return nil 58 | end 59 | 60 | -- search for js file that contains version 61 | js_path = string.match(resp_js_path.body:lower(), " 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 36 | 37 | 38 | 39 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /samples/102018/map/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 36 | 37 | 38 | 39 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /samples/112018/map/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 36 | 37 | 38 | 39 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /harvester.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import os 5 | import sys 6 | 7 | import harvester.core as core 8 | 9 | # Default input file with queries 10 | core.QUERIES_JSON_FILE = "shodan_queries.json" 11 | 12 | # Default confidence level 13 | core.DEFAULT_CONFIDENCE = "certain" 14 | 15 | # Default quantity of results 16 | core.MAX_COUNTRIES = 10 17 | core.MAX_VENDORS = 10 18 | core.MAX_VULNERS = 10 19 | 20 | # Default paths and directories 21 | core.NMAP_SCRIPTS_PATH = "nse-scripts" 22 | core.PY_SCRIPTS_PATH = "py-scripts" 23 | 24 | core.MAP_MARKERS_DIR = "map" 25 | core.RESULTS_DIR = "results" 26 | 27 | 28 | def get_key_from_env(): 29 | """ 30 | Get Shodan API Key from environment variable 31 | 32 | :return: Shodan API key from env variable (str) 33 | """ 34 | try: 35 | shodan_api_key = os.environ['SHODAN_API_KEY'] 36 | return shodan_api_key 37 | except KeyError: 38 | print( 39 | 'Please set the environment variable SHODAN_API_KEY or use -sk key') 40 | sys.exit(1) 41 | 42 | 43 | def main(): 44 | """ 45 | Main interface for harvester core 46 | 47 | :return: None 48 | """ 49 | if sys.version_info < (3, 6): 50 | print('Required python version is 3.6 or greater') 51 | sys.exit(1) 52 | 53 | if len(sys.argv) == 1: 54 | print( 55 | "Usage: '{script_name} -h' for help".format( 56 | script_name=sys.argv[0])) 57 | sys.exit(1) 58 | 59 | parser = argparse.ArgumentParser(description=".") 60 | parser.add_argument("-sk", "--shodan-key", action="store", 61 | default=None, help="Shodan API key") 62 | parser.add_argument("-n", "--new", action="store_true", 63 | help="New scan in shodan") 64 | parser.add_argument("-q", "--queries", action="store", 65 | default=core.QUERIES_JSON_FILE, 66 | help="File with queries") 67 | parser.add_argument("-d", "--destination", action="store", 68 | default=core.RESULTS_DIR, help="Destination directory") 69 | parser.add_argument("-c", "--confidence", default=core.DEFAULT_CONFIDENCE, 70 | action="store", help="""Confidence level. Available 71 | levels: certain, firm, 72 | tentative""") 73 | parser.add_argument("-v", "--vulners", action="store", nargs='*', 74 | help="""List of vendors for vulners scan, e.g., 75 | '--vulners silver peak, arista, talari'. 76 | Use '--vulners all' to include all vendors 77 | in statistics.""") 78 | parser.add_argument("-mv", "--max-vendors", default=core.MAX_VENDORS, type=int, 79 | action="store", 80 | help="Max number of vendors in statistics") 81 | parser.add_argument("-mc", "--max-countries", default=core.MAX_COUNTRIES, 82 | type=int, 83 | action="store", 84 | help="Max number of countries in statistics") 85 | parser.add_argument("-maxv", "--max-vulners", default=core.MAX_VULNERS, 86 | type=int, action="store", 87 | help="Max number of vulners in statistics") 88 | parser.add_argument("-u", "--update-markers", action="store_true", 89 | default=False, help="Update map markers with new results") 90 | args = parser.parse_args() 91 | 92 | # Try to get key from environment if it was not passed with CLI 93 | if not args.shodan_key and args.new is True: 94 | args.shodan_key = get_key_from_env() 95 | 96 | # Check confidence level 97 | if args.confidence.lower() not in ['certain', 'firm', 'tentative']: 98 | print('Wrong confidence level. Use -h key for help.') 99 | sys.exit(1) 100 | 101 | # Run harvester 102 | core.run(args) 103 | 104 | 105 | if __name__ == '__main__': 106 | main() 107 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SD-WAN Harvester 2 | :globe_with_meridians: SD-WAN Internet Census Framework 3 | 4 | ## Disclaimer 5 | This project is no longer maintained. It is stable and you still can use it for SD-WAN scanning, but currently, more preferable and accurate way to scan different things on the internet (not only SD-WAN solutions) is to use our new Grinder Framework. 6 | 7 | **[:mag_right: Grinder Framework](https://github.com/sdnewhop/grinder)** 8 | 9 | ## Contents 10 | 1. [Description](#description) 11 | 1. [Slides](#slides) 12 | 1. [Requirements](#requirements) 13 | 1. [Installation](#installation) 14 | 1. [Usage](#usage) 15 | - [Command Line Arguments](#command-line-arguments) 16 | - [Examples](#examples) 17 | 18 | ## Description 19 | `SD-WAN Harvester` tool was created to automatically enumerate and fingerprint SD-WAN nodes on the Internet. 20 | It uses Shodan search engine for discovering, NMAP NSE scripts for fingerprinting, and masscan to implement some specific checks. 21 | 22 | ## Slides 23 | - [SD-WAN Internet Census. Zero Nights 2018](https://github.com/sdnewhop/sdwannewhope/blob/master/slides/zn-2018.pdf) 24 | 25 | ## Requirements 26 | `SD-WAN Harvester` requires [Python 3.6](https://www.python.org/getit/) or later and [Nmap](https://nmap.org/download.html). 27 | 28 | You also need an Shodan API key. 29 | 30 | ## Installation 31 | 1. Clone the repository: 32 | ``` 33 | git clone https://github.com/sdnewhop/sdwan-harvester.git 34 | ``` 35 | 2. Install `pip` requirements: 36 | ``` 37 | python3.6 -m pip install -r requirements.txt 38 | ``` 39 | 3. Run the script: 40 | ``` 41 | python3.6 harvester.py -h 42 | ``` 43 | 4. Set your Shodan key via a command line argument 44 | ``` 45 | ./harvester.py -sk YOUR_SHODAN_KEY 46 | ``` 47 | or via an environment variable 48 | ``` 49 | export SHODAN_API_KEY=YOUR_API_KEY_HERE 50 | ./harvester.py (without -sk key) 51 | ``` 52 | 53 | ## Usage 54 | ### Command Line Arguments 55 | 1. `-h, --help` - show the help message and exit. 56 | 57 | 2. `-sk SHODAN_KEY, --shodan-key SHODAN_KEY` - set a Shodan API key. 58 | 59 | 3. `-n, --new` - initiate a new discovery using Shodan. 60 | 61 | 4. `-q QUERIES, --queries QUERIES` - specify the file containing SD-WAN queries and filters for Shodan. 62 | *Default value is `shodan_queries.json`.* 63 | 64 | 5. `-d DESTINATION, --destination DESTINATION` - the directory where results will be stored. 65 | *Default value is `results`.* 66 | 67 | 6. `-C CONFIDENCE, --confidence CONFIDENCE` - set the confidence level (`certain`, `firm`, or `tentative`). 68 | *Default value is `certain`.* 69 | 70 | 7. `-v [VULNERS [VULNERS ...]], --vulners [VULNERS [VULNERS ...]]` - the list of venodrs checked by Shodan vulnerability scanner. For example, `--- vulners silver peak, arista, talari` command starts finding of known vulnerabilities for `silver peak`, `arista` and `talari` products. Use `--vulners all` to run scanning for all vendors. 71 | *By default, Shodan vulnerability scanning is turned off.* 72 | 73 | 8. `-mv MAX_VENDORS, --max-vendors MAX_VENDORS` - the Maximum Number of Vendors shown in reports. 74 | *Default value is `10`.* 75 | 76 | 9. `-mc MAX_COUNTRIES, --max-countries MAX_COUNTRIES` - the Maximum Number of Countries shown in reports. 77 | *Default value is `10`.* 78 | 79 | 10. `-maxv MAX_VULNERS, --max-vulners MAX_VULNERS` - the Maximum Number of Vulnerabilities shown in reports. 80 | *Default value is `10`.* 81 | 82 | 11. `-u, --update-markers` - Update map markers. 83 | 84 | ### Examples 85 | Show help 86 | ``` 87 | python3.6 harvester.py -h 88 | ``` 89 | Run an enumeration 90 | ``` 91 | python3.6 harvester.py -sk YOUR_API_KEY -n 92 | ``` 93 | Run an enumeration with `firm` level of confidence 94 | ``` 95 | python3.6 harvester.py -sk YOUR_API_KEY -n -c firm 96 | ``` 97 | Run a vulnerability scan against `talari` vendor 98 | ``` 99 | python3.6 harvester.py -sk YOUR_API_KEY -n -v talari 100 | ``` 101 | Run a new vulnerability scan for all vendors. The Maximum Number of Vendors is 8, the Maximum Number of Countries is 8, and the Maximum Number of CVEs is 8 102 | ``` 103 | python3.6 harvester.py -sk YOUR_API_KEY -n -v all -mv 8 -mc 8 -maxv 8 104 | ``` 105 | Run a new scan with all features enabled 106 | ``` 107 | python3.6 harvester.py -sk YOUR_API_KEY -n -v all -c all 108 | ``` 109 | Process data from previous scan results (for example, if you want to build new charts and graphics containing fewer vendors, countries, or vulners.) 110 | ``` 111 | python3.6 harvester.py -v -mv -mc -maxv 112 | ``` 113 | -------------------------------------------------------------------------------- /shodan_queries.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"vendor": "Silver Peak Systems","product":"Silver Peak Unity EdgeConnect", "query":"vxoaSessionID", "script":"vsilverpeak.nse", "confidence": "certain"}, 3 | {"vendor": "Silver Peak Systems","product":"Silver Peak Unity EdgeConnect", "query":"ssl:\"silver-peak\"", "script":"vsilverpeak.nse", "confidence": "certain"}, 4 | {"vendor": "Silver Peak Systems","product":"Silver Peak Systems Unity Orchestrator", "query":"gmsSessionID", "script":"vsilverpeak.nse", "confidence": "certain"}, 5 | {"vendor": "Silver Peak Systems","product":"Silver Peak Systems Unity Orchestrator", "query":"ssl:\"Silverpeak GMS\"", "script":"vsilverpeak.nse", "confidence": "certain"}, 6 | {"vendor": "CloudGenix","product":"CloudGenix SD-WAN", "query":"ssl:\"O=CloudGenix Inc\"", "script":"", "confidence": "firm"}, 7 | {"vendor": "Ecessa","product":"Ecessa WANworX SD-WAN", "query":"http.html_hash:-1848258522 title:\"Ecessa\"", "script":"", "confidence": "tentative"}, 8 | {"vendor": "Nuage","product":"Nuage Networks SD-WAN (VNS)", "query":"title:\"SD-WAN*Portal\"", "script":"", "confidence": "certain"}, 9 | {"vendor": "Nuage","product":"Nuage Networks SD-WAN (VNS)", "query":"http.favicon.hash:1069145589", "script":"", "confidence": "certain"}, 10 | {"vendor": "Nuage","product":"Nuage Networks SD-WAN (VNS)", "query":"http.favicon.hash:1069145589 title:\"SD-WAN*Portal\"", "script":"", "confidence": "certain"}, 11 | {"vendor": "Nuage","product":"Nuage Networks SD-WAN (VNS)", "query":"http.favicon.hash:1069145589 title:\"Architect\"", "script":"", "confidence": "certain"}, 12 | {"vendor": "Nuage","product":"Nuage Networks SD-WAN (VNS)", "query":"http.favicon.hash:1069145589 title:\"VNS Portal\"", "script":"", "confidence": "certain"}, 13 | {"vendor": "Talari","product":"Talari SD-WAN", "query":"http.favicon.hash:269992656", "script":"vtalari.nse", "confidence": "certain"}, 14 | {"vendor": "Talari","product":"Talari SD-WAN", "query":"ssl:\"emailAddress=support@talari.com\"", "script":"vtalari.nse", "confidence": "certain"}, 15 | {"vendor": "Citrix","product":"Citrix Netscaler SD-WAN", "query":"http.favicon.hash:-1272756243 title:\"Citrix NetScaler SD-WAN - Login\"", "script":"vcitrix.nse", "confidence": "certain"}, 16 | {"vendor": "Citrix","product":"Citrix Netscaler SD-WAN", "query":"title:\"DC | Login\" and ssl:\"Citrix\"", "script":"vcitrix.nse", "confidence": "certain"}, 17 | {"vendor": "Citrix","product":"Citrix Netscaler SD-WAN Center", "query":"http.favicon.hash:-1272756243 title:\"SD-WAN Center*Login\"", "script":"vcitrix.nse", "confidence": "certain"}, 18 | {"vendor": "Citrix","product":"Citrix Netscaler SD-WAN Center", "query":"VWCSession", "script":"vcitrix.nse", "confidence": "certain"}, 19 | {"vendor": "Riverbed","product":"Riverbed SteelConnect", "query":"title:\"SteelConnect Manager\"", "script":"vriverbed.nse", "confidence": "certain"}, 20 | {"vendor": "Riverbed","product":"Riverbed SteelConnect", "query":"title:\"Riverbed AWS Appliance\"", "script":"vriverbed.nse", "confidence": "certain"}, 21 | {"vendor": "Riverbed","product":"Riverbed SteelHead", "query":"ssl:Riverbed Apache ", "script":"vriverbed.nse", "confidence": "certain"}, 22 | {"vendor": "Riverbed","product":"Riverbed SteelHead", "query":"http.favicon.hash:-1338133217", "script":"vriverbed.nse", "confidence": "certain"}, 23 | {"vendor": "Riverbed","product":"Riverbed SteelHead", "query":"title:\"amnesiac Sign in\"", "script":"vriverbed.nse", "confidence": "certain"}, 24 | {"vendor": "Versa","product":"Versa Director", "query":"\"server: versa Director\"", "script":"", "confidence": "certain"}, 25 | {"vendor": "Versa","product":"Versa Director", "query":"ssl:\"VersaDirector\"", "script":"", "confidence": "certain"}, 26 | {"vendor": "Versa","product":"Versa Director", "query":"ssl:\"versa-director\"", "script":"", "confidence": "certain"}, 27 | {"vendor": "Versa","product":"Versa Flex", "query":"title:\"Flex VNF Web-UI\"", "script":"vversa_flex.nse", "confidence": "certain"}, 28 | {"vendor": "Versa","product":"Versa Analytics", "query":"versa-analytics port:161", "script":"vversa_analytics.nse", "confidence": "certain"}, 29 | {"vendor": "Versa","product":"Versa Analytics", "query":"ssl:\"versa-analytics\"", "script":"vversa_analytics.nse", "confidence": "certain"}, 30 | {"vendor": "Versa","product":"Versa Analytics", "query":"\"van_analytics\" port:9160", "script":"vversa_analytics.nse", "confidence": "certain"}, 31 | {"vendor": "Versa","product":"Versa Analytics", "query":"Versa-Analytics-Server", "script":"vversa_analytics_server.nse", "confidence": "certain"}, 32 | {"vendor": "Cisco","product":"Cisco SD-WAN", "query":"title:\"Viptela vManage\"", "script":"", "confidence": "certain"}, 33 | {"vendor": "Cisco","product":"Cisco SD-WAN", "query":"title:\"Cisco vManage\"", "script":"", "confidence": "certain"}, 34 | {"vendor": "Cisco","product":"Cisco SD-WAN", "query":"title:vManage", "script":"", "confidence": "certain"}, 35 | {"vendor": "Cisco","product":"Cisco SD-WAN", "query":"ssl:\"O=Viptela Inc\"", "script":"", "confidence": "certain"}, 36 | {"vendor": "Cisco","product":"Cisco SD-WAN", "query":"http.favicon.hash:-904700687", "script":"", "confidence": "certain"}, 37 | {"vendor": "Fatpipe","product":"Fatpipe SYMPHONY SD-WAN", "query":"Linux Fatpipe", "script":"vfatpipe.nse", "confidence": "certain"}, 38 | {"vendor": "Fatpipe","product":"Fatpipe SYMPHONY SD-WAN", "query":"title:\"Fatpipe WARP\" port:443", "script":"vfatpipe.nse", "confidence": "certain"}, 39 | {"vendor": "VMWare","product":"VMWare VeloCloud", "query":"title:\"VeloCloud\"", "script":"vvmware_nsx.nse", "confidence": "certain"}, 40 | {"vendor": "VMWare","product":"VMWare VeloCloud", "query":"title:\"VeloCloud Orchestrator\"", "script":"vvmware_nsx.nse", "confidence": "certain"}, 41 | {"vendor": "VMWare","product":"VMWare VeloCloud", "query":"http.html_hash:1218757368", "script":"vvmware_nsx.nse", "confidence": "certain"}, 42 | {"vendor": "VMWare","product":"VMWare VeloCloud", "query":"http.favicon.hash:-2062596654 title:\"301 Moved Permanently\"", "script":"vvmware_nsx.nse", "confidence": "certain"}, 43 | {"vendor": "Teloip","product":"Teloip VINO SD-WAN", "query":"title:\"Teloip Orchestrator API\"", "script":"", "confidence": "certain"}, 44 | {"vendor": "Aryaka","product":"Aryaka SD-WAN", "query":"title:\"Aryaka\"", "script":"", "confidence": "tentative"}, 45 | {"vendor": "Aryaka","product":"Aryaka SD-WAN", "query":"\"Aryaka Networks\"", "script":"", "confidence": "tentative"}, 46 | {"vendor": "Aryaka","product":"Aryaka SD-WAN", "query":"http.favicon.hash:-1423557501", "script":"", "confidence": "tentative"}, 47 | {"vendor": "Aryaka","product":"Aryaka SD-WAN", "query":"title:\"Aryaka, Welcome\"", "script":"", "confidence": "tentative"}, 48 | {"vendor": "Arista","product":"Arista Networks EOS", "query":"\"Arista Networks EOS\"", "script":"", "confidence": "certain"}, 49 | {"vendor": "Sonus ","product":"Sonus SBC Management Application", "query":"title:\"SBC Management Application\"", "script":"vsonus_mgmt.nse", "confidence": "certain"}, 50 | {"vendor": "Sonus ","product":"Sonus SBC Edge", "query":"title:\"SBC Edge\"", "script":"vsonus_edge.nse", "confidence": "certain"}, 51 | {"vendor": "Sonus ","product":"Sonus SBC Edge", "query":"title:\"SBC 1000\"", "script":"vsonus_edge.nse", "confidence": "certain"}, 52 | {"vendor": "InfoVista ","product":"InfoVista SALSA", "query":"\"Server: Apache\"+title:\"SALSA\"*\"Login\" port:443", "script":"", "confidence": "firm"}, 53 | {"vendor": "InfoVista ","product":"InfoVista SALSA", "query":"ssl:\"SALSA Portal\"", "script":"", "confidence": "firm"}, 54 | {"vendor": "InfoVista ","product":"InfoVista SALSA", "query":"title:\"SALSA Login\"", "script":"", "confidence": "firm"}, 55 | {"vendor": "Huawei","product":"Huawei SD-WAN", "query":"\"Agile Controller\"", "script":"", "confidence": "certain"}, 56 | {"vendor": "Arista","product":"Arista Networks EOS", "query":"\"Arista Networks EOS\"", "script":"", "confidence": "certain"}, 57 | {"vendor": "128 Technology","product":"128 Technology Networking Platform", "query":"http.title:\"128T Networking Platform\"", "script":"", "confidence": "tentative"}, 58 | {"vendor": "128 Technology","product":"128 Technology Networking Platform", "query":"http.favicon.hash:-1556425248", "script":"", "confidence": "tentative"}, 59 | {"vendor": "Glue Networks","product":"Gluware Control", "query":"title:\"Gluware Control\"", "script":"vgluware.py", "confidence": "certain"}, 60 | {"vendor": "Barracuda Networks","product":"Barracuda CloudGen Firewall", "query":"ssl:\"Barracuda CloudGen Firewall\" port:\"443\"", "script":"", "confidence": "certain"}, 61 | {"vendor": "Barracuda Networks","product":"Barracuda CloudGen Firewall", "query":"Barracuda CloudGen Firewall", "script":"", "confidence": "certain"}, 62 | {"vendor": "Juniper","product":"Juniper Networks Contrail SD-WAN", "query":"title:\"Log In - Juniper Networks Web Management\"", "script":"", "confidence": "tentative"}, 63 | {"vendor": "Juniper","product":"Juniper Networks Contrail SD-WAN", "query":"\"Juniper Networks, Inc.\" junos srx", "script":"", "confidence": "tentative"}, 64 | {"vendor": "Viprinet","product":"Viprinet Virtual VPN Hub", "query":"Server: \"Viprinet\"", "script":"", "confidence": "certain"}, 65 | {"vendor": "Viprinet","product":"Viprinet Virtual VPN Hub", "query":"Server: \"ViprinetHubReplacement\"", "script":"", "confidence": "certain"}, 66 | {"vendor": "Viprinet","product":"Viprinet Virtual VPN Hub", "query":"title:\"Viprinet - AdminDesk - Login\"", "script":"", "confidence": "certain"}, 67 | {"vendor": "Viprinet","product":"Viprinet Virtual VPN Hub", "query":"http.favicon.hash:-1352019987", "script":"", "confidence": "certain"}, 68 | {"vendor": "Viprinet","product":"Viprinet Virtual VPN Hub", "query":"ssl: \"Viprinet\" port:\"161\"", "script":"", "confidence": "certain"}, 69 | {"vendor": "Cradlepoint", "product": "Cradlepoint SD-WAN", "query":"title:\"Login :: CR4250\"", "script":"vcradlepoint.nse", "confidence":"certain"}, 70 | {"vendor": "Cradlepoint", "product": "Cradlepoint SD-WAN", "query":"title:\"Login :: AER2200\"", "script":"vcradlepoint.nse", "confidence":"certain"}, 71 | {"vendor": "Fortinet", "product": "Fortinet FortiGate SD-WAN", "query":"ssl:\"OU=FortiGate\" ssl:\"O=Fortinet\" ssl:CN=FGT", "script":"", "confidence":"certain"}, 72 | {"vendor": "Fortinet", "product": "Fortinet FortiGate SD-WAN", "query":"http.favicon.hash:945408572 http.title:\"302*\" port:8008", "script":"vfortinet.nse", "confidence":"certain"}, 73 | {"vendor": "Brain4Net", "product": "Brain4Net Orchestrator", "query":"title: B4N ORC", "script":"vbrain.nse", "confidence":"certain"} 74 | ] 75 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. -------------------------------------------------------------------------------- /harvester/core.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import copy 4 | import csv 5 | import json 6 | import os 7 | import re 8 | import sys 9 | import time 10 | from collections import Counter 11 | from importlib import import_module 12 | 13 | import nmap 14 | import shodan 15 | from colorama import Fore, Style 16 | from matplotlib import pyplot as plt 17 | from pycountry_convert import \ 18 | country_alpha2_to_continent_code as code_to_continent 19 | from pycountry_convert import \ 20 | country_name_to_country_alpha2 as country_to_code 21 | 22 | # Interface part 23 | # Can be overwritten by calling module 24 | QUERIES_JSON_FILE = "shodan_queries.json" 25 | RESULTS_DIR = "results" 26 | DEFAULT_CONFIDENCE = "certain" 27 | MAX_COUNTRIES = 10 28 | MAX_VENDORS = 10 29 | MAX_VULNERS = 10 30 | 31 | # Additional scripts 32 | NMAP_SCRIPTS_PATH = "../nse-scripts" 33 | PY_SCRIPTS_PATH = "../py-scripts" 34 | 35 | # Map markers 36 | MAP_MARKERS_DIR = "../samples/map" 37 | 38 | # Sort output files by extensions 39 | JSON_DIR = "json" 40 | CSV_DIR = "csv" 41 | TXT_DIR = "txt" 42 | PNG_DIR = "png" 43 | 44 | # Output json dict dumps 45 | RESULT_JSON_FILE = "Result.json" 46 | COUNTRIES_JSON_FILE = "Countries.json" 47 | CONTINENTS_JSON_FILE = "Continents.json" 48 | VULNERS_JSON_FILE = "Vulnerabilities.json" 49 | VULNERS_BY_VENDORS_JSON = "Vulnerabilities_by_vendors.json" 50 | PRODUCTS_JSON_FILE = "Products.json" 51 | 52 | # Output csv files 53 | RESULT_CSV_FILE = "Result.csv" 54 | GROUPED_BY_VERSION_FILE = "Grouped_by_version.csv" 55 | 56 | # Output txt tops 57 | RESULT_TOP_TXT_FILE = "Result_top.txt" 58 | COUNTRIES_TOP_TXT_FILE = "Countries_top.txt" 59 | CONTINENTS_TOP_TXT_FILE = "Continents_top.txt" 60 | VULNERS_TOP_TXT_FILE = "Vulnerabilities_top.txt" 61 | PRODUCTS_TOP_TXT_FILE = "Products_top.txt" 62 | 63 | # Output piechart pictures 64 | RESULT_PIECHART_FILE = "Vendors.png" 65 | COUNTRIES_PIECHART_FILE = "Countries.png" 66 | CONTINENTS_PIECHART_FILE = "Continents.png" 67 | VULNERS_PIECHART_FILE = "Vulnerabilities.png" 68 | PRODUCTS_PIECHART_FILE = "Products.png" 69 | 70 | # Matplot chart ids 71 | VENDOR_PIE_CHART_ID = 0 72 | COUNTRIES_PIE_CHART_ID = 1 73 | CONTINENTS_PIE_CHART_ID = 2 74 | VULNERS_PIE_CHART_ID = 3 75 | PRODUCTS_PIE_CHART_ID = 4 76 | VULNERS_BY_VENDORS_PIE_CHART_ID = 5 77 | 78 | # Pie chart properties 79 | PIE_DEFAULT_AUTOPCT = "%1.1f%%" 80 | PIE_LABEL_FONT_SIZE = 6 81 | PIE_SUPTITLE_FONT_SIZE = 12 82 | PIE_DPI = 200 83 | 84 | # Pie chart names 85 | BASIC_TITLE = "Percentage of SD-WAN Nodes by" 86 | PIE_VENDORS_TITLE = "{base} Vendors".format(base=BASIC_TITLE) 87 | PIE_PRODUCTS_TITLE = "{base} Products".format(base=BASIC_TITLE) 88 | PIE_COUNTRIES_TITLE = "{base} Countries".format(base=BASIC_TITLE) 89 | PIE_CONTINENTS_TITLE = "{base} Continents".format(base=BASIC_TITLE) 90 | PIE_VULNERABILITIES_TITLE = "{base} Vulnerabilities".format(base=BASIC_TITLE) 91 | PIE_VULNERS_BY_VENDORS_TITLE_ADD = "most common vulnerabilities" 92 | 93 | # Sleep time in case of errors and basic request delay (1 req/sec) 94 | REQUEST_LIMIT_SLEEP_TIME = 5 95 | REQUEST_DELAY_SLEEP_TIME = 1 96 | 97 | # Terminal statuses color 98 | ADD_VULNERABILITIES_COLOR = Fore.CYAN 99 | ADD_SNMP_COLOR = Fore.LIGHTCYAN_EX 100 | PASS_VENDOR_BY_CONFIDENCE_COLOR = Fore.LIGHTBLUE_EX 101 | PRODUCT_FOUND_COLOR = Fore.LIGHTCYAN_EX 102 | ERROR_COLOR = Fore.LIGHTRED_EX 103 | RESET_COLOR = Style.RESET_ALL 104 | 105 | 106 | def write_result_to_file_json(result_array, dest_dir, filename): 107 | """ 108 | Write result array to output json file 109 | 110 | :param result_array: result array (list) 111 | :param dest_dir: destination directory (str) 112 | :param filename: name of json file to save (str) 113 | :return: None 114 | """ 115 | if not result_array or result_array is None: 116 | return 117 | 118 | try: 119 | with open( 120 | "{dest}/{json}/{result_file}".format( 121 | dest=dest_dir, 122 | json=JSON_DIR, 123 | result_file=filename), 124 | mode="w") as file: 125 | file.write(json.dumps(result_array)) 126 | except FileNotFoundError: 127 | print("{color}Error: destination file write failed{reset}".format( 128 | color=ERROR_COLOR, reset=RESET_COLOR)) 129 | 130 | 131 | def write_result_to_file_csv(result_array, dest_dir, 132 | filename=RESULT_CSV_FILE): 133 | """ 134 | Write result array to output csv file 135 | 136 | :param result_array: result array of dicts (dict) 137 | :param dest_dir: destination directory (str) 138 | :param filename: name of .csv file (str) 139 | :return: None 140 | """ 141 | if not result_array or result_array is None: 142 | return 143 | 144 | try: 145 | with open( 146 | "{dest}/{csv}/{result_file}".format( 147 | dest=dest_dir, 148 | csv=CSV_DIR, 149 | result_file=filename), 150 | mode="w") as file: 151 | writer = csv.DictWriter(file, fieldnames=result_array[0].keys()) 152 | writer.writeheader() 153 | for row in result_array: 154 | writer.writerow(row) 155 | except FileNotFoundError: 156 | print("{color}Error: destination file write failed{reset}".format( 157 | color=ERROR_COLOR, reset=RESET_COLOR)) 158 | 159 | 160 | def group_by_version(result_dict): 161 | """ 162 | Group results by version 163 | 164 | :param result_dict: dictionary with results (dict) 165 | :return: dictionary with results grouped by versions (dict) 166 | """ 167 | result = {} 168 | 169 | for element in result_dict: 170 | version = element["additional_info"] 171 | key = "{version};{product}".format(version=version, 172 | product=element["product"]) 173 | if key in result.keys(): 174 | result[key]["ip_list"] += ",{ip}".format(ip=element["ip"]) 175 | else: 176 | result[key] = { 177 | "vendor": element["vendor"], 178 | "product": element["product"], 179 | "ip_list": element["ip"] 180 | } 181 | return result 182 | 183 | 184 | def add_to_array(result_list, result_csv_list, current_elem): 185 | """ 186 | Add results to resulting array (unique hosts and unique pairs of 187 | ips and ports) 188 | 189 | :param result_list: result array of unique hosts (list) 190 | :param result_csv_list: result array of unique ips and ports (list) 191 | :param current_elem: current shodan search result (dict) 192 | :return: None 193 | """ 194 | for res in result_list: 195 | if (current_elem["ip"], current_elem["port"]) == ( 196 | res["ip"], res["port"]): 197 | break 198 | # If ip and port is never repeat in result list 199 | else: 200 | elem_copy = copy.deepcopy(current_elem) 201 | result_csv_list.append(elem_copy) 202 | result_list.append(elem_copy) 203 | 204 | 205 | def nmap_script_exec(nm, ip, port, script): 206 | """ 207 | Execute nmap script and get information 208 | 209 | :param nm: nmap port scanner object 210 | :param ip: ip of host (str) 211 | :param port: port of host (str) 212 | :param script: name of script (str) 213 | :return: appliance version (str) 214 | """ 215 | res = nm.scan(ip, str(port), 216 | arguments="-Pn --script={nmap_scripts}/{script_name}" 217 | .format(nmap_scripts=NMAP_SCRIPTS_PATH, script_name=script)) 218 | script_name = script.split(".")[0] 219 | raw_script = res["scan"][ip]["tcp"][port].get("script") 220 | 221 | if raw_script is None: 222 | return None 223 | raw_version = raw_script[script_name] 224 | version_index = raw_version.find("Version:") 225 | if version_index == -1: 226 | return None 227 | version = raw_version[version_index + len("Version: "):] 228 | return version 229 | 230 | 231 | def python_script_exec(script, ip): 232 | """ 233 | Import additional python script and run it 234 | 235 | :param script: script name from json (str) 236 | :return: version (str) 237 | """ 238 | if script.endswith('.py'): 239 | py_module = script[:-3] 240 | else: 241 | py_module = script 242 | 243 | try: 244 | module = import_module('.' + py_module, package=PY_SCRIPTS_PATH) 245 | except Exception: 246 | return 247 | 248 | if not module: 249 | return 250 | version = module.main(ip) 251 | if not version: 252 | return 253 | return version 254 | 255 | 256 | def get_info(nm, script, vendor, elem): 257 | """ 258 | Check vendor and port before nmap script executing 259 | 260 | :param nm: nmap port scanner object 261 | :param script: name of script (str) 262 | :param vendor: current vendor (str) 263 | :param elem: dict for current elem search results (dict) 264 | :return: call to nmap_script_exec function 265 | """ 266 | if vendor.lower() == "silver peak systems": 267 | data = elem.get("data") 268 | if data is not None and "VXOA " in data: 269 | return data.encode("utf-8", "ignore") 270 | 271 | tmp_http = elem.get("http") 272 | if tmp_http is not None: 273 | redirects = tmp_http.get("redirects") 274 | if not redirects: 275 | return None 276 | rdata = redirects[0].get("data") 277 | search_result = re.search(r"Location:\s*\/([0-9_.]+)\/", rdata) 278 | if search_result: 279 | return search_result.group(1) 280 | if str(elem.get("port")) in ["80", "443", "8080"] and script: 281 | return nmap_script_exec(nm, elem.get("ip_str"), elem.get("port"), 282 | script) 283 | 284 | elif vendor.lower() == "arista": 285 | data = elem.get("data") 286 | if data is not None and "EOS " in data: 287 | version_index = data.find("EOS version ") 288 | version_index_end = data.find(" running") 289 | if version_index == -1: 290 | return None 291 | version = data[version_index + 292 | len("EOS version "):version_index_end] 293 | return version 294 | 295 | # Check if we got nmap or python script 296 | else: 297 | if str(elem.get("port")) in ["80", "161", "443", "8008", "8080"]: 298 | if not script: 299 | return 300 | if script.endswith(".nse"): 301 | return nmap_script_exec(nm, elem.get("ip_str"), 302 | elem.get("port"), script) 303 | if script.endswith(".py"): 304 | return python_script_exec(script, elem.get("ip_str")) 305 | 306 | 307 | def delete_build(dver): 308 | """ 309 | Remove build from raw version 310 | 311 | :param dver: version (str) 312 | :return: version without build number (str) 313 | """ 314 | if dver is None: 315 | return dver 316 | 317 | spl_ = dver.split("_") 318 | splr = dver.split("r") 319 | spld = dver.split(".") 320 | splm = dver.split("-") 321 | 322 | if dver[:2] == "r7": 323 | return dver[1] + "." + dver[3] 324 | if len(splm) > 2: 325 | return splm[-1].split("r")[0] 326 | if len(splr) == 2 and splr[0] and splr[1]: 327 | return splr[0] 328 | if len(spl_) == 2: 329 | return spl_[0] 330 | if len(spld) > 3 and len(spld[3]) > 4: 331 | return ".".join(spld[:-2]) 332 | 333 | return dver 334 | 335 | 336 | def make_autopct(values): 337 | """ 338 | Make plot with percents and count (e.g 15% (20)) 339 | 340 | :param values: values to count (list) 341 | :return: percent and count (func) 342 | """ 343 | 344 | def percent_and_count(pct): 345 | total = sum(values) 346 | val = int(round(pct * total / 100.0)) 347 | return '{p:1.1f}% ({v:d})'.format(p=pct, v=val) 348 | 349 | return percent_and_count 350 | 351 | 352 | def create_top_and_chart(results, max_vendors, dest): 353 | """ 354 | Create pyplot pie chart by vendors 355 | 356 | :param results: list of search results (list) 357 | :param max_vendors: max number of vendors in statistic (int) 358 | :param dest: destination directory (list) 359 | :return: None 360 | """ 361 | GLOBAL_TOP = {} 362 | 363 | for result in results: 364 | key = result["vendor"] 365 | if GLOBAL_TOP.get(key) is None: 366 | GLOBAL_TOP[key] = 1 367 | else: 368 | GLOBAL_TOP[key] += 1 369 | 370 | top_max = "" 371 | max_vendors_list = sorted( 372 | GLOBAL_TOP.items(), key=lambda x: -x[1])[:max_vendors] 373 | for key, _ in max_vendors_list: 374 | top_max += "Vendor: {name} Found unique pairs (hosts + port): {unique}\n".format( 375 | name=key, unique=GLOBAL_TOP[key]) 376 | 377 | try: 378 | with open( 379 | "{dest}/{txt}/{result_file}".format(dest=dest, 380 | txt=TXT_DIR, 381 | result_file=RESULT_TOP_TXT_FILE), 382 | mode="w") as file: 383 | file.write(top_max) 384 | except FileNotFoundError: 385 | print("{color}Error: destination file write failed{reset}".format( 386 | color=ERROR_COLOR, reset=RESET_COLOR)) 387 | return 388 | 389 | global_values = [value for key, value in max_vendors_list] 390 | global_keys = [key for key, value in max_vendors_list] 391 | max_value = max(global_values) 392 | explode = [0 for x in range(len(global_keys))] 393 | explode[list(global_values).index(max_value)] = 0.1 394 | plt.figure(VENDOR_PIE_CHART_ID) 395 | plt.subplots_adjust(bottom=.05, left=.01, right=.99, top=.90, hspace=.35) 396 | plt.pie(global_values, explode=explode, labels=global_keys, 397 | autopct=make_autopct(global_values), 398 | textprops={'fontsize': PIE_LABEL_FONT_SIZE}) 399 | plt.axis("equal") 400 | plt.suptitle(PIE_VENDORS_TITLE, fontsize=PIE_SUPTITLE_FONT_SIZE) 401 | 402 | plt.gcf().set_dpi(PIE_DPI) 403 | plt.savefig("{dest}/{png}/{result_file}".format(dest=dest, 404 | png=PNG_DIR, 405 | result_file=RESULT_PIECHART_FILE)) 406 | 407 | 408 | def try_load_results(dest_dir, filename): 409 | """ 410 | Try to load file with results (in json format) 411 | 412 | :param dest_dir: directory with main results (str) 413 | :param filename: name of file to load from (str) 414 | :return: result dictionary (dict) 415 | """ 416 | try: 417 | with open("{dest}/{json}/{result_file}".format( 418 | dest=dest_dir, 419 | json=JSON_DIR, 420 | result_file=filename)) as f: 421 | result = json.loads(f.read()) 422 | except EnvironmentError: 423 | return None 424 | 425 | return result 426 | 427 | 428 | def write_continents_top(continents): 429 | """ 430 | Write top continents with count to txt file 431 | 432 | :param continents: dict with continents (dict) 433 | :return: None 434 | """ 435 | top_continents_list = "" 436 | for continent in continents.keys(): 437 | top_continents_list += "Continent: {continent}, found - {count}\n".format( 438 | continent=continent, count=continents[continent]) 439 | try: 440 | with open( 441 | "{dest}/{txt}/{result_file}".format( 442 | dest=RESULTS_DIR, 443 | txt=TXT_DIR, 444 | result_file=CONTINENTS_TOP_TXT_FILE), 445 | mode="w") as file: 446 | file.write(top_continents_list) 447 | except FileNotFoundError: 448 | print("{color}Error: destination file write failed{reset}".format( 449 | color=ERROR_COLOR, reset=RESET_COLOR)) 450 | 451 | 452 | def count_continents(unique_countries): 453 | """ 454 | Find all continents based on country name 455 | 456 | :param unique_countries: dict of unique countries {country: count}(dict) 457 | :return: dict of continents (dict) 458 | """ 459 | full_names = { 460 | "AF": "Africa", 461 | "AN": "Antarctica", 462 | "AS": "Asia", 463 | "EU": "Europe", 464 | "NA": "North America", 465 | "OC": "Oceania", 466 | "SA": "South and Central America" 467 | } 468 | 469 | continents = {} 470 | for country in unique_countries.keys(): 471 | try: 472 | cntry_code = country_to_code(country, cn_name_format="default") 473 | continent_key = code_to_continent(cntry_code) 474 | continent = full_names[continent_key] 475 | except KeyError: 476 | continent = country 477 | 478 | if continent not in continents: 479 | continents[continent] = unique_countries[country] 480 | else: 481 | continents[continent] += unique_countries[country] 482 | 483 | return continents 484 | 485 | 486 | def create_pie_chart(elements, suptitle, png, figure_id): 487 | """ 488 | Create pie chart 489 | 490 | :param elements: dict with elements (dict) 491 | :param suptitle: name of chart (str) 492 | :param png: name of output file (str) 493 | :param figure_id: id of current plot (started with 1) (int) 494 | :return: None 495 | """ 496 | values = [value for value in elements.values()] 497 | keys = [key for key in elements.keys()] 498 | plt.figure(figure_id) 499 | plt.subplots_adjust(bottom=.05, left=.01, right=.99, top=.90, hspace=.35) 500 | 501 | explode = [0 for x in range(len(keys))] 502 | max_value = max(values) 503 | explode[list(values).index(max_value)] = 0.1 504 | 505 | plt.pie(values, labels=keys, 506 | autopct=make_autopct(values), explode=explode, 507 | textprops={'fontsize': PIE_LABEL_FONT_SIZE}) 508 | plt.axis("equal") 509 | plt.suptitle(suptitle, fontsize=PIE_SUPTITLE_FONT_SIZE) 510 | 511 | plt.gcf().set_dpi(PIE_DPI) 512 | plt.savefig("{dest}/{png}/{result_file}".format(dest=RESULTS_DIR, 513 | png=PNG_DIR, 514 | result_file=png)) 515 | 516 | 517 | def count_entries(elements, max_elements, element_name, filename): 518 | """ 519 | Count every entity that was founded on sd-wan search results. 520 | Write to txt file. 521 | 522 | :param elements: list of elements (list) 523 | :param max_elements: maximum elements in dict (int) 524 | :param element_name: name (type) of counting element (str) 525 | :param filename: output filename (str) 526 | :return: sorted by value dict of elements (dict) 527 | """ 528 | elements_dict = Counter(elements) 529 | sorted_by_value = dict( 530 | sorted(elements_dict.items(), key=lambda x: x[1], reverse=True)) 531 | 532 | real_max = len(sorted_by_value.keys()) 533 | if max_elements < real_max: 534 | real_max = max_elements 535 | 536 | full_dict = {key: sorted_by_value[key] for key in list(sorted_by_value)} 537 | fixed_dict = {key: sorted_by_value[key] for key in 538 | list(sorted_by_value)[:real_max]} 539 | 540 | # Write top 541 | top_elements_list = "" 542 | for element in fixed_dict.keys(): 543 | top_elements_list += "{type}: {value}, found - {count}\n".format( 544 | type=element_name, value=element, count=elements_dict[element]) 545 | try: 546 | with open( 547 | "{dest}/{txt}/{result_file}".format( 548 | dest=RESULTS_DIR, 549 | txt=TXT_DIR, 550 | result_file=filename), 551 | mode="w") as file: 552 | file.write(top_elements_list) 553 | except FileNotFoundError: 554 | print("{color}Error: destination file write failed{reset}".format( 555 | color=ERROR_COLOR, reset=RESET_COLOR)) 556 | 557 | return fixed_dict, full_dict 558 | 559 | 560 | def add_hostvuln_to_allvuln(host_vulners, all_vulners): 561 | """ 562 | Extend main counter of all vulnerabilities with new founded host vulnerabilities 563 | 564 | :param host_vulners: vulnerabilities from new host (list) 565 | :param all_vulners: list of all vulnerabilities (list) 566 | :return: None 567 | """ 568 | if isinstance(host_vulners, list): 569 | all_vulners.extend(host_vulners) 570 | elif isinstance(host_vulners, str): 571 | all_vulners.append(host_vulners) 572 | 573 | 574 | def vendor_exist(vuln_scan, vendor_name): 575 | """ 576 | Check if command line argument is findable in our script. 577 | 578 | :param vuln_scan: list of CLI arguments (list) 579 | :param vendor_name: name of current scanning vendor (str) 580 | :return: True or False (bool) 581 | """ 582 | 583 | # If we choose all vendors 584 | if "all" in vuln_scan: 585 | return True 586 | 587 | for arg_vendor in vuln_scan: 588 | if arg_vendor.lower() not in vendor_name.lower(): 589 | continue 590 | else: 591 | return True 592 | 593 | return False 594 | 595 | 596 | def vendor_vulners_scan(vendor_name, vendor_vulners, host_vulners): 597 | """ 598 | Collect vulnerabilities on some vendor 599 | 600 | :param vendor_name: Name of collected vendor (e.g. Silverpeak) (str) 601 | :param vendor_vulners: dict with vendors and vulnerabilities (dict) 602 | :param host_vulners: list of host vulnerabilities (list) 603 | :return: None 604 | """ 605 | if vendor_name not in vendor_vulners: 606 | vendor_vulners[vendor_name] = host_vulners 607 | else: 608 | add_hostvuln_to_allvuln(host_vulners, vendor_vulners[vendor_name]) 609 | 610 | 611 | def snmp_checker(host_data, ip): 612 | """ 613 | Check for snmp public services 614 | 615 | :param host_data: data from host (dict) 616 | :param ip: host ip (str) 617 | """ 618 | data_list = host_data.get("data") 619 | if not data_list: 620 | return 621 | for service in data_list: 622 | snmp_service = service.get("snmp") 623 | if snmp_service: 624 | print("{color}[+] found SNMP at: {addr}{reset}".format(addr=ip, 625 | color=ADD_SNMP_COLOR, 626 | reset=RESET_COLOR)) 627 | return "CWE-798" 628 | 629 | 630 | def host_vulners_scan(api, ip): 631 | """ 632 | Initiate vulnerabilities scan with shodan api host method 633 | 634 | :param api: shodan api instance 635 | :param ip: host ip (str) 636 | :return: list of host vulnerabilities (list) 637 | """ 638 | time.sleep(REQUEST_DELAY_SLEEP_TIME) 639 | 640 | try: 641 | host_data = api.host(ip) 642 | except shodan.exception.APIError as rate_limit_err: 643 | print( 644 | "{color}Request limit error (vulnerabilities): {error_info}{reset}".format( 645 | error_info=rate_limit_err, 646 | color=ERROR_COLOR, 647 | reset=RESET_COLOR)) 648 | time.sleep(REQUEST_LIMIT_SLEEP_TIME) 649 | return host_vulners_scan(api, ip) 650 | except Exception as unknown_error: 651 | print( 652 | "{color}Error: {error_info}{reset}".format( 653 | error_info=unknown_error, color=ERROR_COLOR, 654 | reset=RESET_COLOR)) 655 | return 656 | 657 | snmp_vulner = snmp_checker(host_data, ip) 658 | 659 | host_vulners = host_data.get("vulns") 660 | if snmp_vulner: 661 | if host_vulners is None: 662 | host_vulners = [] 663 | host_vulners.append(snmp_vulner) 664 | 665 | if not host_vulners: 666 | return 667 | 668 | return host_vulners 669 | 670 | 671 | def new_scan(queries, destination, confidence, shodan_key, vuln_scan): 672 | """ 673 | Start new scan with shodan and nmap port scanner 674 | 675 | :param queries: dictionary with shodan queries (dict) 676 | :param destination: destination write directory (str) 677 | :param confidence: confidence level (str) 678 | :param shodan_key: key from shodan API (str) 679 | :param vuln_scan: enable vulnerabilities scan (bool) 680 | 681 | :return result: list with shodan and nmap results (list) 682 | :return countries: list with countries (list) 683 | :return all_vulners: list with CVE vulnerabilities (list) 684 | :return vendor_vulners: dictionary with cve grouped by vend (dict) 685 | """ 686 | api = shodan.Shodan(shodan_key) 687 | nm = nmap.PortScanner() 688 | 689 | result_csv = [] 690 | result = [] 691 | countries = [] 692 | all_vulners = [] 693 | vendor_vulners = {} 694 | prev_vuln_counter = 0 695 | 696 | for query in queries: 697 | 698 | # Confidence levels: 699 | # certain > firm > tentative 700 | # certain = certain 701 | # firm = certain + firm 702 | # tentative = certain + firm + tentative (all) 703 | 704 | confidence = confidence.lower() 705 | if confidence == 'certain': 706 | if query["confidence"] != confidence: 707 | print( 708 | "{color}[-] {product} ignored: confidence level is not equal ({confidence_query} / {confidence_req}){reset}".format( 709 | color=PASS_VENDOR_BY_CONFIDENCE_COLOR, 710 | product=query["product"], 711 | confidence_query=query["confidence"], 712 | confidence_req=confidence, 713 | reset=RESET_COLOR)) 714 | continue 715 | elif confidence == 'firm': 716 | if query["confidence"] not in ['certain', 'firm']: 717 | print( 718 | "{color}[-] {product} ignored: confidence level is not equal ({confidence_query} / {confidence_req}){reset}".format( 719 | color=PASS_VENDOR_BY_CONFIDENCE_COLOR, 720 | product=query["product"], 721 | confidence_query=query["confidence"], 722 | confidence_req=confidence, 723 | reset=RESET_COLOR)) 724 | continue 725 | 726 | try: 727 | print("{color}{product} found: {res_count}{reset}".format( 728 | color=PRODUCT_FOUND_COLOR, 729 | product=query["product"], 730 | res_count=api.count(query["query"]).get("total"), 731 | reset=RESET_COLOR)) 732 | 733 | current_result = api.search_cursor(query["query"]) 734 | 735 | # Save quantity of vulnerabilities before new query to count it 736 | if vuln_scan: 737 | prev_vuln_counter = len(all_vulners) 738 | 739 | # Parse every field from current scanned host 740 | for result_field in current_result: 741 | 742 | # Check for latitude and longitude 743 | location = result_field["location"] 744 | if None in (location["latitude"], location["longitude"]): 745 | continue 746 | 747 | # Collect countries for country-chart 748 | if location["country_name"]: 749 | countries.append(location["country_name"]) 750 | 751 | # Collect additional host info 752 | info = str(get_info(nm, query["script"], query["vendor"], 753 | result_field)) 754 | parsed_additional_info = delete_build(info) 755 | 756 | # Collect CVEs if vulnerabilities scan is on 757 | host_vulners = None 758 | if vuln_scan: 759 | host_vulners = host_vulners_scan(api, result_field.get( 760 | "ip_str")) 761 | if host_vulners: 762 | add_hostvuln_to_allvuln(host_vulners, all_vulners) 763 | if host_vulners and vendor_exist(vuln_scan, 764 | query["vendor"]): 765 | print( 766 | '{color}[+] found {count} vulnerabilities for {name} from: {address}{reset}'.format( 767 | color=ADD_VULNERABILITIES_COLOR, 768 | count=len(host_vulners), 769 | name=query["vendor"], 770 | address=result_field.get("ip_str"), 771 | reset=RESET_COLOR)) 772 | vendor_vulners_scan(query["vendor"], vendor_vulners, 773 | host_vulners) 774 | 775 | # Create result array 776 | add_to_array(result, result_csv, 777 | { 778 | "product": query["product"], 779 | "vendor": query["vendor"], 780 | "port": result_field.get("port"), 781 | "proto": result_field["_shodan"]["module"], 782 | "ip": result_field.get("ip_str"), 783 | "lat": result_field["location"]["latitude"], 784 | "lng": result_field["location"]["longitude"], 785 | "country": location["country_name"], 786 | "vulnerabilities": host_vulners, 787 | "additional_info": parsed_additional_info 788 | }) 789 | 790 | # Calculate vulnerabilities quantity after new query 791 | if vuln_scan: 792 | print( 793 | "{color}[!] vulnerabilities found: {count}{reset}".format( 794 | color=ADD_VULNERABILITIES_COLOR, 795 | count=(len(all_vulners) - prev_vuln_counter), 796 | reset=RESET_COLOR 797 | )) 798 | 799 | except shodan.exception.APIError as rate_limit_err: 800 | print("{color}Request limit error: {error_info}{reset}".format( 801 | color=ERROR_COLOR, 802 | error_info=rate_limit_err, 803 | reset=RESET_COLOR)) 804 | # Default timer = 30 sec. 805 | time.sleep(REQUEST_LIMIT_SLEEP_TIME) 806 | except Exception as unknown_error: 807 | print("{color}Error: {error_info}{reset}".format( 808 | color=ERROR_COLOR, 809 | error_info=unknown_error, 810 | reset=RESET_COLOR)) 811 | if not result: 812 | break 813 | 814 | print("{color}Final result (unique hosts): {result_count}{reset}".format( 815 | color=ADD_VULNERABILITIES_COLOR, 816 | result_count=len(result), 817 | reset=RESET_COLOR)) 818 | print( 819 | "{color}Final result (unique pairs host and port): {unique_count}{reset}".format( 820 | color=ADD_VULNERABILITIES_COLOR, 821 | unique_count=len(result_csv), 822 | reset=RESET_COLOR)) 823 | 824 | write_result_to_file_json(result, destination, RESULT_JSON_FILE) 825 | write_result_to_file_csv(result_csv, destination) 826 | 827 | return result, countries, all_vulners, vendor_vulners 828 | 829 | 830 | def create_subdirectory(subdir, dest): 831 | """ 832 | Create subdirectories for result files 833 | 834 | :param subdir: subdir name (str) 835 | :param dest: main root result directory (str) 836 | :return: None 837 | """ 838 | full_path = "./{dest}/{subdir}".format(dest=dest, 839 | subdir=subdir) 840 | if not os.path.exists(full_path): 841 | os.makedirs(full_path) 842 | 843 | 844 | def create_root_dir(dest): 845 | """ 846 | Create root directory for results 847 | 848 | :param dest: root dir name (str) 849 | :return: None 850 | """ 851 | full_path = "./{dest}".format(dest=dest) 852 | if not os.path.exists(full_path): 853 | os.makedirs(full_path) 854 | 855 | 856 | def update_map_markers(result_data): 857 | """ 858 | Update markers for SD-WAN map 859 | 860 | :param result_data: results with geo data (latitude, longitude) 861 | :return: None 862 | """ 863 | with open("{map_dir}/maps/markers.js".format(map_dir=MAP_MARKERS_DIR), 864 | mode="w") \ 865 | as markers_js: 866 | data = json.dumps(result_data) 867 | markers_js.write("var markers = {data};".format(data=data)) 868 | 869 | 870 | def run(args): 871 | """ 872 | Main harvester core module 873 | 874 | :return: None 875 | """ 876 | 877 | # ['silver', 'peak,', ' talari,', ...] -> ['silver peak', 'talari', ...] 878 | if args.vulners: 879 | parse_arguments = ' '.join(args.vulners).split(',') 880 | args.vulners = [arg.strip() for idx, arg in 881 | enumerate(parse_arguments)] 882 | 883 | # Create directories and subdirectories for output results 884 | create_root_dir(args.destination) 885 | for directory in [JSON_DIR, CSV_DIR, TXT_DIR, PNG_DIR]: 886 | create_subdirectory(directory, args.destination) 887 | 888 | # Try to open .json file with Shodan queries 889 | try: 890 | with open(args.queries) as fp: 891 | queries = json.loads(fp.read()) 892 | except FileNotFoundError as file_error: 893 | print( 894 | "{color}Can not find file {file_name}: {error_msg}{reset}".format( 895 | color=ERROR_COLOR, 896 | file_name=args.queries, 897 | error_msg=file_error, 898 | reset=RESET_COLOR)) 899 | sys.exit(1) 900 | 901 | # Start new scan if new is initiated 902 | result = None 903 | countries = None 904 | vulners = None 905 | vendor_vulners = None 906 | 907 | if args.new is True: 908 | result, countries, vulners, vendor_vulners = new_scan(queries, 909 | args.destination, 910 | args.confidence, 911 | args.shodan_key, 912 | args.vulners) 913 | 914 | # If new scan results is empty or argument not set - load offline results 915 | if not result: 916 | result = try_load_results(args.destination, RESULT_JSON_FILE) 917 | if result is None: 918 | print("{color}File with results not found. Exit{reset}".format( 919 | color=ERROR_COLOR, reset=RESET_COLOR)) 920 | sys.exit(1) 921 | 922 | # If no vendor vulnerabilities - load offline json file with vulnerabilities 923 | if not vendor_vulners: 924 | vendor_vulners = try_load_results(args.destination, 925 | VULNERS_BY_VENDORS_JSON) 926 | if vendor_vulners is None: 927 | print( 928 | "{color}File with vulnerabilities by vendor not found. Ignored{reset}".format( 929 | color=ERROR_COLOR, 930 | reset=RESET_COLOR)) 931 | 932 | # If no countries results - load offline json file with countries 933 | if not countries: 934 | countries = try_load_results(args.destination, COUNTRIES_JSON_FILE) 935 | if countries is None: 936 | print( 937 | "{color}File with countries not found. Ignored{reset}".format( 938 | color=ERROR_COLOR, reset=RESET_COLOR)) 939 | 940 | if args.vulners: 941 | # If vulnerabilities is required, but empty - load offline json results 942 | if not vulners: 943 | vulners = try_load_results(args.destination, VULNERS_JSON_FILE) 944 | if vulners is None: 945 | print( 946 | "{color}File with vulnerabilities not found. Ignored{reset}".format( 947 | color=ERROR_COLOR, 948 | reset=RESET_COLOR)) 949 | 950 | # If vulnerabilities loading is succeeded 951 | if vulners: 952 | unique_vulners_top, all_unique_vulners = count_entries( 953 | vulners, 954 | args.max_vulners, 955 | "Vulnerability", 956 | VULNERS_TOP_TXT_FILE) 957 | create_pie_chart(unique_vulners_top, PIE_VULNERABILITIES_TITLE, 958 | VULNERS_PIECHART_FILE, 959 | VULNERS_PIE_CHART_ID) 960 | # If new scan is initiated - update json file with new results 961 | if args.new is True: 962 | write_result_to_file_json(all_unique_vulners, args.destination, 963 | VULNERS_JSON_FILE) 964 | 965 | # If we got vulnerabilities by vendors - save all results in json 966 | if vendor_vulners: 967 | write_result_to_file_json(vendor_vulners, args.destination, 968 | VULNERS_BY_VENDORS_JSON) 969 | start_id = VULNERS_BY_VENDORS_PIE_CHART_ID 970 | for vendor in vendor_vulners.keys(): 971 | unique_vendor_top, all_unique_vendors = count_entries( 972 | vendor_vulners[vendor], 973 | args.max_vulners, 974 | "Vulnerability", 975 | vendor + '.txt') 976 | create_pie_chart(unique_vendor_top, 977 | vendor + " " + PIE_VULNERS_BY_VENDORS_TITLE_ADD, 978 | vendor + '.png', 979 | start_id) 980 | if args.new is True: 981 | # Write jsons for every vendor 982 | write_result_to_file_json(all_unique_vendors, 983 | args.destination, 984 | vendor + '.json') 985 | start_id += 1 986 | 987 | # If countries loading is succeeded 988 | if countries: 989 | unique_countries_top, all_unique_countries = count_entries( 990 | countries, 991 | args.max_countries, 992 | "Country", 993 | COUNTRIES_TOP_TXT_FILE) 994 | create_pie_chart(unique_countries_top, PIE_COUNTRIES_TITLE, 995 | COUNTRIES_PIECHART_FILE, COUNTRIES_PIE_CHART_ID) 996 | 997 | # Work on continents, based on countries 998 | unique_continents = count_continents(all_unique_countries) 999 | write_result_to_file_json(unique_continents, args.destination, 1000 | CONTINENTS_JSON_FILE) 1001 | write_continents_top(unique_continents) 1002 | create_pie_chart(unique_continents, PIE_CONTINENTS_TITLE, 1003 | CONTINENTS_PIECHART_FILE, 1004 | CONTINENTS_PIE_CHART_ID) 1005 | 1006 | # Save to json if this is our new scan result 1007 | if args.new is True: 1008 | write_result_to_file_json(all_unique_countries, args.destination, 1009 | COUNTRIES_JSON_FILE) 1010 | 1011 | # Count products 1012 | if result: 1013 | try: 1014 | product_list = [] 1015 | # Make full list of products from results 1016 | for product in result: 1017 | product_list.append(product['product']) 1018 | 1019 | unique_products_top, all_unique_products = count_entries( 1020 | product_list, 1021 | args.max_vendors, 1022 | "Product", 1023 | PRODUCTS_TOP_TXT_FILE) 1024 | write_result_to_file_json(all_unique_products, args.destination, 1025 | PRODUCTS_JSON_FILE) 1026 | create_pie_chart(unique_products_top, PIE_PRODUCTS_TITLE, 1027 | PRODUCTS_PIECHART_FILE, 1028 | PRODUCTS_PIE_CHART_ID) 1029 | except Exception: 1030 | pass 1031 | 1032 | try: 1033 | grouped_dict = group_by_version(result) 1034 | grouped_by_ver_res = [ 1035 | { 1036 | "vendor": value["vendor"], 1037 | "product": key.split(";")[1], 1038 | "additional_info": key.split(";")[0], 1039 | "ip_list": value["ip_list"], 1040 | "hosts_amount": len(value["ip_list"].split(",")) 1041 | } for key, value in grouped_dict.items() 1042 | ] 1043 | 1044 | write_result_to_file_csv(grouped_by_ver_res, args.destination, 1045 | GROUPED_BY_VERSION_FILE) 1046 | 1047 | create_top_and_chart(result, args.max_vendors, args.destination) 1048 | except Exception: 1049 | pass 1050 | 1051 | # Update map markers if needed 1052 | if result and args.update_markers: 1053 | update_map_markers(result) 1054 | --------------------------------------------------------------------------------