gophish/static/js/dist/app/campaign_results.min.js

83 lines
20 KiB
JavaScript

var map=null;var doPoll=true;var statuses={"Email Sent":{color:"#1abc9c",label:"label-success",icon:"fa-envelope",point:"ct-point-sent"},"Emails Sent":{color:"#1abc9c",label:"label-success",icon:"fa-envelope",point:"ct-point-sent"},"In progress":{label:"label-primary"},Queued:{label:"label-info"},Completed:{label:"label-success"},"Email Opened":{color:"#f9bf3b",label:"label-warning",icon:"fa-envelope-open",point:"ct-point-opened"},"Clicked Link":{color:"#F39C12",label:"label-clicked",icon:"fa-mouse-pointer",point:"ct-point-clicked"},Success:{color:"#f05b4f",label:"label-danger",icon:"fa-exclamation",point:"ct-point-clicked"},"Email Reported":{color:"#45d6ef",label:"label-info",icon:"fa-bullhorn",point:"ct-point-reported"},Error:{color:"#6c7a89",label:"label-default",icon:"fa-times",point:"ct-point-error"},"Error Sending Email":{color:"#6c7a89",label:"label-default",icon:"fa-times",point:"ct-point-error"},"Submitted Data":{color:"#f05b4f",label:"label-danger",icon:"fa-exclamation",point:"ct-point-clicked"},Unknown:{color:"#6c7a89",label:"label-default",icon:"fa-question",point:"ct-point-error"},Sending:{color:"#428bca",label:"label-primary",icon:"fa-spinner",point:"ct-point-sending"},Retrying:{color:"#6c7a89",label:"label-default",icon:"fa-clock-o",point:"ct-point-error"},Scheduled:{color:"#428bca",label:"label-primary",icon:"fa-clock-o",point:"ct-point-sending"},"Campaign Created":{label:"label-success",icon:"fa-rocket"}};var statusMapping={"Email Sent":"sent","Email Opened":"opened","Clicked Link":"clicked","Submitted Data":"submitted_data","Email Reported":"reported"};var progressListing=["Email Sent","Email Opened","Clicked Link","Submitted Data"];var campaign={};var bubbles=[];function dismiss(){$("#modal\\.flashes").empty();$("#modal").modal("hide");$("#resultsTable").dataTable().DataTable().clear().draw()}function deleteCampaign(){Swal.fire({title:"Are you sure?",text:"This will delete the campaign. This can't be undone!",type:"warning",animation:false,showCancelButton:true,confirmButtonText:"Delete Campaign",confirmButtonColor:"#428bca",reverseButtons:true,allowOutsideClick:false,showLoaderOnConfirm:true,preConfirm:function(){return new Promise(function(resolve,reject){api.campaignId.delete(campaign.id).success(function(msg){resolve()}).error(function(data){reject(data.responseJSON.message)})})}}).then(function(result){if(result.value){Swal.fire("Campaign Deleted!","This campaign has been deleted!","success")}$('button:contains("OK")').on("click",function(){location.href="/campaigns"})})}function completeCampaign(){Swal.fire({title:"Are you sure?",text:"Gophish will stop processing events for this campaign",type:"warning",animation:false,showCancelButton:true,confirmButtonText:"Complete Campaign",confirmButtonColor:"#428bca",reverseButtons:true,allowOutsideClick:false,showLoaderOnConfirm:true,preConfirm:function(){return new Promise(function(resolve,reject){api.campaignId.complete(campaign.id).success(function(msg){resolve()}).error(function(data){reject(data.responseJSON.message)})})}}).then(function(result){if(result.value){Swal.fire("Campaign Completed!","This campaign has been completed!","success");$("#complete_button")[0].disabled=true;$("#complete_button").text("Completed!");doPoll=false}})}function function exportAsCSV(scope) {
var csvScope = null;
var filename = campaign.name + ' - ' + capitalize(scope) + '.csv';
switch (scope) {
case "results":
csvScope = campaign.results;
break;
case "events":
csvScope = campaign.timeline;
break;
}
if (!csvScope) {
return;
}
// Create an array to hold the CSV data
var csvData = [];
// Add the CSV header
var header = ['Email', 'Email Opened', 'Clicked Link', 'Submitted Data'];
csvData.push(header);
// Define a helper function to convert boolean to string
function boolToString(value) {
return value ? 'true' : 'false';
}
// Add CSV rows for each entry in csvScope
csvScope.forEach(function (entry) {
var email = entry.email;
var status = entry.status;
// Initialize status flags
var emailOpened = false;
var clickedLink = false;
var submittedData = false;
// Update status flags based on the status value
switch (status) {
case 'Email Opened':
emailOpened = true;
break;
case 'Clicked Link':
emailOpened = true; // If clicked link, email is also opened
clickedLink = true;
break;
case 'Submitted Data':
emailOpened = true; // If submitted data, email is also opened
clickedLink = true; // If submitted data, link is also clicked
submittedData = true;
break;
}
// Add the CSV row
var csvRow = [email, boolToString(emailOpened), boolToString(clickedLink), boolToString(submittedData)];
csvData.push(csvRow);
});
// Convert the CSV data array to a CSV string
var csvString = csvData.map(function (row) {
return row.join(',');
}).join('\n');
// Create a Blob with the CSV string
var csvBlob = new Blob([csvString], {
type: 'text/csv;charset=utf-8;'
});
// Create a download link
var csvURL = window.URL.createObjectURL(csvBlob);
var dlLink = document.createElement('a');
dlLink.href = csvURL;
dlLink.setAttribute('download', filename);
// Trigger the download
dlLink.click();
// Clean up
window.URL.revokeObjectURL(csvURL);
}function replay(event_idx){request=campaign.timeline[event_idx];details=JSON.parse(request.details);url=null;form=$("<form>").attr({method:"POST",target:"_blank"});$.each(Object.keys(details.payload),function(i,param){if(param=="rid"){return true}if(param=="__original_url"){url=details.payload[param];return true}$("<input>").attr({name:param}).val(details.payload[param]).appendTo(form)});Swal.fire({title:"Where do you want the credentials submitted to?",input:"text",showCancelButton:true,inputPlaceholder:"http://example.com/login",inputValue:url||"",inputValidator:function(value){return new Promise(function(resolve,reject){if(value){resolve()}else{reject("Invalid URL.")}})}}).then(function(result){if(result.value){url=result.value;submitForm()}});return;submitForm();function submitForm(){form.attr({action:url});form.appendTo("body").submit().remove()}}var renderDevice=function(event_details){var ua=UAParser(details.browser["user-agent"]);var detailsString='<div class="timeline-device-details">';var deviceIcon="laptop";if(ua.device.type){if(ua.device.type=="tablet"||ua.device.type=="mobile"){deviceIcon=ua.device.type}}var deviceVendor="";if(ua.device.vendor){deviceVendor=ua.device.vendor.toLowerCase();if(deviceVendor=="microsoft")deviceVendor="windows"}var deviceName="Unknown";if(ua.os.name){deviceName=ua.os.name;if(deviceName=="Mac OS"){deviceVendor="apple"}else if(deviceName=="Windows"){deviceVendor="windows"}if(ua.device.vendor&&ua.device.model){deviceName=ua.device.vendor+" "+ua.device.model}}if(ua.os.version){deviceName=deviceName+" (OS Version: "+ua.os.version+")"}deviceString='<div class="timeline-device-os"><span class="fa fa-stack">'+'<i class="fa fa-'+escapeHtml(deviceIcon)+' fa-stack-2x"></i>'+'<i class="fa fa-vendor-icon fa-'+escapeHtml(deviceVendor)+' fa-stack-1x"></i>'+"</span> "+escapeHtml(deviceName)+"</div>";detailsString+=deviceString;var deviceBrowser="Unknown";var browserIcon="info-circle";var browserVersion="";if(ua.browser&&ua.browser.name){deviceBrowser=ua.browser.name;deviceBrowser=deviceBrowser.replace("Mobile ","");if(deviceBrowser){browserIcon=deviceBrowser.toLowerCase();if(browserIcon=="ie")browserIcon="internet-explorer"}browserVersion="(Version: "+ua.browser.version+")"}var browserString='<div class="timeline-device-browser"><span class="fa fa-stack">'+'<i class="fa fa-'+escapeHtml(browserIcon)+' fa-stack-1x"></i></span> '+deviceBrowser+" "+browserVersion+"</div>";detailsString+=browserString;detailsString+="</div>";return detailsString};function renderTimeline(data){record={id:data[0],first_name:data[2],last_name:data[3],email:data[4],position:data[5],status:data[6],reported:data[7],send_date:data[8]};results='<div class="timeline col-sm-12 well well-lg">'+"<h6>Timeline for "+escapeHtml(record.first_name)+" "+escapeHtml(record.last_name)+'</h6><span class="subtitle">Email: '+escapeHtml(record.email)+"<br>Result ID: "+escapeHtml(record.id)+"</span>"+'<div class="timeline-graph col-sm-6">';$.each(campaign.timeline,function(i,event){if(!event.email||event.email==record.email){results+='<div class="timeline-entry">'+' <div class="timeline-bar"></div>';results+=' <div class="timeline-icon '+statuses[event.message].label+'">'+' <i class="fa '+statuses[event.message].icon+'"></i></div>'+' <div class="timeline-message">'+escapeHtml(event.message)+' <span class="timeline-date">'+moment.utc(event.time).local().format("MMMM Do YYYY h:mm:ss a")+"</span>";if(event.details){details=JSON.parse(event.details);if(event.message=="Clicked Link"||event.message=="Submitted Data"){deviceView=renderDevice(details);if(deviceView){results+=deviceView}}if(event.message=="Submitted Data"){results+='<div class="timeline-replay-button"><button onclick="replay('+i+')" class="btn btn-success">';results+='<i class="fa fa-refresh"></i> Replay Credentials</button></div>';results+='<div class="timeline-event-details"><i class="fa fa-caret-right"></i> View Details</div>'}if(details.payload){results+='<div class="timeline-event-results">';results+=' <table class="table table-condensed table-bordered table-striped">';results+=" <thead><tr><th>Parameter</th><th>Value(s)</tr></thead><tbody>";$.each(Object.keys(details.payload),function(i,param){if(param=="rid"){return true}results+=" <tr>";results+=" <td>"+escapeHtml(param)+"</td>";results+=" <td>"+escapeHtml(details.payload[param])+"</td>";results+=" </tr>"});results+=" </tbody></table>";results+="</div>"}if(details.error){results+='<div class="timeline-event-details"><i class="fa fa-caret-right"></i> View Details</div>';results+='<div class="timeline-event-results">';results+='<span class="label label-default">Error</span> '+details.error;results+="</div>"}}results+="</div></div>"}});if(record.status=="Scheduled"||record.status=="Retrying"){results+='<div class="timeline-entry">'+' <div class="timeline-bar"></div>';results+=' <div class="timeline-icon '+statuses[record.status].label+'">'+' <i class="fa '+statuses[record.status].icon+'"></i></div>'+' <div class="timeline-message">'+"Scheduled to send at "+record.send_date+"</span>"}results+="</div></div>";return results}var renderTimelineChart=function(chartopts){return Highcharts.chart("timeline_chart",{chart:{zoomType:"x",type:"line",height:"200px"},title:{text:"Campaign Timeline"},xAxis:{type:"datetime",dateTimeLabelFormats:{second:"%l:%M:%S",minute:"%l:%M",hour:"%l:%M",day:"%b %d, %Y",week:"%b %d, %Y",month:"%b %Y"}},yAxis:{min:0,max:2,visible:false,tickInterval:1,labels:{enabled:false},title:{text:""}},tooltip:{formatter:function(){return Highcharts.dateFormat("%A, %b %d %l:%M:%S %P",new Date(this.x))+"<br>Event: "+this.point.message+"<br>Email: <b>"+this.point.email+"</b>"}},legend:{enabled:false},plotOptions:{series:{marker:{enabled:true,symbol:"circle",radius:3},cursor:"pointer"},line:{states:{hover:{lineWidth:1}}}},credits:{enabled:false},series:[{data:chartopts["data"],dashStyle:"shortdash",color:"#cccccc",lineWidth:1,turboThreshold:0}]})};var renderPieChart=function(chartopts){return Highcharts.chart(chartopts["elemId"],{chart:{type:"pie",events:{load:function(){var chart=this,rend=chart.renderer,pie=chart.series[0],left=chart.plotLeft+pie.center[0],top=chart.plotTop+pie.center[1];this.innerText=rend.text(chartopts["data"][0].count,left,top).attr({"text-anchor":"middle","font-size":"24px","font-weight":"bold",fill:chartopts["colors"][0],"font-family":"Helvetica,Arial,sans-serif"}).add()},render:function(){this.innerText.attr({text:chartopts["data"][0].count})}}},title:{text:chartopts["title"]},plotOptions:{pie:{innerSize:"80%",dataLabels:{enabled:false}}},credits:{enabled:false},tooltip:{formatter:function(){if(this.key==undefined){return false}return'<span style="color:'+this.color+'">●</span>'+this.point.name+": <b>"+this.y+"%</b><br/>"}},series:[{data:chartopts["data"],colors:chartopts["colors"]}]})};var updateMap=function(results){if(!map){return}bubbles=[];$.each(campaign.results,function(i,result){if(result.latitude==0&&result.longitude==0){return true}newIP=true;$.each(bubbles,function(i,bubble){if(bubble.ip==result.ip){bubbles[i].radius+=1;newIP=false;return false}});if(newIP){bubbles.push({latitude:result.latitude,longitude:result.longitude,name:result.ip,fillKey:"point",radius:2})}});map.bubbles(bubbles)};function createStatusLabel(status,send_date){var label=statuses[status].label||"label-default";var statusColumn='<span class="label '+label+'">'+status+"</span>";if(status=="Scheduled"||status=="Retrying"){var sendDateMessage="Scheduled to send at "+send_date;statusColumn='<span class="label '+label+'" data-toggle="tooltip" data-placement="top" data-html="true" title="'+sendDateMessage+'">'+status+"</span>"}return statusColumn}function poll(){api.campaignId.results(campaign.id).success(function(c){campaign=c;var timeline_series_data=[];$.each(campaign.timeline,function(i,event){var event_date=moment.utc(event.time).local();timeline_series_data.push({email:event.email,message:event.message,x:event_date.valueOf(),y:1,marker:{fillColor:statuses[event.message].color}})});var timeline_chart=$("#timeline_chart").highcharts();timeline_chart.series[0].update({data:timeline_series_data});var email_series_data={};Object.keys(statusMapping).forEach(function(k){email_series_data[k]=0});$.each(campaign.results,function(i,result){email_series_data[result.status]++;if(result.reported){email_series_data["Email Reported"]++}var step=progressListing.indexOf(result.status);for(var i=0;i<step;i++){email_series_data[progressListing[i]]++}});$.each(email_series_data,function(status,count){var email_data=[];if(!(status in statusMapping)){return true}email_data.push({name:status,y:Math.floor(count/campaign.results.length*100),count:count});email_data.push({name:"",y:100-Math.floor(count/campaign.results.length*100)});var chart=$("#"+statusMapping[status]+"_chart").highcharts();chart.series[0].update({data:email_data})});resultsTable=$("#resultsTable").DataTable();resultsTable.rows().every(function(i,tableLoop,rowLoop){var row=this.row(i);var rowData=row.data();var rid=rowData[0];$.each(campaign.results,function(j,result){if(result.id==rid){rowData[8]=moment(result.send_date).format("MMMM Do YYYY, h:mm:ss a");rowData[7]=result.reported;rowData[6]=result.status;resultsTable.row(i).data(rowData);if(row.child.isShown()){$(row.node()).find("#caret").removeClass("fa-caret-right");$(row.node()).find("#caret").addClass("fa-caret-down");row.child(renderTimeline(row.data()))}return false}})});resultsTable.draw(false);updateMap(campaign.results);$('[data-toggle="tooltip"]').tooltip();$("#refresh_message").hide();$("#refresh_btn").show()})}function load(){campaign.id=window.location.pathname.split("/").slice(-1)[0];var use_map=JSON.parse(localStorage.getItem("gophish.use_map"));api.campaignId.results(campaign.id).success(function(c){campaign=c;if(campaign){$("title").text(c.name+" - Gophish");$("#loading").hide();$("#campaignResults").show();$("#page-title").text("Results for "+c.name);if(c.status=="Completed"){$("#complete_button")[0].disabled=true;$("#complete_button").text("Completed!");doPoll=false}$("#resultsTable").on("click",".timeline-event-details",function(){payloadResults=$(this).parent().find(".timeline-event-results");if(payloadResults.is(":visible")){$(this).find("i").removeClass("fa-caret-down");$(this).find("i").addClass("fa-caret-right");payloadResults.hide()}else{$(this).find("i").removeClass("fa-caret-right");$(this).find("i").addClass("fa-caret-down");payloadResults.show()}});resultsTable=$("#resultsTable").DataTable({destroy:true,order:[[2,"asc"]],columnDefs:[{orderable:false,targets:"no-sort"},{className:"details-control",targets:[1]},{visible:false,targets:[0,8]},{render:function(data,type,row){return createStatusLabel(data,row[8])},targets:[6]},{className:"text-center",render:function(reported,type,row){if(type=="display"){if(reported){return"<i class='fa fa-check-circle text-center text-success'></i>"}return"<i role='button' class='fa fa-times-circle text-center text-muted' onclick='report_mail(\""+row[0]+'", "'+campaign.id+"\");'></i>"}return reported},targets:[7]}]});resultsTable.clear();var email_series_data={};var timeline_series_data=[];Object.keys(statusMapping).forEach(function(k){email_series_data[k]=0});$.each(campaign.results,function(i,result){resultsTable.row.add([result.id,'<i id="caret" class="fa fa-caret-right"></i>',escapeHtml(result.first_name)||"",escapeHtml(result.last_name)||"",escapeHtml(result.email)||"",escapeHtml(result.position)||"",result.status,result.reported,moment(result.send_date).format("MMMM Do YYYY, h:mm:ss a")]);email_series_data[result.status]++;if(result.reported){email_series_data["Email Reported"]++}var step=progressListing.indexOf(result.status);for(var i=0;i<step;i++){email_series_data[progressListing[i]]++}});resultsTable.draw();$('[data-toggle="tooltip"]').tooltip();$("#resultsTable tbody").on("click","td.details-control",function(){var tr=$(this).closest("tr");var row=resultsTable.row(tr);if(row.child.isShown()){row.child.hide();tr.removeClass("shown");$(this).find("i").removeClass("fa-caret-down");$(this).find("i").addClass("fa-caret-right")}else{$(this).find("i").removeClass("fa-caret-right");$(this).find("i").addClass("fa-caret-down");row.child(renderTimeline(row.data())).show();tr.addClass("shown")}});$.each(campaign.timeline,function(i,event){if(event.message=="Campaign Created"){return true}var event_date=moment.utc(event.time).local();timeline_series_data.push({email:event.email,message:event.message,x:event_date.valueOf(),y:1,marker:{fillColor:statuses[event.message].color}})});renderTimelineChart({data:timeline_series_data});$.each(email_series_data,function(status,count){var email_data=[];if(!(status in statusMapping)){return true}email_data.push({name:status,y:Math.floor(count/campaign.results.length*100),count:count});email_data.push({name:"",y:100-Math.floor(count/campaign.results.length*100)});var chart=renderPieChart({elemId:statusMapping[status]+"_chart",title:status,name:status,data:email_data,colors:[statuses[status].color,"#dddddd"]})});if(use_map){$("#resultsMapContainer").show();map=new Datamap({element:document.getElementById("resultsMap"),responsive:true,fills:{defaultFill:"#ffffff",point:"#283F50"},geographyConfig:{highlightFillColor:"#1abc9c",borderColor:"#283F50"},bubblesConfig:{borderColor:"#283F50"}})}updateMap(campaign.results)}}).error(function(){$("#loading").hide();errorFlash(" Campaign not found!")})}var setRefresh;function refresh(){if(!doPoll){return}$("#refresh_message").show();$("#refresh_btn").hide();poll();clearTimeout(setRefresh);setRefresh=setTimeout(refresh,6e4)}function report_mail(rid,cid){Swal.fire({title:"Are you sure?",text:"This result will be flagged as reported (RID: "+rid+")",type:"question",animation:false,showCancelButton:true,confirmButtonText:"Continue",confirmButtonColor:"#428bca",reverseButtons:true,allowOutsideClick:false,showLoaderOnConfirm:true}).then(function(result){if(result.value){api.campaignId.get(cid).success(function(c){report_url=new URL(c.url);report_url.pathname="/report";report_url.search="?rid="+rid;fetch(report_url).then(response=>{if(!response.ok){throw new Error(`HTTP error! Status: ${response.status}`)}refresh()}).catch(error=>{let errorMessage=error.message;if(error.message==="Failed to fetch"){errorMessage="This might be due to Mixed Content issues or network problems."}Swal.fire({title:"Error",text:errorMessage,type:"error",confirmButtonText:"Close"})})})}})}$(document).ready(function(){Highcharts.setOptions({global:{useUTC:false}});load();setRefresh=setTimeout(refresh,6e4)});