Merge pull request #123 from gophish/61-record-browser-post

Capture Credentials Sent via POST
pull/138/head
Jordan Wright 2016-02-02 22:54:42 -06:00
commit a0a8a7b8ad
7 changed files with 113 additions and 11 deletions

View File

@ -1,11 +1,13 @@
package controllers package controllers
import ( import (
"encoding/json"
"fmt" "fmt"
"html/template" "html/template"
"log" "log"
"net" "net"
"net/http" "net/http"
"net/url"
"os" "os"
"github.com/gophish/gophish/auth" "github.com/gophish/gophish/auth"
@ -120,7 +122,12 @@ func PhishTracker(w http.ResponseWriter, r *http.Request) {
// PhishHandler handles incoming client connections and registers the associated actions performed // PhishHandler handles incoming client connections and registers the associated actions performed
// (such as clicked link, etc.) // (such as clicked link, etc.)
func PhishHandler(w http.ResponseWriter, r *http.Request) { func PhishHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm() err := r.ParseForm()
if err != nil {
Logger.Println(err)
http.NotFound(w, r)
return
}
id := r.Form.Get("rid") id := r.Form.Get("rid")
if id == "" { if id == "" {
http.NotFound(w, r) http.NotFound(w, r)
@ -140,7 +147,32 @@ func PhishHandler(w http.ResponseWriter, r *http.Request) {
if err != nil { if err != nil {
Logger.Println(err) Logger.Println(err)
} }
c.AddEvent(models.Event{Email: rs.Email, Message: models.EVENT_CLICKED}) switch {
case r.Method == "GET":
err = c.AddEvent(models.Event{Email: rs.Email, Message: models.EVENT_CLICKED})
if err != nil {
Logger.Println(err)
}
case r.Method == "POST":
// If data was POST'ed, let's record it
// Store the data in an event
d := struct {
Payload url.Values `json:"payload"`
Browser map[string]string `json:"browser"`
}{
Payload: r.Form,
}
rj, err := json.Marshal(d)
if err != nil {
Logger.Println(err)
http.NotFound(w, r)
return
}
c.AddEvent(models.Event{Email: rs.Email, Message: models.EVENT_DATA_SUBMIT, Details: string(rj)})
if err != nil {
Logger.Println(err)
}
}
w.Write([]byte(p.HTML)) w.Write([]byte(p.HTML))
} }

5
db/dbconf.yml Normal file
View File

@ -0,0 +1,5 @@
production:
driver: sqlite3
open: gophish.db
dialect: sqlite3
import: github.com/mattn/go-sqlite3

View File

@ -0,0 +1,8 @@
-- +goose Up
-- SQL in section 'Up' is executed when this migration is applied
ALTER TABLE events ADD COLUMN details BLOB;
-- +goose Down
-- SQL section 'Down' is executed when this migration is rolled back

View File

@ -109,6 +109,7 @@ type Event struct {
Email string `json:"email"` Email string `json:"email"`
Time time.Time `json:"time"` Time time.Time `json:"time"`
Message string `json:"message"` Message string `json:"message"`
Details string `json:"details"`
} }
// GetCampaigns returns the campaigns owned by the given user. // GetCampaigns returns the campaigns owned by the given user.

View File

@ -33,6 +33,7 @@ const (
EVENT_SENDING_ERROR string = "Error Sending Email" EVENT_SENDING_ERROR string = "Error Sending Email"
EVENT_OPENED string = "Email Opened" EVENT_OPENED string = "Email Opened"
EVENT_CLICKED string = "Clicked Link" EVENT_CLICKED string = "Clicked Link"
EVENT_DATA_SUBMIT string = "Submitted Data"
STATUS_SUCCESS string = "Success" STATUS_SUCCESS string = "Success"
STATUS_SENDING string = "Sending" STATUS_SENDING string = "Sending"
STATUS_UNKNOWN string = "Unknown" STATUS_UNKNOWN string = "Unknown"

15
static/css/main.css vendored
View File

@ -433,3 +433,18 @@ table.dataTable thead .sorting_desc:after {
color:#999999; color:#999999;
font-style:italic; font-style:italic;
} }
.timeline-event-details {
font-size:16px;
margin-top:5px;
cursor:pointer;
}
.timeline-event-details>.table-responsive{
display:none;
}
.timeline-event-details{
margin-top: 10px;
margin-bottom: 10px;
}
.timeline-event-table{
display:none;
}

View File

@ -38,6 +38,12 @@ var statuses = {
label: "label-default", label: "label-default",
icon: "fa-times" icon: "fa-times"
}, },
"Submitted Data": {
slice: "ct-slice-donut-clicked",
legend: "ct-legend-clicked",
label: "label-danger",
icon: "fa-exclamation"
},
"Unknown": { "Unknown": {
slice: "ct-slice-donut-error", slice: "ct-slice-donut-error",
legend: "ct-legend-error", legend: "ct-legend-error",
@ -90,7 +96,9 @@ function exportAsCSV(scope) {
csvScope = campaign.timeline csvScope = campaign.timeline
break; break;
} }
if (!csvScope){return} if (!csvScope) {
return
}
$("#exportButton").html('<i class="fa fa-spinner fa-spin"></i>') $("#exportButton").html('<i class="fa fa-spinner fa-spin"></i>')
var csvString = Papa.unparse(csvScope, {}) var csvString = Papa.unparse(csvScope, {})
var csvData = new Blob([csvString], { var csvData = new Blob([csvString], {
@ -128,9 +136,27 @@ function renderTimeline(data) {
' <div class="timeline-icon ' + statuses[event.message].label + '">' + ' <div class="timeline-icon ' + statuses[event.message].label + '">' +
' <i class="fa ' + statuses[event.message].icon + '"></i></div>' + ' <i class="fa ' + statuses[event.message].icon + '"></i></div>' +
' <div class="timeline-message">' + event.message + ' <div class="timeline-message">' + event.message +
' <span class="timeline-date">' + moment(event.time).format('MMMM Do YYYY h:mm') + '</span></div>' ' <span class="timeline-date">' + moment(event.time).format('MMMM Do YYYY h:mm') + '</span>'
if (event.details) {
results += '<div class="timeline-event-details"><i class="fa fa-caret-right"></i> View Details</div>'
results += '<div class="timeline-event-table">'
results += ' <table class="table table-condensed table-bordered table-striped">'
results += ' <thead><tr><th>Parameter</th><th>Value(s)</tr></thead><tbody>'
details = JSON.parse(event.details)
$.each(Object.keys(details.payload), function(i, param) {
if (param == "rid") {
return true;
}
results += ' <tr>'
results += ' <td>' + param + '</td>'
results += ' <td>' + details.payload[param] + '</td>'
results += ' </tr>'
})
results += ' </tbody></table>'
results += '</div>' results += '</div>'
} }
results += '</div></div>'
}
}) })
results += '</div></div>' results += '</div></div>'
return results return results
@ -145,6 +171,20 @@ $(document).ready(function() {
$("#page-title").text("Results for " + c.name) $("#page-title").text("Results for " + c.name)
// Setup tooltips // Setup tooltips
$('[data-toggle="tooltip"]').tooltip() $('[data-toggle="tooltip"]').tooltip()
// Setup viewing the details of a result
$("#resultsTable").on("click", ".timeline-event-details", function() {
// Show the parameters
payloadTable = $(this).parent().find(".timeline-event-table")
if (payloadTable.is(":visible")) {
$(this).find("i").removeClass("fa-caret-down")
$(this).find("i").addClass("fa-caret-right")
payloadTable.hide()
} else {
$(this).find("i").removeClass("fa-caret-right")
$(this).find("i").addClass("fa-caret-down")
payloadTable.show()
}
})
// Setup our graphs // Setup our graphs
var timeline_data = { var timeline_data = {
series: [{ series: [{