2017-06-09 04:41:38 +00:00
|
|
|
package controllers
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2018-06-10 01:58:05 +00:00
|
|
|
"encoding/json"
|
2017-06-09 04:41:38 +00:00
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
2018-06-09 02:20:52 +00:00
|
|
|
"log"
|
2017-06-09 04:41:38 +00:00
|
|
|
"net/http"
|
2018-10-15 21:42:05 +00:00
|
|
|
"net/url"
|
2017-06-09 04:41:38 +00:00
|
|
|
|
2018-06-10 01:58:05 +00:00
|
|
|
"github.com/gophish/gophish/config"
|
2017-06-09 04:41:38 +00:00
|
|
|
"github.com/gophish/gophish/models"
|
|
|
|
)
|
|
|
|
|
|
|
|
func (s *ControllersSuite) getFirstCampaign() models.Campaign {
|
|
|
|
campaigns, err := models.GetCampaigns(1)
|
|
|
|
s.Nil(err)
|
|
|
|
return campaigns[0]
|
|
|
|
}
|
|
|
|
|
2018-06-09 02:20:52 +00:00
|
|
|
func (s *ControllersSuite) getFirstEmailRequest() models.EmailRequest {
|
|
|
|
campaign := s.getFirstCampaign()
|
|
|
|
req := models.EmailRequest{
|
|
|
|
TemplateId: campaign.TemplateId,
|
|
|
|
Template: campaign.Template,
|
|
|
|
PageId: campaign.PageId,
|
|
|
|
Page: campaign.Page,
|
|
|
|
URL: "http://localhost.localdomain",
|
|
|
|
UserId: 1,
|
|
|
|
BaseRecipient: campaign.Results[0].BaseRecipient,
|
|
|
|
SMTP: campaign.SMTP,
|
2018-06-19 02:37:59 +00:00
|
|
|
FromAddress: campaign.SMTP.FromAddress,
|
2018-06-09 02:20:52 +00:00
|
|
|
}
|
|
|
|
err := models.PostEmailRequest(&req)
|
|
|
|
s.Nil(err)
|
|
|
|
return req
|
|
|
|
}
|
|
|
|
|
2017-06-09 04:41:38 +00:00
|
|
|
func (s *ControllersSuite) openEmail(rid string) {
|
2018-02-23 05:02:27 +00:00
|
|
|
resp, err := http.Get(fmt.Sprintf("%s/track?%s=%s", ps.URL, models.RecipientParameter, rid))
|
2017-06-09 04:41:38 +00:00
|
|
|
s.Nil(err)
|
|
|
|
defer resp.Body.Close()
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
|
|
s.Nil(err)
|
|
|
|
expected, err := ioutil.ReadFile("static/images/pixel.png")
|
|
|
|
s.Nil(err)
|
|
|
|
s.Equal(bytes.Compare(body, expected), 0)
|
|
|
|
}
|
|
|
|
|
2018-03-19 03:03:00 +00:00
|
|
|
func (s *ControllersSuite) reportedEmail(rid string) {
|
|
|
|
resp, err := http.Get(fmt.Sprintf("%s/report?%s=%s", ps.URL, models.RecipientParameter, rid))
|
|
|
|
s.Nil(err)
|
|
|
|
s.Equal(resp.StatusCode, http.StatusNoContent)
|
|
|
|
}
|
|
|
|
|
2018-06-10 01:58:05 +00:00
|
|
|
func (s *ControllersSuite) reportEmail404(rid string) {
|
|
|
|
resp, err := http.Get(fmt.Sprintf("%s/report?%s=%s", ps.URL, models.RecipientParameter, rid))
|
|
|
|
s.Nil(err)
|
|
|
|
s.Equal(resp.StatusCode, http.StatusNotFound)
|
|
|
|
}
|
|
|
|
|
2017-06-09 04:41:38 +00:00
|
|
|
func (s *ControllersSuite) openEmail404(rid string) {
|
2018-02-23 05:02:27 +00:00
|
|
|
resp, err := http.Get(fmt.Sprintf("%s/track?%s=%s", ps.URL, models.RecipientParameter, rid))
|
2017-06-09 04:41:38 +00:00
|
|
|
s.Nil(err)
|
|
|
|
defer resp.Body.Close()
|
|
|
|
s.Nil(err)
|
|
|
|
s.Equal(resp.StatusCode, http.StatusNotFound)
|
|
|
|
}
|
|
|
|
|
2018-06-09 02:20:52 +00:00
|
|
|
func (s *ControllersSuite) clickLink(rid string, expectedHTML string) {
|
2018-02-23 05:02:27 +00:00
|
|
|
resp, err := http.Get(fmt.Sprintf("%s/?%s=%s", ps.URL, models.RecipientParameter, rid))
|
2017-06-09 04:41:38 +00:00
|
|
|
s.Nil(err)
|
|
|
|
defer resp.Body.Close()
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
|
|
s.Nil(err)
|
2018-06-09 02:20:52 +00:00
|
|
|
log.Printf("%s\n\n\n", body)
|
|
|
|
s.Equal(bytes.Compare(body, []byte(expectedHTML)), 0)
|
2017-06-09 04:41:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *ControllersSuite) clickLink404(rid string) {
|
2018-02-23 05:02:27 +00:00
|
|
|
resp, err := http.Get(fmt.Sprintf("%s/?%s=%s", ps.URL, models.RecipientParameter, rid))
|
2017-06-09 04:41:38 +00:00
|
|
|
s.Nil(err)
|
|
|
|
defer resp.Body.Close()
|
|
|
|
s.Nil(err)
|
|
|
|
s.Equal(resp.StatusCode, http.StatusNotFound)
|
|
|
|
}
|
|
|
|
|
2018-06-10 01:58:05 +00:00
|
|
|
func (s *ControllersSuite) transparencyRequest(r models.Result, rid, path string) {
|
|
|
|
resp, err := http.Get(fmt.Sprintf("%s%s?%s=%s", ps.URL, path, models.RecipientParameter, rid))
|
|
|
|
s.Nil(err)
|
|
|
|
defer resp.Body.Close()
|
|
|
|
s.Equal(resp.StatusCode, http.StatusOK)
|
|
|
|
tr := &TransparencyResponse{}
|
|
|
|
err = json.NewDecoder(resp.Body).Decode(tr)
|
|
|
|
s.Nil(err)
|
|
|
|
s.Equal(tr.ContactAddress, config.Conf.ContactAddress)
|
|
|
|
s.Equal(tr.SendDate, r.SendDate)
|
2018-06-19 02:37:59 +00:00
|
|
|
s.Equal(tr.Server, config.ServerName)
|
2018-06-10 01:58:05 +00:00
|
|
|
}
|
|
|
|
|
2017-06-09 04:41:38 +00:00
|
|
|
func (s *ControllersSuite) TestOpenedPhishingEmail() {
|
|
|
|
campaign := s.getFirstCampaign()
|
|
|
|
result := campaign.Results[0]
|
|
|
|
s.Equal(result.Status, models.STATUS_SENDING)
|
|
|
|
|
|
|
|
s.openEmail(result.RId)
|
|
|
|
|
|
|
|
campaign = s.getFirstCampaign()
|
|
|
|
result = campaign.Results[0]
|
2018-05-27 02:26:34 +00:00
|
|
|
lastEvent := campaign.Events[len(campaign.Events)-1]
|
2017-06-09 04:41:38 +00:00
|
|
|
s.Equal(result.Status, models.EVENT_OPENED)
|
2018-05-27 02:26:34 +00:00
|
|
|
s.Equal(lastEvent.Message, models.EVENT_OPENED)
|
|
|
|
s.Equal(result.ModifiedDate, lastEvent.Time)
|
2017-06-09 04:41:38 +00:00
|
|
|
}
|
|
|
|
|
2018-03-19 03:03:00 +00:00
|
|
|
func (s *ControllersSuite) TestReportedPhishingEmail() {
|
|
|
|
campaign := s.getFirstCampaign()
|
|
|
|
result := campaign.Results[0]
|
|
|
|
s.Equal(result.Status, models.STATUS_SENDING)
|
|
|
|
|
|
|
|
s.reportedEmail(result.RId)
|
|
|
|
|
|
|
|
campaign = s.getFirstCampaign()
|
|
|
|
result = campaign.Results[0]
|
2018-05-27 02:26:34 +00:00
|
|
|
lastEvent := campaign.Events[len(campaign.Events)-1]
|
2018-03-19 03:03:00 +00:00
|
|
|
s.Equal(result.Reported, true)
|
2018-05-27 02:26:34 +00:00
|
|
|
s.Equal(lastEvent.Message, models.EVENT_REPORTED)
|
|
|
|
s.Equal(result.ModifiedDate, lastEvent.Time)
|
2018-03-19 03:03:00 +00:00
|
|
|
}
|
|
|
|
|
2017-06-09 04:41:38 +00:00
|
|
|
func (s *ControllersSuite) TestClickedPhishingLinkAfterOpen() {
|
|
|
|
campaign := s.getFirstCampaign()
|
|
|
|
result := campaign.Results[0]
|
|
|
|
s.Equal(result.Status, models.STATUS_SENDING)
|
|
|
|
|
|
|
|
s.openEmail(result.RId)
|
2018-06-09 02:20:52 +00:00
|
|
|
s.clickLink(result.RId, campaign.Page.HTML)
|
2017-06-09 04:41:38 +00:00
|
|
|
|
|
|
|
campaign = s.getFirstCampaign()
|
|
|
|
result = campaign.Results[0]
|
2018-05-27 02:26:34 +00:00
|
|
|
lastEvent := campaign.Events[len(campaign.Events)-1]
|
2017-06-09 04:41:38 +00:00
|
|
|
s.Equal(result.Status, models.EVENT_CLICKED)
|
2018-05-27 02:26:34 +00:00
|
|
|
s.Equal(lastEvent.Message, models.EVENT_CLICKED)
|
|
|
|
s.Equal(result.ModifiedDate, lastEvent.Time)
|
2017-06-09 04:41:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *ControllersSuite) TestNoRecipientID() {
|
|
|
|
resp, err := http.Get(fmt.Sprintf("%s/track", ps.URL))
|
|
|
|
s.Nil(err)
|
|
|
|
s.Equal(resp.StatusCode, http.StatusNotFound)
|
|
|
|
|
|
|
|
resp, err = http.Get(ps.URL)
|
|
|
|
s.Nil(err)
|
|
|
|
s.Equal(resp.StatusCode, http.StatusNotFound)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *ControllersSuite) TestInvalidRecipientID() {
|
|
|
|
rid := "XXXXXXXXXX"
|
2018-06-10 01:58:05 +00:00
|
|
|
s.openEmail404(rid)
|
|
|
|
s.clickLink404(rid)
|
|
|
|
s.reportEmail404(rid)
|
2017-06-09 04:41:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *ControllersSuite) TestCompletedCampaignClick() {
|
|
|
|
campaign := s.getFirstCampaign()
|
|
|
|
result := campaign.Results[0]
|
|
|
|
s.Equal(result.Status, models.STATUS_SENDING)
|
|
|
|
s.openEmail(result.RId)
|
|
|
|
|
|
|
|
campaign = s.getFirstCampaign()
|
|
|
|
result = campaign.Results[0]
|
|
|
|
s.Equal(result.Status, models.EVENT_OPENED)
|
|
|
|
|
|
|
|
models.CompleteCampaign(campaign.Id, 1)
|
|
|
|
s.openEmail404(result.RId)
|
|
|
|
s.clickLink404(result.RId)
|
|
|
|
|
|
|
|
campaign = s.getFirstCampaign()
|
|
|
|
result = campaign.Results[0]
|
|
|
|
s.Equal(result.Status, models.EVENT_OPENED)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *ControllersSuite) TestRobotsHandler() {
|
|
|
|
expected := []byte("User-agent: *\nDisallow: /\n")
|
|
|
|
resp, err := http.Get(fmt.Sprintf("%s/robots.txt", ps.URL))
|
|
|
|
s.Nil(err)
|
|
|
|
s.Equal(resp.StatusCode, http.StatusOK)
|
|
|
|
defer resp.Body.Close()
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
|
|
s.Nil(err)
|
|
|
|
s.Equal(bytes.Compare(body, expected), 0)
|
|
|
|
}
|
2018-06-09 02:20:52 +00:00
|
|
|
|
|
|
|
func (s *ControllersSuite) TestInvalidPreviewID() {
|
|
|
|
bogusRId := fmt.Sprintf("%sbogus", models.PreviewPrefix)
|
|
|
|
s.openEmail404(bogusRId)
|
|
|
|
s.clickLink404(bogusRId)
|
2018-06-10 01:58:05 +00:00
|
|
|
s.reportEmail404(bogusRId)
|
2018-06-09 02:20:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *ControllersSuite) TestPreviewTrack() {
|
|
|
|
req := s.getFirstEmailRequest()
|
|
|
|
s.openEmail(req.RId)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *ControllersSuite) TestPreviewClick() {
|
|
|
|
req := s.getFirstEmailRequest()
|
|
|
|
s.clickLink(req.RId, req.Page.HTML)
|
|
|
|
}
|
2018-06-10 01:58:05 +00:00
|
|
|
|
|
|
|
func (s *ControllersSuite) TestInvalidTransparencyRequest() {
|
|
|
|
bogusRId := fmt.Sprintf("bogus%s", TransparencySuffix)
|
|
|
|
s.openEmail404(bogusRId)
|
|
|
|
s.clickLink404(bogusRId)
|
|
|
|
s.reportEmail404(bogusRId)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *ControllersSuite) TestTransparencyRequest() {
|
|
|
|
campaign := s.getFirstCampaign()
|
|
|
|
result := campaign.Results[0]
|
|
|
|
rid := fmt.Sprintf("%s%s", result.RId, TransparencySuffix)
|
|
|
|
s.transparencyRequest(result, rid, "/")
|
|
|
|
s.transparencyRequest(result, rid, "/track")
|
|
|
|
s.transparencyRequest(result, rid, "/report")
|
|
|
|
|
|
|
|
// And check with the URL encoded version of a +
|
|
|
|
rid = fmt.Sprintf("%s%s", result.RId, "%2b")
|
|
|
|
s.transparencyRequest(result, rid, "/")
|
|
|
|
s.transparencyRequest(result, rid, "/track")
|
|
|
|
s.transparencyRequest(result, rid, "/report")
|
|
|
|
}
|
2018-10-15 21:42:05 +00:00
|
|
|
|
|
|
|
func (s *ControllersSuite) TestRedirectTemplating() {
|
|
|
|
p := models.Page{
|
|
|
|
Name: "Redirect Page",
|
|
|
|
HTML: "<html>Test</html>",
|
|
|
|
UserId: 1,
|
|
|
|
RedirectURL: "http://example.com/{{.RId}}",
|
|
|
|
}
|
|
|
|
err := models.PostPage(&p)
|
|
|
|
s.Nil(err)
|
|
|
|
smtp, _ := models.GetSMTP(1, 1)
|
|
|
|
template, _ := models.GetTemplate(1, 1)
|
|
|
|
group, _ := models.GetGroup(1, 1)
|
|
|
|
|
|
|
|
campaign := models.Campaign{Name: "Redirect campaign"}
|
|
|
|
campaign.UserId = 1
|
|
|
|
campaign.Template = template
|
|
|
|
campaign.Page = p
|
|
|
|
campaign.SMTP = smtp
|
|
|
|
campaign.Groups = []models.Group{group}
|
|
|
|
err = models.PostCampaign(&campaign, campaign.UserId)
|
|
|
|
s.Nil(err)
|
|
|
|
|
|
|
|
client := http.Client{
|
|
|
|
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
|
|
|
return http.ErrUseLastResponse
|
|
|
|
},
|
|
|
|
}
|
|
|
|
result := campaign.Results[0]
|
|
|
|
resp, err := client.PostForm(fmt.Sprintf("%s/?%s=%s", ps.URL, models.RecipientParameter, result.RId), url.Values{"username": {"test"}, "password": {"test"}})
|
|
|
|
s.Nil(err)
|
|
|
|
defer resp.Body.Close()
|
|
|
|
s.Equal(http.StatusFound, resp.StatusCode)
|
|
|
|
expectedURL := fmt.Sprintf("http://example.com/%s", result.RId)
|
|
|
|
got, err := resp.Location()
|
|
|
|
s.Nil(err)
|
|
|
|
s.Equal(expectedURL, got.String())
|
|
|
|
}
|