adding extended_templates feature

pull/1813/head
Ahmed Khalid 2020-04-16 02:55:43 +02:00
parent 07b46d226a
commit 7debe78745
11 changed files with 102 additions and 43 deletions

View File

@ -265,11 +265,13 @@ func (ps *PhishingServer) PhishHandler(w http.ResponseWriter, r *http.Request) {
// connection. This usually involves writing out the page HTML or redirecting
// the user to the correct URL.
func renderPhishResponse(w http.ResponseWriter, r *http.Request, ptx models.PhishingTemplateContext, p models.Page) {
// Getting all template params.. current + extended.
allTemplateParams := models.GetAllTemplateParams(ptx)
// If the request was a form submit and a redirect URL was specified, we
// should send the user to that URL
if r.Method == "POST" {
if p.RedirectURL != "" {
redirectURL, err := models.ExecuteTemplate(p.RedirectURL, ptx)
redirectURL, err := models.ExecuteTemplate(p.RedirectURL, allTemplateParams)
if err != nil {
log.Error(err)
http.NotFound(w, r)
@ -280,7 +282,7 @@ func renderPhishResponse(w http.ResponseWriter, r *http.Request, ptx models.Phis
}
}
// Otherwise, we just need to write out the templated HTML
html, err := models.ExecuteTemplate(p.HTML, ptx)
html, err := models.ExecuteTemplate(p.HTML, allTemplateParams)
if err != nil {
log.Error(err)
http.NotFound(w, r)

View File

@ -0,0 +1,7 @@
-- +goose Up
-- SQL in this section is executed when the migration is applied.
ALTER TABLE `targets` ADD COLUMN extended_template BLOB;
ALTER TABLE `email_requests` ADD COLUMN extended_template BLOB;
ALTER TABLE `results` ADD COLUMN extended_template BLOB;
-- +goose Down
-- SQL in this section is executed when the migration is rolled back.

View File

@ -0,0 +1,7 @@
-- +goose Up
-- SQL in this section is executed when the migration is applied.
ALTER TABLE targets ADD COLUMN extended_template BLOB;
ALTER TABLE email_requests ADD COLUMN extended_template BLOB;
ALTER TABLE results ADD COLUMN extended_template BLOB;
-- +goose Down
-- SQL in this section is executed when the migration is rolled back.

View File

@ -556,6 +556,7 @@ func PostCampaign(c *Campaign, uid int64) error {
Position: t.Position,
FirstName: t.FirstName,
LastName: t.LastName,
ExtendedTemplate: t.ExtendedTemplate,
},
Status: StatusScheduled,
CampaignId: c.Id,

View File

@ -113,8 +113,10 @@ func (s *EmailRequest) Generate(msg *gomail.Message) error {
if err != nil {
return err
}
// Getting all template params.. current + extended.
allTemplateParams := GetAllTemplateParams(ptx)
url, err := ExecuteTemplate(s.URL, ptx)
url, err := ExecuteTemplate(s.URL, allTemplateParams)
if err != nil {
return err
}
@ -128,12 +130,12 @@ func (s *EmailRequest) Generate(msg *gomail.Message) error {
// Parse the customHeader templates
for _, header := range s.SMTP.Headers {
key, err := ExecuteTemplate(header.Key, ptx)
key, err := ExecuteTemplate(header.Key, allTemplateParams)
if err != nil {
log.Error(err)
}
value, err := ExecuteTemplate(header.Value, ptx)
value, err := ExecuteTemplate(header.Value, allTemplateParams)
if err != nil {
log.Error(err)
}
@ -143,7 +145,7 @@ func (s *EmailRequest) Generate(msg *gomail.Message) error {
}
// Parse remaining templates
subject, err := ExecuteTemplate(s.Template.Subject, ptx)
subject, err := ExecuteTemplate(s.Template.Subject, allTemplateParams)
if err != nil {
log.Error(err)
}
@ -154,14 +156,14 @@ func (s *EmailRequest) Generate(msg *gomail.Message) error {
msg.SetHeader("To", s.FormatAddress())
if s.Template.Text != "" {
text, err := ExecuteTemplate(s.Template.Text, ptx)
text, err := ExecuteTemplate(s.Template.Text, allTemplateParams)
if err != nil {
log.Error(err)
}
msg.SetBody("text/plain", text)
}
if s.Template.HTML != "" {
html, err := ExecuteTemplate(s.Template.HTML, ptx)
html, err := ExecuteTemplate(s.Template.HTML, allTemplateParams)
if err != nil {
log.Error(err)
}

View File

@ -57,6 +57,7 @@ type BaseRecipient struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Position string `json:"position"`
ExtendedTemplate string `json:"extended_template,omitempty"`
}
// FormatAddress returns the email address to use in the "To" header of the email
@ -348,6 +349,10 @@ func UpdateTarget(tx *gorm.DB, target Target) error {
"last_name": target.LastName,
"position": target.Position,
}
// handling front end overrides..extended_template is not sent from front end.
if target.ExtendedTemplate != "" {
targetInfo["extended_template"] = target.ExtendedTemplate
}
err := tx.Model(&target).Where("id = ?", target.Id).Updates(targetInfo).Error
if err != nil {
log.WithFields(logrus.Fields{
@ -360,6 +365,6 @@ func UpdateTarget(tx *gorm.DB, target Target) error {
// GetTargets performs a many-to-many select to get all the Targets for a Group
func GetTargets(gid int64) ([]Target, error) {
ts := []Target{}
err := db.Table("targets").Select("targets.id, targets.email, targets.first_name, targets.last_name, targets.position").Joins("left join group_targets gt ON targets.id = gt.target_id").Where("gt.group_id=?", gid).Scan(&ts).Error
err := db.Table("targets").Select("targets.id, targets.email, targets.first_name, targets.last_name, targets.position,targets.extended_template").Joins("left join group_targets gt ON targets.id = gt.target_id").Where("gt.group_id=?", gid).Scan(&ts).Error
return ts, err
}

View File

@ -179,6 +179,8 @@ func (m *MailLog) Generate(msg *gomail.Message) error {
if err != nil {
return err
}
// Getting all template params.. current + extended.
allTemplateParams := GetAllTemplateParams(ptx)
// Add the transparency headers
msg.SetHeader("X-Mailer", config.ServerName)
@ -195,12 +197,12 @@ func (m *MailLog) Generate(msg *gomail.Message) error {
// Parse the customHeader templates
for _, header := range c.SMTP.Headers {
key, err := ExecuteTemplate(header.Key, ptx)
key, err := ExecuteTemplate(header.Key, allTemplateParams)
if err != nil {
log.Warn(err)
}
value, err := ExecuteTemplate(header.Value, ptx)
value, err := ExecuteTemplate(header.Value, allTemplateParams)
if err != nil {
log.Warn(err)
}
@ -210,7 +212,7 @@ func (m *MailLog) Generate(msg *gomail.Message) error {
}
// Parse remaining templates
subject, err := ExecuteTemplate(c.Template.Subject, ptx)
subject, err := ExecuteTemplate(c.Template.Subject, allTemplateParams)
if err != nil {
log.Warn(err)
}
@ -221,14 +223,14 @@ func (m *MailLog) Generate(msg *gomail.Message) error {
msg.SetHeader("To", r.FormatAddress())
if c.Template.Text != "" {
text, err := ExecuteTemplate(c.Template.Text, ptx)
text, err := ExecuteTemplate(c.Template.Text, allTemplateParams)
if err != nil {
log.Warn(err)
}
msg.SetBody("text/plain", text)
}
if c.Template.HTML != "" {
html, err := ExecuteTemplate(c.Template.HTML, ptx)
html, err := ExecuteTemplate(c.Template.HTML, allTemplateParams)
if err != nil {
log.Warn(err)
}

View File

@ -79,12 +79,13 @@ func (p *Page) Validate() error {
if p.CapturePasswords && !p.CaptureCredentials {
p.CaptureCredentials = true
}
if err := ValidateTemplate(p.HTML); err != nil {
// bypass this.. since we can't predict with all extended params in advance.
/*if err := ValidateTemplate(p.HTML); err != nil {
return err
}
if err := ValidateTemplate(p.RedirectURL); err != nil {
return err
}
}*/
return p.parseHTML()
}

View File

@ -123,7 +123,8 @@ func (s *ModelsSuite) TestPageValidation(c *check.C) {
err = p.Validate()
c.Assert(err, check.Equals, nil)
c.Assert(p.CaptureCredentials, check.Equals, true)
// bypassing..no longer needed
/*
// Validate that if the HTML contains an invalid template tag, that we
// catch it
p.HTML = `<html>
@ -138,5 +139,5 @@ func (s *ModelsSuite) TestPageValidation(c *check.C) {
p.HTML = "valid data"
p.RedirectURL = "http://example.com/{{.INVALIDTAG}}"
err = p.Validate()
c.Assert(err, check.NotNil)
c.Assert(err, check.NotNil)*/
}

View File

@ -34,12 +34,14 @@ func (t *Template) Validate() error {
case t.Text == "" && t.HTML == "":
return ErrTemplateMissingParameter
}
if err := ValidateTemplate(t.HTML); err != nil {
// bypass this.. since we can't predict all extended params in advance.
/*if err := ValidateTemplate(t.HTML); err != nil {
return err
}
if err := ValidateTemplate(t.Text); err != nil {
return err
}
}*/
return nil
}
@ -109,7 +111,6 @@ func GetTemplateByName(n string, uid int64) (Template, error) {
// PostTemplate creates a new template in the database.
func PostTemplate(t *Template) error {
// Insert into the DB
if err := t.Validate(); err != nil {
return err
}

View File

@ -2,6 +2,7 @@ package models
import (
"bytes"
"encoding/json"
"net/mail"
"net/url"
"path"
@ -76,7 +77,8 @@ func NewPhishingTemplateContext(ctx TemplateContext, r BaseRecipient, rid string
// template body and data.
func ExecuteTemplate(text string, data interface{}) (string, error) {
buff := bytes.Buffer{}
tmpl, err := template.New("template").Parse(text)
// replacing template params with no corresponding map keys with empty string.
tmpl, err := template.New("template").Option("missingkey=zero").Parse(text)
if err != nil {
return buff.String(), err
}
@ -124,3 +126,31 @@ func ValidateTemplate(text string) error {
}
return nil
}
// GetAllTemplateParams merges the PhishingTemplateContext with the extended_parameters
// if extended_parameters are valid JSON
func GetAllTemplateParams(ptx PhishingTemplateContext) map[string]string {
currentTemplateParams := map[string]string{
"From": ptx.From,
"URL": ptx.URL,
"Tracker": ptx.Tracker,
"TrackingURL": ptx.TrackingURL,
"RId": ptx.RId,
"BaseURL": ptx.BaseURL,
"Email": ptx.BaseRecipient.Email,
"FirstName": ptx.BaseRecipient.FirstName,
"LastName": ptx.BaseRecipient.LastName,
"Position": ptx.BaseRecipient.Position,
}
extendedTemplateParams := map[string]string{}
err := json.Unmarshal([]byte(ptx.BaseRecipient.ExtendedTemplate), &extendedTemplateParams)
if err == nil {
// only merge if we have a valid JSON in extended_parameters
for k, v := range extendedTemplateParams {
currentTemplateParams[k] = v
}
}
return currentTemplateParams
}