From 576aa469e9a70ddfbb5169bbf4a63fcf959192c0 Mon Sep 17 00:00:00 2001 From: Jordan Wright Date: Sat, 6 Aug 2016 18:06:18 -0500 Subject: [PATCH] Adding the ability to replay credentials from the campaign results page --- controllers/api.go | 10 ++++++ static/css/main.css | 3 ++ static/js/app/campaign_results.js | 55 +++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/controllers/api.go b/controllers/api.go index dabb5d8b..72681c7c 100644 --- a/controllers/api.go +++ b/controllers/api.go @@ -560,6 +560,16 @@ func API_Import_Site(w http.ResponseWriter, r *http.Request) { if d.Find("head base").Length() == 0 { d.Find("head").PrependHtml(fmt.Sprintf("", cr.URL)) } + forms := d.Find("form") + forms.Each(func(i int, f *goquery.Selection) { + // We'll want to store where we got the form from + // (the current URL) + url := f.AttrOr("action", cr.URL) + if !strings.HasPrefix(url, "http") { + url = fmt.Sprintf("%s%s", cr.URL, url) + } + f.PrependHtml(fmt.Sprintf("", url)) + }) h, err := d.Html() if err != nil { JSONResponse(w, models.Response{Success: false, Message: err.Error()}, http.StatusInternalServerError) diff --git a/static/css/main.css b/static/css/main.css index b8198b55..5c2bb719 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -485,6 +485,9 @@ td.details-control{ margin-top:5px; cursor:pointer; } +.timeline-replay-button { + margin-top:10px; +} .timeline-event-details>.table-responsive{ display:none; } diff --git a/static/js/app/campaign_results.js b/static/js/app/campaign_results.js index e774e82a..2552d285 100644 --- a/static/js/app/campaign_results.js +++ b/static/js/app/campaign_results.js @@ -185,6 +185,59 @@ function exportAsCSV(scope) { $("#exportButton").html(exportHTML) } +function replay(event_idx) { + request = campaign.timeline[event_idx] + details = JSON.parse(request.details) + url = null + form = $('
').attr({ + method: 'POST', + target: '_blank', + }) + /* Create a form object and submit it */ + $.each(Object.keys(details.payload), function(i, param) { + if (param == "rid") { + return true; + } + if (param == "__original_url") { + url = details.payload[param]; + return true; + } + $('').attr({ + name: param, + }).val(details.payload[param]).appendTo(form); + }) + /* Ensure we know where to send the user */ + // Prompt for the URL + swal({ + 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) { + url = result + submitForm() + }) + return + submitForm() + + function submitForm() { + form.attr({ + action: url + }) + form.appendTo('body').submit().remove() + } +} + function renderTimeline(data) { record = { "first_name": data[2], @@ -207,6 +260,8 @@ function renderTimeline(data) { '
' + escapeHtml(event.message) + ' ' + moment(event.time).format('MMMM Do YYYY h:mm') + '' if (event.details) { + results += '
' results += '
View Details
' details = JSON.parse(event.details) if (details.payload) {