diff --git a/.gitignore b/.gitignore index 2fc4abd..2699056 100644 --- a/.gitignore +++ b/.gitignore @@ -81,3 +81,6 @@ target/ #Ipython Notebook .ipynb_checkpoints + +# webmap PDF report +static/*.pdf diff --git a/api.py b/api.py index 2174ee5..5f394b7 100644 --- a/api.py +++ b/api.py @@ -1,6 +1,6 @@ from django.shortcuts import render from django.http import HttpResponse -import xmltodict, json, html, os, hashlib, re +import xmltodict, json, html, os, hashlib, re, requests from collections import OrderedDict def rmNotes(request, hashstr): @@ -103,3 +103,27 @@ def genPDF(request): os.popen('/opt/wkhtmltox/bin/wkhtmltopdf --cookie sessionid '+request.session._session_key+' --enable-javascript --javascript-delay 6000 http://127.0.0.1:8000/view/pdf/ /opt/nmapdashboard/nmapreport/static/'+pdffile+'.pdf') res = {'ok':'PDF created', 'file':'/static/'+pdffile+'.pdf'} return HttpResponse(json.dumps(res), content_type="application/json") + +def getCVE(request): + res = {} + + if request.method == "POST": + scanfilemd5 = hashlib.md5(str(request.session['scanfile']).encode('utf-8')).hexdigest() + hostmd5 = hashlib.md5(str(request.POST['host']).encode('utf-8')).hexdigest() + portmd5 = hashlib.md5(str(request.POST['port']).encode('utf-8')).hexdigest() + + # request.POST['host'] + r = requests.get('http://cve.circl.lu/api/cvefor/'+request.POST['cpe']) + + if request.POST['host'] not in res: + res[request.POST['host']] = {} + + cvejson = r.json() + + if type(cvejson) is list and len(cvejson) > 0: + res[request.POST['host']][request.POST['port']] = cvejson[0] + f = open('/opt/notes/'+scanfilemd5+'_'+hostmd5+'.'+request.POST['port']+'.cve', 'w') + f.write(json.dumps(cvejson)) + f.close() + + return HttpResponse(json.dumps(res), content_type="application/json") diff --git a/pdf.py b/pdf.py index 738b7ea..3f66d12 100644 --- a/pdf.py +++ b/pdf.py @@ -22,6 +22,21 @@ def reportPDFView(request): counters = {'po':0,'pc':0,'pf':0,'hostsup':0,'ostype':{},'pi':{},'ss':{}} scanmd5 = hashlib.md5(str(request.session['scanfile']).encode('utf-8')).hexdigest() + + # collect all cve in cvehost dict + cvehost = {} + cvefiles = os.listdir('/opt/notes') + for cf in cvefiles: + m = re.match('^('+scanmd5+')_([a-z0-9]{32,32})\.([0-9]+)\.cve$', cf) + if m is not None: + if m.group(1) not in cvehost: + cvehost[m.group(1)] = {} + + if m.group(2) not in cvehost[m.group(1)]: + cvehost[m.group(1)][m.group(2)] = {} + + cvehost[m.group(1)][m.group(2)][m.group(3)] = open('/opt/notes/'+cf, 'r').read() + for ik in o['host']: # this fix single host report @@ -184,6 +199,35 @@ def reportPDFView(request): '' + cveout,cveout_html = '','' + if scanmd5 in cvehost: + if addressmd5 in cvehost[scanmd5]: + for cveport in cvehost[scanmd5][addressmd5]: + cvejson = json.loads(cvehost[scanmd5][addressmd5][cveport]) + for cveobj in cvejson: + + cverefout = '' + for cveref in cveobj['references']: + cverefout += ''+cveref+'
' + + cveexdbout = '' + if 'exploit-db' in cveobj: + cveexdbout = '
Exploit DB:
' + for cveexdb in cveobj['exploit-db']: + if 'title' in cveexdb: + cveexdbout += ''+html.escape(cveexdb['title'])+'
' + cveexdbout += '
' + + cveout += '
'+\ + ' '+html.escape(cveobj['id'])+' '+html.escape(cveobj['summary'])+'

'+\ + '
References:
'+cverefout+'
'+\ + cveexdbout+\ + '
' + + cveout_html = '
'+\ + '

CVE List for '+saddress+':

'+\ + cveout+\ + '
' if i['status']['@state'] == 'up': hostdetails_html += '
'+\ @@ -196,7 +240,8 @@ def reportPDFView(request): hostdetails_html_tr+\ '
'+\ '
'+portdetails_html_tr+'
'+\ - notesout + notesout+\ + cveout_html if portsfound is True: # r['out'] += '1,' @@ -334,7 +379,7 @@ def reportPDFView(request): r['html'] += ''+\ '
'+\ '
'+\ - '
Generated with
'+\ + '
Generated by
'+\ '
'+\ ' https://github.com/Rev3rseSecurity/WebMap'+\ '
'+\ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..5109f05 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +requests +xmltodict diff --git a/static/async.js b/static/async.js index 14fb5b5..67d4e9c 100644 --- a/static/async.js +++ b/static/async.js @@ -2,6 +2,74 @@ $(document).ready(function() { // doc ready }); +var cpetot = 0; +var cpetimer; +function checkCVE() { + cpe = JSON.parse(atob(decodeURIComponent($('#cpestring').val()))); + csrftoken = $('input[name="csrfmiddlewaretoken"]').val(); + console.log(cpe); + /* $.get('http://cve.circl.lu/api/cvefor/cpe:/a:openbsd:openssh:7.6').done(function(d) { + console.log(d); + }); */ + + $('#modal1').css('background-color','#3e3e3e'); + $('#modaltitle').html('Looking for CVE and Exploits'); + $('#modalbody').html( + 'This process could take a while, please wait...'+ + '
' + ); + $('#modalfooter').html(''); + $('#modal1').modal('open'); + + cpetot = Object.keys(cpe).length; + console.log(cpetot); + + for(host in cpe) { + for(port in cpe[host]) { + for(cpestr in cpe[host][port]) { + if(/^cpe:.+:.+:.+:.*$/.test(cpestr)) { + console.log(cpestr); + $.post('/report/api/getcve/', { + 'cpe': cpestr, + 'host':host, + 'port':port, + 'csrfmiddlewaretoken': csrftoken + }).done(function(d) { + console.log(d); + for(rhost in d) { + for(rport in d[rhost]) { + $('#modalbody').append('
Received: '+d[rhost][rport]['id']+' host:'+rhost+' port:'+rport+'
'); + } + } + }).always(function() { cpetot = (cpetot - 1); }); + } else { + cpetot = (cpetot - 1); + } + + console.log(cpetot); + } + } + } + + cpetimer = setInterval(function() { + if(checkCPETOT()) { + console.log('END'); + window.clearInterval(cpetimer); + $('#modalbody').html('Done. Please, reload this page by clicking on Reload button.'); + $('#modalfooter').html(''); + } + }, 2000); + +} + +function checkCPETOT() { + if(cpetot <= 0) { + return true; + } else { + return false; + } +} + function genPDF(md5scan) { if(/^[a-f0-9]{32,32}$/.test(md5scan)) { $.get('/report/api/pdf/').done(function(data) { diff --git a/urls.py b/urls.py index e2e3626..17924dd 100644 --- a/urls.py +++ b/urls.py @@ -11,6 +11,7 @@ path('api/setlabel//