2015-02-07 02:24:10 +00:00
|
|
|
package models
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
2016-02-26 01:58:49 +00:00
|
|
|
"strings"
|
2015-02-07 02:24:10 +00:00
|
|
|
"time"
|
2016-02-26 01:58:49 +00:00
|
|
|
|
|
|
|
"github.com/PuerkitoBio/goquery"
|
2018-05-04 00:07:41 +00:00
|
|
|
log "github.com/gophish/gophish/logger"
|
2015-02-07 02:24:10 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Page contains the fields used for a Page model
|
|
|
|
type Page struct {
|
2016-02-26 01:58:49 +00:00
|
|
|
Id int64 `json:"id" gorm:"column:id; primary_key:yes"`
|
|
|
|
UserId int64 `json:"-" gorm:"column:user_id"`
|
|
|
|
Name string `json:"name"`
|
|
|
|
HTML string `json:"html" gorm:"column:html"`
|
|
|
|
CaptureCredentials bool `json:"capture_credentials" gorm:"column:capture_credentials"`
|
|
|
|
CapturePasswords bool `json:"capture_passwords" gorm:"column:capture_passwords"`
|
2016-03-19 01:19:13 +00:00
|
|
|
RedirectURL string `json:"redirect_url" gorm:"column:redirect_url"`
|
2016-02-26 01:58:49 +00:00
|
|
|
ModifiedDate time.Time `json:"modified_date"`
|
2015-02-07 02:24:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ErrPageNameNotSpecified is thrown if the name of the landing page is blank.
|
2015-02-07 20:31:41 +00:00
|
|
|
var ErrPageNameNotSpecified = errors.New("Page Name not specified")
|
2015-02-07 02:24:10 +00:00
|
|
|
|
2016-02-26 01:58:49 +00:00
|
|
|
// parseHTML parses the page HTML on save to handle the
|
|
|
|
// capturing (or lack thereof!) of credentials and passwords
|
|
|
|
func (p *Page) parseHTML() error {
|
|
|
|
d, err := goquery.NewDocumentFromReader(strings.NewReader(p.HTML))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
forms := d.Find("form")
|
|
|
|
forms.Each(func(i int, f *goquery.Selection) {
|
|
|
|
// We always want the submitted events to be
|
|
|
|
// sent to our server
|
|
|
|
f.SetAttr("action", "")
|
|
|
|
if p.CaptureCredentials {
|
|
|
|
// If we don't want to capture passwords,
|
|
|
|
// find all the password fields and remove the "name" attribute.
|
|
|
|
if !p.CapturePasswords {
|
2017-05-27 01:18:19 +00:00
|
|
|
inputs := f.Find("input")
|
|
|
|
inputs.Each(func(j int, input *goquery.Selection) {
|
|
|
|
if t, _ := input.Attr("type"); strings.EqualFold(t, "password") {
|
|
|
|
input.RemoveAttr("name")
|
|
|
|
}
|
2016-02-26 01:58:49 +00:00
|
|
|
})
|
2018-11-11 18:34:26 +00:00
|
|
|
} else {
|
|
|
|
// If the user chooses to re-enable the capture passwords setting,
|
|
|
|
// we need to re-add the name attribute
|
|
|
|
inputs := f.Find("input")
|
|
|
|
inputs.Each(func(j int, input *goquery.Selection) {
|
|
|
|
if t, _ := input.Attr("type"); strings.EqualFold(t, "password") {
|
|
|
|
input.SetAttr("name", "password")
|
|
|
|
}
|
|
|
|
})
|
2016-02-26 01:58:49 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Otherwise, remove the name from all
|
|
|
|
// inputs.
|
|
|
|
inputFields := f.Find("input")
|
|
|
|
inputFields.Each(func(j int, input *goquery.Selection) {
|
|
|
|
input.RemoveAttr("name")
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
p.HTML, err = d.Html()
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2015-02-07 02:24:10 +00:00
|
|
|
// Validate ensures that a page contains the appropriate details
|
|
|
|
func (p *Page) Validate() error {
|
|
|
|
if p.Name == "" {
|
|
|
|
return ErrPageNameNotSpecified
|
|
|
|
}
|
2016-02-26 01:58:49 +00:00
|
|
|
// If the user specifies to capture passwords,
|
|
|
|
// we automatically capture credentials
|
|
|
|
if p.CapturePasswords && !p.CaptureCredentials {
|
|
|
|
p.CaptureCredentials = true
|
|
|
|
}
|
2020-04-16 00:55:43 +00:00
|
|
|
// bypass this.. since we can't predict with all extended params in advance.
|
|
|
|
/*if err := ValidateTemplate(p.HTML); err != nil {
|
2018-09-09 16:33:51 +00:00
|
|
|
return err
|
|
|
|
}
|
2018-10-15 21:42:05 +00:00
|
|
|
if err := ValidateTemplate(p.RedirectURL); err != nil {
|
|
|
|
return err
|
2020-04-16 00:55:43 +00:00
|
|
|
}*/
|
2016-02-26 01:58:49 +00:00
|
|
|
return p.parseHTML()
|
2015-02-07 02:24:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetPages returns the pages owned by the given user.
|
|
|
|
func GetPages(uid int64) ([]Page, error) {
|
|
|
|
ps := []Page{}
|
|
|
|
err := db.Where("user_id=?", uid).Find(&ps).Error
|
|
|
|
if err != nil {
|
2018-05-04 00:07:41 +00:00
|
|
|
log.Error(err)
|
2015-02-07 02:24:10 +00:00
|
|
|
return ps, err
|
|
|
|
}
|
|
|
|
return ps, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetPage returns the page, if it exists, specified by the given id and user_id.
|
|
|
|
func GetPage(id int64, uid int64) (Page, error) {
|
|
|
|
p := Page{}
|
|
|
|
err := db.Where("user_id=? and id=?", uid, id).Find(&p).Error
|
|
|
|
if err != nil {
|
2018-05-04 00:07:41 +00:00
|
|
|
log.Error(err)
|
2015-02-07 02:24:10 +00:00
|
|
|
}
|
|
|
|
return p, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetPageByName returns the page, if it exists, specified by the given name and user_id.
|
|
|
|
func GetPageByName(n string, uid int64) (Page, error) {
|
|
|
|
p := Page{}
|
|
|
|
err := db.Where("user_id=? and name=?", uid, n).Find(&p).Error
|
|
|
|
if err != nil {
|
2018-05-04 00:07:41 +00:00
|
|
|
log.Error(err)
|
2015-02-07 02:24:10 +00:00
|
|
|
}
|
2015-02-07 20:31:41 +00:00
|
|
|
return p, err
|
2015-02-07 02:24:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// PostPage creates a new page in the database.
|
|
|
|
func PostPage(p *Page) error {
|
2015-02-07 16:41:53 +00:00
|
|
|
err := p.Validate()
|
|
|
|
if err != nil {
|
2018-05-04 00:07:41 +00:00
|
|
|
log.Error(err)
|
2015-02-07 16:41:53 +00:00
|
|
|
return err
|
|
|
|
}
|
2015-02-07 02:24:10 +00:00
|
|
|
// Insert into the DB
|
2015-02-07 16:41:53 +00:00
|
|
|
err = db.Save(p).Error
|
2015-02-07 02:24:10 +00:00
|
|
|
if err != nil {
|
2018-05-04 00:07:41 +00:00
|
|
|
log.Error(err)
|
2015-02-07 02:24:10 +00:00
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// PutPage edits an existing Page in the database.
|
|
|
|
// Per the PUT Method RFC, it presumes all data for a page is provided.
|
|
|
|
func PutPage(p *Page) error {
|
2016-02-26 01:58:49 +00:00
|
|
|
err := p.Validate()
|
|
|
|
err = db.Where("id=?", p.Id).Save(p).Error
|
2015-02-07 02:24:10 +00:00
|
|
|
if err != nil {
|
2018-05-04 00:07:41 +00:00
|
|
|
log.Error(err)
|
2015-02-07 02:24:10 +00:00
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeletePage deletes an existing page in the database.
|
|
|
|
// An error is returned if a page with the given user id and page id is not found.
|
|
|
|
func DeletePage(id int64, uid int64) error {
|
2018-12-15 21:42:32 +00:00
|
|
|
err := db.Where("user_id=?", uid).Delete(Page{Id: id}).Error
|
2015-02-07 02:24:10 +00:00
|
|
|
if err != nil {
|
2018-05-04 00:07:41 +00:00
|
|
|
log.Error(err)
|
2015-02-07 02:24:10 +00:00
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|