mirror of https://github.com/gophish/gophish
Merge pull request #123 from gophish/61-record-browser-post
Capture Credentials Sent via POSTpull/138/head
commit
a0a8a7b8ad
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
production:
|
||||||
|
driver: sqlite3
|
||||||
|
open: gophish.db
|
||||||
|
dialect: sqlite3
|
||||||
|
import: github.com/mattn/go-sqlite3
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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: [{
|
||||||
|
|
Loading…
Reference in New Issue