diff --git a/controllers/phish.go b/controllers/phish.go index 6715732c..04165829 100644 --- a/controllers/phish.go +++ b/controllers/phish.go @@ -190,7 +190,13 @@ func renderPhishResponse(w http.ResponseWriter, r *http.Request, ptx models.Phis // should send the user to that URL if r.Method == "POST" { if p.RedirectURL != "" { - http.Redirect(w, r, p.RedirectURL, 302) + redirectURL, err := models.ExecuteTemplate(p.RedirectURL, ptx) + if err != nil { + log.Error(err) + http.NotFound(w, r) + return + } + http.Redirect(w, r, redirectURL, http.StatusFound) return } } diff --git a/controllers/phish_test.go b/controllers/phish_test.go index 6676e4c8..59425c8a 100644 --- a/controllers/phish_test.go +++ b/controllers/phish_test.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "log" "net/http" + "net/url" "github.com/gophish/gophish/config" "github.com/gophish/gophish/models" @@ -229,3 +230,41 @@ func (s *ControllersSuite) TestTransparencyRequest() { s.transparencyRequest(result, rid, "/track") s.transparencyRequest(result, rid, "/report") } + +func (s *ControllersSuite) TestRedirectTemplating() { + p := models.Page{ + Name: "Redirect Page", + HTML: "Test", + 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()) +} diff --git a/models/page.go b/models/page.go index 0f8cc53b..4372935d 100644 --- a/models/page.go +++ b/models/page.go @@ -73,6 +73,9 @@ func (p *Page) Validate() error { if err := ValidateTemplate(p.HTML); err != nil { return err } + if err := ValidateTemplate(p.RedirectURL); err != nil { + return err + } return p.parseHTML() } diff --git a/models/page_test.go b/models/page_test.go index c219a1cc..f337ff80 100644 --- a/models/page_test.go +++ b/models/page_test.go @@ -116,4 +116,11 @@ func (s *ModelsSuite) TestPageValidation(c *check.C) { ` err = p.Validate() c.Assert(err, check.NotNil) + + // Validate that if the RedirectURL contains an invalid template tag, that + // we catch it + p.HTML = "valid data" + p.RedirectURL = "http://example.com/{{.INVALIDTAG}}" + err = p.Validate() + c.Assert(err, check.NotNil) }