forked from gophish/gophish
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpage.go
156 lines (144 loc) · 4.28 KB
/
page.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package models
import (
"errors"
"strings"
"time"
"github.com/PuerkitoBio/goquery"
log "github.com/gophish/gophish/logger"
)
// Page contains the fields used for a Page model
type Page struct {
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"`
RedirectURL string `json:"redirect_url" gorm:"column:redirect_url"`
ModifiedDate time.Time `json:"modified_date"`
}
// ErrPageNameNotSpecified is thrown if the name of the landing page is blank.
var ErrPageNameNotSpecified = errors.New("Page Name not specified")
// 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 {
inputs := f.Find("input")
inputs.Each(func(j int, input *goquery.Selection) {
if t, _ := input.Attr("type"); strings.EqualFold(t, "password") {
input.RemoveAttr("name")
}
})
} 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")
}
})
}
} 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
}
// Validate ensures that a page contains the appropriate details
func (p *Page) Validate() error {
if p.Name == "" {
return ErrPageNameNotSpecified
}
// If the user specifies to capture passwords,
// we automatically capture credentials
if p.CapturePasswords && !p.CaptureCredentials {
p.CaptureCredentials = true
}
if err := ValidateTemplate(p.HTML); err != nil {
return err
}
if err := ValidateTemplate(p.RedirectURL); err != nil {
return err
}
return p.parseHTML()
}
// 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 {
log.Error(err)
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 {
log.Error(err)
}
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 {
log.Error(err)
}
return p, err
}
// PostPage creates a new page in the database.
func PostPage(p *Page) error {
err := p.Validate()
if err != nil {
log.Error(err)
return err
}
// Insert into the DB
err = db.Save(p).Error
if err != nil {
log.Error(err)
}
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 {
err := p.Validate()
err = db.Where("id=?", p.Id).Save(p).Error
if err != nil {
log.Error(err)
}
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 {
err := db.Where("user_id=?", uid).Delete(Page{Id: id}).Error
if err != nil {
log.Error(err)
}
return err
}