mirror of https://github.com/gophish/gophish
Added support for redirect URL's after creds are submitted. Fixes #210
parent
9051ee7656
commit
52b9eda3b2
|
@ -190,6 +190,11 @@ func PhishHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Logger.Println(err)
|
Logger.Println(err)
|
||||||
}
|
}
|
||||||
|
// Redirect to the desired page
|
||||||
|
if p.RedirectURL != "" {
|
||||||
|
http.Redirect(w, r, p.RedirectURL, 302)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
w.Write([]byte(p.HTML))
|
w.Write([]byte(p.HTML))
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
-- +goose Up
|
||||||
|
-- SQL in section 'Up' is executed when this migration is applied
|
||||||
|
ALTER TABLE pages ADD COLUMN redirect_url VARCHAR(255);
|
||||||
|
|
||||||
|
-- +goose Down
|
||||||
|
-- SQL section 'Down' is executed when this migration is rolled back
|
||||||
|
|
|
@ -108,12 +108,14 @@ func (s *ModelsSuite) TestPostPage(c *check.C) {
|
||||||
p := Page{
|
p := Page{
|
||||||
Name: "Test Page",
|
Name: "Test Page",
|
||||||
HTML: html,
|
HTML: html,
|
||||||
|
RedirectURL: "http://example.com",
|
||||||
}
|
}
|
||||||
// Check the capturing credentials and passwords
|
// Check the capturing credentials and passwords
|
||||||
p.CaptureCredentials = true
|
p.CaptureCredentials = true
|
||||||
p.CapturePasswords = true
|
p.CapturePasswords = true
|
||||||
err := PostPage(&p)
|
err := PostPage(&p)
|
||||||
c.Assert(err, check.Equals, nil)
|
c.Assert(err, check.Equals, nil)
|
||||||
|
c.Assert(p.RedirectURL, check.Equals, "http://example.com")
|
||||||
d, err := goquery.NewDocumentFromReader(strings.NewReader(p.HTML))
|
d, err := goquery.NewDocumentFromReader(strings.NewReader(p.HTML))
|
||||||
c.Assert(err, check.Equals, nil)
|
c.Assert(err, check.Equals, nil)
|
||||||
forms := d.Find("form")
|
forms := d.Find("form")
|
||||||
|
@ -132,8 +134,10 @@ func (s *ModelsSuite) TestPostPage(c *check.C) {
|
||||||
// Check what happens when we don't capture passwords
|
// Check what happens when we don't capture passwords
|
||||||
p.CapturePasswords = false
|
p.CapturePasswords = false
|
||||||
p.HTML = html
|
p.HTML = html
|
||||||
|
p.RedirectURL = ""
|
||||||
err = PutPage(&p)
|
err = PutPage(&p)
|
||||||
c.Assert(err, check.Equals, nil)
|
c.Assert(err, check.Equals, nil)
|
||||||
|
c.Assert(p.RedirectURL, check.Equals, "")
|
||||||
d, err = goquery.NewDocumentFromReader(strings.NewReader(p.HTML))
|
d, err = goquery.NewDocumentFromReader(strings.NewReader(p.HTML))
|
||||||
c.Assert(err, check.Equals, nil)
|
c.Assert(err, check.Equals, nil)
|
||||||
forms = d.Find("form")
|
forms = d.Find("form")
|
||||||
|
|
|
@ -16,6 +16,7 @@ type Page struct {
|
||||||
HTML string `json:"html" gorm:"column:html"`
|
HTML string `json:"html" gorm:"column:html"`
|
||||||
CaptureCredentials bool `json:"capture_credentials" gorm:"column:capture_credentials"`
|
CaptureCredentials bool `json:"capture_credentials" gorm:"column:capture_credentials"`
|
||||||
CapturePasswords bool `json:"capture_passwords" gorm:"column:capture_passwords"`
|
CapturePasswords bool `json:"capture_passwords" gorm:"column:capture_passwords"`
|
||||||
|
RedirectURL string `json:"redirect_url" gorm:"column:redirect_url"`
|
||||||
ModifiedDate time.Time `json:"modified_date"`
|
ModifiedDate time.Time `json:"modified_date"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -505,6 +505,9 @@ td.details-control{
|
||||||
#capture_passwords {
|
#capture_passwords {
|
||||||
display:none;
|
display:none;
|
||||||
}
|
}
|
||||||
|
#redirect_url {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
.navbar-header {
|
.navbar-header {
|
||||||
margin-left:10px !important;
|
margin-left:10px !important;
|
||||||
|
|
|
@ -13,6 +13,7 @@ function save(idx) {
|
||||||
page.html = editor.getData()
|
page.html = editor.getData()
|
||||||
page.capture_credentials = $("#capture_credentials_checkbox").prop("checked")
|
page.capture_credentials = $("#capture_credentials_checkbox").prop("checked")
|
||||||
page.capture_passwords = $("#capture_passwords_checkbox").prop("checked")
|
page.capture_passwords = $("#capture_passwords_checkbox").prop("checked")
|
||||||
|
page.redirect_url = $("#redirect_url_input").val()
|
||||||
if (idx != -1) {
|
if (idx != -1) {
|
||||||
page.id = pages[idx].id
|
page.id = pages[idx].id
|
||||||
api.pageId.put(page)
|
api.pageId.put(page)
|
||||||
|
@ -40,8 +41,10 @@ function dismiss() {
|
||||||
$("#name").val("")
|
$("#name").val("")
|
||||||
$("#html_editor").val("")
|
$("#html_editor").val("")
|
||||||
$("#url").val("")
|
$("#url").val("")
|
||||||
|
$("#redirect_url_input").val("")
|
||||||
$("#modal").find("input[type='checkbox']").prop("checked", false)
|
$("#modal").find("input[type='checkbox']").prop("checked", false)
|
||||||
$("#capture_passwords").hide()
|
$("#capture_passwords").hide()
|
||||||
|
$("#redirect_url").hide()
|
||||||
$("#modal").modal('hide')
|
$("#modal").modal('hide')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,8 +90,10 @@ function edit(idx) {
|
||||||
$("#html_editor").val(page.html)
|
$("#html_editor").val(page.html)
|
||||||
$("#capture_credentials_checkbox").prop("checked", page.capture_credentials)
|
$("#capture_credentials_checkbox").prop("checked", page.capture_credentials)
|
||||||
$("#capture_passwords_checkbox").prop("checked", page.capture_passwords)
|
$("#capture_passwords_checkbox").prop("checked", page.capture_passwords)
|
||||||
if (page.capture_credentials){
|
$("#redirect_url_input").val(page.redirect_url)
|
||||||
|
if (page.capture_credentials) {
|
||||||
$("#capture_passwords").show()
|
$("#capture_passwords").show()
|
||||||
|
$("#redirect_url").show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,8 +196,9 @@ $(document).ready(function() {
|
||||||
$('#modal').on('hidden.bs.modal', function(event) {
|
$('#modal').on('hidden.bs.modal', function(event) {
|
||||||
dismiss()
|
dismiss()
|
||||||
});
|
});
|
||||||
$("#capture_credentials_checkbox").change(function(){
|
$("#capture_credentials_checkbox").change(function() {
|
||||||
$("#capture_passwords").toggle()
|
$("#capture_passwords").toggle()
|
||||||
|
$("#redirect_url").toggle()
|
||||||
})
|
})
|
||||||
load()
|
load()
|
||||||
})
|
})
|
||||||
|
|
|
@ -96,6 +96,12 @@
|
||||||
<i class="fa fa-exclamation-circle"></i> <b>Warning:</b> Credentials are currently <b>not encrypted</b>. This means that captured passwords are stored in the database as cleartext. Be careful with this!
|
<i class="fa fa-exclamation-circle"></i> <b>Warning:</b> Credentials are currently <b>not encrypted</b>. This means that captured passwords are stored in the database as cleartext. Be careful with this!
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="redirect_url">
|
||||||
|
<label class="control-label" for="redirect_url_input">Redirect to: <i class="fa fa-question-circle" data-toggle="tooltip" data-placement="right" title="This option lets you redirect the user to a page after credentials are submitted."></i></label>
|
||||||
|
<div class="form-group">
|
||||||
|
<input id="redirect_url_input" class="form-control" placeholder="http://example.com"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" data-dismiss="modal" class="btn btn-default" onclick="dismiss()">Cancel</button>
|
<button type="button" data-dismiss="modal" class="btn btn-default" onclick="dismiss()">Cancel</button>
|
||||||
|
|
Loading…
Reference in New Issue