mirror of https://github.com/gophish/gophish
Added IP, Lat and Lon to models.Result. Closes #47
Added basic mapping on campaign results. Closes #51pull/64/head
parent
8969ebdccc
commit
c6cd018536
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"log"
|
"log"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
@ -101,6 +102,16 @@ func PhishTracker(w http.ResponseWriter, r *http.Request) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Logger.Println(err)
|
Logger.Println(err)
|
||||||
}
|
}
|
||||||
|
// Update the GeoIP information
|
||||||
|
ip, _, err := net.SplitHostPort(r.RemoteAddr)
|
||||||
|
if err == nil {
|
||||||
|
err = rs.UpdateGeo(ip)
|
||||||
|
if err != nil {
|
||||||
|
Logger.Println(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Logger.Println(err)
|
||||||
|
}
|
||||||
w.Write([]byte(""))
|
w.Write([]byte(""))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,25 +4,62 @@ import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
|
"github.com/oschwald/maxminddb-golang"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type mmCity struct {
|
||||||
|
GeoPoint mmGeoPoint `maxminddb:"location"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type mmGeoPoint struct {
|
||||||
|
Latitude float64 `maxminddb:"latitude"`
|
||||||
|
Longitude float64 `maxminddb:"longitude"`
|
||||||
|
}
|
||||||
|
|
||||||
type Result struct {
|
type Result struct {
|
||||||
Id int64 `json:"-"`
|
Id int64 `json:"-"`
|
||||||
CampaignId int64 `json:"-"`
|
CampaignId int64 `json:"-"`
|
||||||
UserId int64 `json:"-"`
|
UserId int64 `json:"-"`
|
||||||
RId string `json:"id"`
|
RId string `json:"id"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
FirstName string `json:"first_name"`
|
FirstName string `json:"first_name"`
|
||||||
LastName string `json:"last_name"`
|
LastName string `json:"last_name"`
|
||||||
Status string `json:"status" sql:"not null"`
|
Status string `json:"status" sql:"not null"`
|
||||||
|
IP string `json:"ip"`
|
||||||
|
Latitude float64 `json:"latitude"`
|
||||||
|
Longitude float64 `json:"longitude"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Result) UpdateStatus(s string) error {
|
func (r *Result) UpdateStatus(s string) error {
|
||||||
return db.Table("results").Where("id=?", r.Id).Update("status", s).Error
|
return db.Table("results").Where("id=?", r.Id).Update("status", s).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Result) UpdateGeo(addr string) error {
|
||||||
|
// Open a connection to the maxmind db
|
||||||
|
mmdb, err := maxminddb.Open("static/db/geolite2-city.mmdb")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer mmdb.Close()
|
||||||
|
ip := net.ParseIP(addr)
|
||||||
|
var city mmCity
|
||||||
|
// Get the record
|
||||||
|
err = mmdb.Lookup(ip, &city)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Update the database with the record information
|
||||||
|
return db.Table("results").Where("id=?", r.Id).Updates(map[string]interface{}{
|
||||||
|
"ip": addr,
|
||||||
|
"latitude": city.GeoPoint.Latitude,
|
||||||
|
"longitude": city.GeoPoint.Longitude,
|
||||||
|
}).Error
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Result) GenerateId() {
|
func (r *Result) GenerateId() {
|
||||||
// Keep trying until we generate a unique key (shouldn't take more than one or two iterations)
|
// Keep trying until we generate a unique key (shouldn't take more than one or two iterations)
|
||||||
k := make([]byte, 32)
|
k := make([]byte, 32)
|
||||||
|
|
|
@ -323,3 +323,6 @@
|
||||||
font-family: 'Courier New',Monospace !important;
|
font-family: 'Courier New',Monospace !important;
|
||||||
font-size: small !important;
|
font-size: small !important;
|
||||||
}
|
}
|
||||||
|
#resultsMap {
|
||||||
|
margin-top:-30px;
|
||||||
|
}
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 37 MiB |
|
@ -183,25 +183,70 @@ $(document).ready(function(){
|
||||||
});
|
});
|
||||||
$("#loading").hide()
|
$("#loading").hide()
|
||||||
$("#campaignResults").show()
|
$("#campaignResults").show()
|
||||||
|
map = new Datamap({
|
||||||
|
element: document.getElementById("resultsMap"),
|
||||||
|
responsive: true,
|
||||||
|
fills: {
|
||||||
|
defaultFill: "#ffffff",
|
||||||
|
point: "#34495e"
|
||||||
|
},
|
||||||
|
geographyConfig: {
|
||||||
|
highlightFillColor : "#1abc9c",
|
||||||
|
borderColor:"#34495e"
|
||||||
|
},
|
||||||
|
bubblesConfig: {
|
||||||
|
borderColor: "#34495e"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
bubbles = []
|
||||||
|
$.each(campaign.results, function(i, result){
|
||||||
|
// Check that it wasn't an internal IP
|
||||||
|
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){
|
||||||
|
console.log("Adding bubble at: ")
|
||||||
|
console.log({
|
||||||
|
latitude : result.latitude,
|
||||||
|
longitude: result.longitude,
|
||||||
|
name : result.ip,
|
||||||
|
fillKey: "point"
|
||||||
|
})
|
||||||
|
bubbles.push({
|
||||||
|
latitude : result.latitude,
|
||||||
|
longitude: result.longitude,
|
||||||
|
name : result.ip,
|
||||||
|
fillKey: "point",
|
||||||
|
radius: 2
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
map.bubbles(bubbles)
|
||||||
}
|
}
|
||||||
// Load up the map data (only once!)
|
// Load up the map data (only once!)
|
||||||
// Slated for 0.2 release - coming soon! :)
|
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||||
// $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
if ($(e.target).attr('href') == "#overview"){
|
||||||
// if ($(e.target).attr('href') == "#plugins"){
|
if (!map){
|
||||||
// if (!map){
|
map = new Datamap({
|
||||||
// map = new Datamap({
|
element: document.getElementById("resultsMap"),
|
||||||
// element: document.getElementById("resultsMap"),
|
responsive: true,
|
||||||
// responsive: true,
|
fills: {
|
||||||
// fills: {
|
defaultFill: "#ffffff"
|
||||||
// defaultFill: "#34495e"
|
},
|
||||||
// },
|
geographyConfig: {
|
||||||
// geographyConfig: {
|
highlightFillColor : "#1abc9c",
|
||||||
// highlightFillColor : "#1abc9c"
|
borderColor:"#34495e"
|
||||||
// }
|
}
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// })
|
})
|
||||||
})
|
})
|
||||||
.error(function(){
|
.error(function(){
|
||||||
$("#loading").hide()
|
$("#loading").hide()
|
||||||
|
|
|
@ -52,8 +52,8 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<ul class="nav nav-tabs" role="tablist">
|
<ul class="nav nav-tabs" role="tablist">
|
||||||
<li class="active"><a href="#overview" aria-controls="home" role="tab" data-toggle="tab">Overview</a></li>
|
<li class="active"><a href="#overview" aria-controls="home" role="tab" data-toggle="tab">Overview</a></li>
|
||||||
<!-- <li><a href="#plugins" aria-controls="profile" role="tab" data-toggle="tab">Plugins</a></li>
|
<!--<li><a href="#plugins" aria-controls="profile" role="tab" data-toggle="tab">Plugins</a></li>
|
||||||
<li><a href="#demographics" aria-controls="settings" role="tab" data-toggle="tab">Demographics</a></li> -->
|
<li><a href="#demographics" aria-controls="settings" role="tab" data-toggle="tab">Demographics</a></li>-->
|
||||||
</ul>
|
</ul>
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div role="tabpanel" class="tab-pane active" id="overview">
|
<div role="tabpanel" class="tab-pane active" id="overview">
|
||||||
|
@ -73,13 +73,15 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="row">
|
||||||
<!-- <div role="tabpanel" class="tab-pane" id="plugins">
|
<div class="col-md-6">
|
||||||
<div class="row">
|
<p style="text-align:center;">Targets Map</p>
|
||||||
<div class="col-md-8">
|
|
||||||
<div id="resultsMap"></div>
|
<div id="resultsMap"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--
|
||||||
|
<div role="tabpanel" class="tab-pane" id="plugins">
|
||||||
</div>
|
</div>
|
||||||
<div role="tabpanel" class="tab-pane" id="demographics">
|
<div role="tabpanel" class="tab-pane" id="demographics">
|
||||||
Demographics here
|
Demographics here
|
||||||
|
|
Loading…
Reference in New Issue