From 1f16faf5a30ce980f193c76183b0d84ff7805f82 Mon Sep 17 00:00:00 2001 From: domwhewell-sage <122788350+domwhewell-sage@users.noreply.github.com> Date: Tue, 7 May 2024 16:17:43 +0100 Subject: [PATCH 1/8] Start adding graphql --- config.go | 32 ++++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 2 ++ messages.go | 15 +++++++++++++++ sending_helpers.go | 43 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+) diff --git a/config.go b/config.go index 16b422d..4864515 100644 --- a/config.go +++ b/config.go @@ -22,6 +22,31 @@ Email Address - {{ .Email }} IP Address - {{ .Address }} User Agent - {{ .UserAgent }}` +var defaultgraphqlTemplate = `mutation InsertCobaltSyncLog ( + $oplog: bigint!, $startDate: timestamptz, $endDate: timestamptz, $sourceIp: String, $destIp: String, + $tool: String, $userContext: String, $command: String, $description: String, + $output: String, $comments: String, $operatorName: String, $entry_identifier: String!, $extraFields: jsonb! +) { + insert_oplogEntry(objects: { + oplog: $oplog, + startDate: $startDate, + endDate: $endDate, + sourceIp: $sourceIp, + destIp: $destIp, + tool: $tool, + userContext: $userContext, + command: $command, + description: $description, + output: $output, + comments: $comments, + operatorName: $operatorName, + entryIdentifier: $entry_identifier, + extraFields: $extraFields + }) { + returning { id } + } +}` + func init() { viper.SetConfigName("config") viper.SetConfigType("yaml") @@ -48,6 +73,7 @@ func setDefaults() { viper.SetDefault("email_send_click_template", defaultClickedTemplate) viper.SetDefault("email_submitted_credentials_template", defaultSubmittedCredentailsTemplate) viper.SetDefault("email_default_email_open_template", defaultEmailOpenedTemplate) + viper.SetDefault("graphql_default_query", defaultgraphqlTemplate) viper.SetDefault("profiles", []string{"slack"}) } @@ -87,6 +113,12 @@ func validateConfig() { viper.GetString("email.recipient")) continue } + if profile == "ghostwriter" { + ghostwriterConfigs := []string{"ghostwriter.graphql_endpoint", "ghostwriter.api_key"} + checkKeysExist(ghostwriterConfigs...) + log.Infof("Using Ghostwriter sending profile. Will send messages to %s", viper.GetString("ghostwriter.url")) + continue + } log.Fatalf("Profile \"%s\" does not exist", profile) } } diff --git a/go.mod b/go.mod index 1b25e90..20348cf 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.12 require ( github.com/ashwanthkumar/slack-go-webhook v0.0.0-20200209025033-430dd4e66960 github.com/elazarl/goproxy v0.0.0-20210801061803-8e322dfb79c4 // indirect + github.com/machinebox/graphql v0.2.2 // indirect github.com/parnurzeal/gorequest v0.2.16 // indirect github.com/sirupsen/logrus v1.8.1 github.com/spf13/viper v1.8.1 diff --git a/go.sum b/go.sum index ec7632c..4ab2bca 100644 --- a/go.sum +++ b/go.sum @@ -180,6 +180,8 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/machinebox/graphql v0.2.2 h1:dWKpJligYKhYKO5A2gvNhkJdQMNZeChZYyBbrZkBZfo= +github.com/machinebox/graphql v0.2.2/go.mod h1:F+kbVMHuwrQ5tYgU9JXlnskM8nOaFxCAEolaQybkjWA= github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= diff --git a/messages.go b/messages.go index b400709..a94af94 100644 --- a/messages.go +++ b/messages.go @@ -130,6 +130,11 @@ func (w SubmittedDetails) SendEmail() error { return sendEmail("PhishBot - Credentials Submitted", body) } +func (w SubmittedDetails) SendGraphql() error { + oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: "Email: " + w.Email + "\nUsername: " + w.Username + "\nPassword: " + w.Password, Comments: SubmittedData} + return sendGraphql(oplog_entry) +} + type ClickDetails struct { CampaignID uint ID string @@ -175,6 +180,11 @@ func (w ClickDetails) SendEmail() error { return sendEmail("PhishBot - Email Clicked", body) } +func (w ClickDetails) SendGraphql() error { + oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: "Email: " + w.Email, Comments: ClickedLink} + return sendGraphql(oplog_entry) +} + func getEmailBody(templateValue string, obj interface{}) (string, error) { out := new(strings.Builder) tpl, err := template.New("email").Parse(templateValue) @@ -231,3 +241,8 @@ func (w OpenedDetails) SendEmail() error { } return sendEmail("PhishBot - Email Opened", body) } + +func (w OpenedDetails) SendGraphql() error { + oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: "Email: " + w.Email, Comments: EmailOpened} + return sendGraphql(oplog_entry) +} diff --git a/sending_helpers.go b/sending_helpers.go index 103ba28..f90e00c 100644 --- a/sending_helpers.go +++ b/sending_helpers.go @@ -1,13 +1,32 @@ package main import ( + "context" "fmt" "net/smtp" "github.com/ashwanthkumar/slack-go-webhook" + "github.com/machinebox/graphql" "github.com/spf13/viper" ) +type ghostwriter_oplog_entry struct { + Oplog int + StartDate string + EndDate string + SourceIp string + DestIp string + Tool string + UserContext string + Command string + Description string + Output string + Comments string + OperatorName string + EntryIdentifier string + ExtraFields string +} + func sendSlackAttachment(attachment slack.Attachment) error { payload := slack.Payload{ Username: viper.GetString("slack.bot_username"), @@ -36,3 +55,27 @@ func sendEmail(subject, body string) error { } return nil } + +func sendGraphql(data ghostwriter_oplog_entry) error { + url := viper.GetString("ghostwriter.url") + query := viper.GetString("graphql_default_query") + oplog_id := viper.GetInt("ghostwriter.oplog_id") + client := graphql.NewClient(url) + + req := graphql.NewRequest(query) + req.Var("oplog", oplog_id) + req.Var("sourceIp", data.SourceIp) + req.Var("tool", "gophish") + req.Var("userContext", data.UserContext) + req.Var("description", data.Description) + req.Var("output", data.Output) + req.Var("comments", data.Comments) + + ctx := context.Background() + var respData map[string]interface{} + if err := client.Run(ctx, req, &respData); err != nil { + return err + } + + return nil +} From ada9b0bac51748d32ecb96e7cc89303fc2e103fd Mon Sep 17 00:00:00 2001 From: Dom Whewell Date: Tue, 7 May 2024 17:42:40 +0100 Subject: [PATCH 2/8] Changes to disable credentials in ghostwriter log --- README.md | 11 +++++++++++ config.go | 19 ++++++------------- main.go | 6 ++++++ messages.go | 19 ++++++++++++++++--- sending_helpers.go | 2 +- 5 files changed, 40 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index e0b22ed..4454343 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,17 @@ email: # Email host address host_addr: smtp.gmail.com:587 +# Ghostwriter Profile +ghostwriter: + # Ghostwriter graphql endpoint + graphql_endpoint: http://localhost:4000/graphql + # Ghostwriter API key + api_key: deadbeef + # Oplog ID + oplog_id: 1 + # (Optional) Disable email, username, and credentials from being sent to ghostwriter + disable_credentials: true + # You can also supply an email template for each notification email_submitted_credentials_template: | Someone submitted credentials! diff --git a/config.go b/config.go index 4864515..437b5ef 100644 --- a/config.go +++ b/config.go @@ -22,26 +22,19 @@ Email Address - {{ .Email }} IP Address - {{ .Address }} User Agent - {{ .UserAgent }}` -var defaultgraphqlTemplate = `mutation InsertCobaltSyncLog ( - $oplog: bigint!, $startDate: timestamptz, $endDate: timestamptz, $sourceIp: String, $destIp: String, - $tool: String, $userContext: String, $command: String, $description: String, - $output: String, $comments: String, $operatorName: String, $entry_identifier: String!, $extraFields: jsonb! +var defaultgraphqlTemplate = `mutation InsertGophishLog ( + $oplog: bigint!, $sourceIp: String, $tool: String, + $userContext: String, $description: String, $output: String, + $comments: String ) { insert_oplogEntry(objects: { oplog: $oplog, - startDate: $startDate, - endDate: $endDate, sourceIp: $sourceIp, - destIp: $destIp, tool: $tool, userContext: $userContext, - command: $command, description: $description, output: $output, - comments: $comments, - operatorName: $operatorName, - entryIdentifier: $entry_identifier, - extraFields: $extraFields + comments: $comments }) { returning { id } } @@ -116,7 +109,7 @@ func validateConfig() { if profile == "ghostwriter" { ghostwriterConfigs := []string{"ghostwriter.graphql_endpoint", "ghostwriter.api_key"} checkKeysExist(ghostwriterConfigs...) - log.Infof("Using Ghostwriter sending profile. Will send messages to %s", viper.GetString("ghostwriter.url")) + log.Infof("Using Ghostwriter sending profile. Will send messages to %s", viper.GetString("ghostwriter.graphql_endpoint")) continue } log.Fatalf("Profile \"%s\" does not exist", profile) diff --git a/main.go b/main.go index 67f4216..3cd49a6 100644 --- a/main.go +++ b/main.go @@ -83,6 +83,12 @@ func handler(w http.ResponseWriter, r *http.Request) { return } } + if profile == "ghostwriter" { + if err := sender.SendGraphql(); err != nil { + log.Error(err) + return + } + } } w.WriteHeader(http.StatusNoContent) diff --git a/messages.go b/messages.go index a94af94..b2430a8 100644 --- a/messages.go +++ b/messages.go @@ -21,6 +21,7 @@ var ( type Sender interface { SendSlack() error SendEmail() error + SendGraphql() error } func senderDispatch(status string, webhookResponse WebhookResponse, response []byte) (Sender, error) { @@ -131,7 +132,11 @@ func (w SubmittedDetails) SendEmail() error { } func (w SubmittedDetails) SendGraphql() error { - oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: "Email: " + w.Email + "\nUsername: " + w.Username + "\nPassword: " + w.Password, Comments: SubmittedData} + var output string + if !viper.GetBool("ghostwriter.disable_credentials") { + output := "Email: " + w.Email + "\nUsername: " + w.Username + "\nPassword: " + w.Password + } + oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: output, Comments: SubmittedData} return sendGraphql(oplog_entry) } @@ -181,7 +186,11 @@ func (w ClickDetails) SendEmail() error { } func (w ClickDetails) SendGraphql() error { - oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: "Email: " + w.Email, Comments: ClickedLink} + var output string + if !viper.GetBool("ghostwriter.disable_credentials") { + output := "Email: " + w.Email + } + oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: output, Comments: ClickedLink} return sendGraphql(oplog_entry) } @@ -243,6 +252,10 @@ func (w OpenedDetails) SendEmail() error { } func (w OpenedDetails) SendGraphql() error { - oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: "Email: " + w.Email, Comments: EmailOpened} + var output string + if !viper.GetBool("ghostwriter.disable_credentials") { + output := "Email: " + w.Email + } + oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: output, Comments: EmailOpened} return sendGraphql(oplog_entry) } diff --git a/sending_helpers.go b/sending_helpers.go index f90e00c..ca08448 100644 --- a/sending_helpers.go +++ b/sending_helpers.go @@ -57,7 +57,7 @@ func sendEmail(subject, body string) error { } func sendGraphql(data ghostwriter_oplog_entry) error { - url := viper.GetString("ghostwriter.url") + url := viper.GetString("ghostwriter.graphql_endpoint") query := viper.GetString("graphql_default_query") oplog_id := viper.GetInt("ghostwriter.oplog_id") client := graphql.NewClient(url) From 701f1fe9851c1ceb09cc1b679770d4e6d3ec08a4 Mon Sep 17 00:00:00 2001 From: Dom Whewell Date: Tue, 7 May 2024 17:44:16 +0100 Subject: [PATCH 3/8] Corrected syntax error --- messages.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/messages.go b/messages.go index b2430a8..65b1367 100644 --- a/messages.go +++ b/messages.go @@ -134,7 +134,7 @@ func (w SubmittedDetails) SendEmail() error { func (w SubmittedDetails) SendGraphql() error { var output string if !viper.GetBool("ghostwriter.disable_credentials") { - output := "Email: " + w.Email + "\nUsername: " + w.Username + "\nPassword: " + w.Password + output = "Email: " + w.Email + "\nUsername: " + w.Username + "\nPassword: " + w.Password } oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: output, Comments: SubmittedData} return sendGraphql(oplog_entry) @@ -188,7 +188,7 @@ func (w ClickDetails) SendEmail() error { func (w ClickDetails) SendGraphql() error { var output string if !viper.GetBool("ghostwriter.disable_credentials") { - output := "Email: " + w.Email + output = "Email: " + w.Email } oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: output, Comments: ClickedLink} return sendGraphql(oplog_entry) @@ -254,7 +254,7 @@ func (w OpenedDetails) SendEmail() error { func (w OpenedDetails) SendGraphql() error { var output string if !viper.GetBool("ghostwriter.disable_credentials") { - output := "Email: " + w.Email + output = "Email: " + w.Email } oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: output, Comments: EmailOpened} return sendGraphql(oplog_entry) From b9431715ed7970380191689e43139d267cd87cf5 Mon Sep 17 00:00:00 2001 From: domwhewell-sage <122788350+domwhewell-sage@users.noreply.github.com> Date: Wed, 8 May 2024 09:29:06 +0100 Subject: [PATCH 4/8] Added api key --- config.go | 24 +++++++----------------- sending_helpers.go | 2 ++ 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/config.go b/config.go index 437b5ef..608a66d 100644 --- a/config.go +++ b/config.go @@ -22,23 +22,13 @@ Email Address - {{ .Email }} IP Address - {{ .Address }} User Agent - {{ .UserAgent }}` -var defaultgraphqlTemplate = `mutation InsertGophishLog ( - $oplog: bigint!, $sourceIp: String, $tool: String, - $userContext: String, $description: String, $output: String, - $comments: String -) { - insert_oplogEntry(objects: { - oplog: $oplog, - sourceIp: $sourceIp, - tool: $tool, - userContext: $userContext, - description: $description, - output: $output, - comments: $comments - }) { - returning { id } +var defaultgraphqlTemplate = `mutation InsertGophishLog ($oplog: bigint!, $sourceIp: String, $tool: String, $userContext: String, $description: String, $output: String, $comments: String) { + insert_oplogEntry(objects: {oplog: $oplog, sourceIp: $sourceIp, tool: $tool, userContext: $userContext, description: $description, comments: $comments, output: $output}) { + returning { + id + } } -}` + }` func init() { viper.SetConfigName("config") @@ -107,7 +97,7 @@ func validateConfig() { continue } if profile == "ghostwriter" { - ghostwriterConfigs := []string{"ghostwriter.graphql_endpoint", "ghostwriter.api_key"} + ghostwriterConfigs := []string{"ghostwriter.graphql_endpoint", "ghostwriter.api_key", "ghostwriter.oplog_id"} checkKeysExist(ghostwriterConfigs...) log.Infof("Using Ghostwriter sending profile. Will send messages to %s", viper.GetString("ghostwriter.graphql_endpoint")) continue diff --git a/sending_helpers.go b/sending_helpers.go index ca08448..b3ce290 100644 --- a/sending_helpers.go +++ b/sending_helpers.go @@ -58,11 +58,13 @@ func sendEmail(subject, body string) error { func sendGraphql(data ghostwriter_oplog_entry) error { url := viper.GetString("ghostwriter.graphql_endpoint") + api_key := viper.GetString("ghostwriter.api_key") query := viper.GetString("graphql_default_query") oplog_id := viper.GetInt("ghostwriter.oplog_id") client := graphql.NewClient(url) req := graphql.NewRequest(query) + req.Header.Set("Authorization", "Bearer "+api_key) req.Var("oplog", oplog_id) req.Var("sourceIp", data.SourceIp) req.Var("tool", "gophish") From fe81187ab3a12d4536383d564e4367cb2d7e02fb Mon Sep 17 00:00:00 2001 From: domwhewell-sage <122788350+domwhewell-sage@users.noreply.github.com> Date: Wed, 8 May 2024 11:33:19 +0100 Subject: [PATCH 5/8] Allow sending email to ghostwriter --- README.md | 4 ++-- messages.go | 14 ++++---------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 4454343..9e0bd71 100644 --- a/README.md +++ b/README.md @@ -71,9 +71,9 @@ email: # Ghostwriter Profile ghostwriter: # Ghostwriter graphql endpoint - graphql_endpoint: http://localhost:4000/graphql + graphql_endpoint: 'https://ghostwriter/v1/graphql' # Ghostwriter API key - api_key: deadbeef + api_key: 'deadbeef' # Oplog ID oplog_id: 1 # (Optional) Disable email, username, and credentials from being sent to ghostwriter diff --git a/messages.go b/messages.go index 65b1367..23390db 100644 --- a/messages.go +++ b/messages.go @@ -135,6 +135,8 @@ func (w SubmittedDetails) SendGraphql() error { var output string if !viper.GetBool("ghostwriter.disable_credentials") { output = "Email: " + w.Email + "\nUsername: " + w.Username + "\nPassword: " + w.Password + } else { + output = "Email: " + w.Email } oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: output, Comments: SubmittedData} return sendGraphql(oplog_entry) @@ -186,11 +188,7 @@ func (w ClickDetails) SendEmail() error { } func (w ClickDetails) SendGraphql() error { - var output string - if !viper.GetBool("ghostwriter.disable_credentials") { - output = "Email: " + w.Email - } - oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: output, Comments: ClickedLink} + oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: "Email: " + w.Email, Comments: ClickedLink} return sendGraphql(oplog_entry) } @@ -252,10 +250,6 @@ func (w OpenedDetails) SendEmail() error { } func (w OpenedDetails) SendGraphql() error { - var output string - if !viper.GetBool("ghostwriter.disable_credentials") { - output = "Email: " + w.Email - } - oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: output, Comments: EmailOpened} + oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: "Email: " + w.Email, Comments: EmailOpened} return sendGraphql(oplog_entry) } From d11f6f3de05cbb638ce54464248125989f1ac334 Mon Sep 17 00:00:00 2001 From: domwhewell-sage Date: Wed, 8 May 2024 13:55:32 +0000 Subject: [PATCH 6/8] Changed `string()` to `strconv.FormatUint()` --- messages.go | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/messages.go b/messages.go index 23390db..954a1b5 100644 --- a/messages.go +++ b/messages.go @@ -5,6 +5,7 @@ import ( "html/template" "net/url" "strings" + "strconv" "github.com/ashwanthkumar/slack-go-webhook" log "github.com/sirupsen/logrus" @@ -134,11 +135,15 @@ func (w SubmittedDetails) SendEmail() error { func (w SubmittedDetails) SendGraphql() error { var output string if !viper.GetBool("ghostwriter.disable_credentials") { - output = "Email: " + w.Email + "\nUsername: " + w.Username + "\nPassword: " + w.Password - } else { - output = "Email: " + w.Email + output = "\nUsername: " + w.Username + "\nPassword: " + w.Password + } + oplog_entry := ghostwriter_oplog_entry{ + SourceIp: w.Address, + UserContext: w.Email, + Description: "User ID: " + w.ID + "\nCampaign ID: " + strconv.FormatUint(uint64(w.CampaignID), 10), + Output: output, + Comments: SubmittedData } - oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: output, Comments: SubmittedData} return sendGraphql(oplog_entry) } @@ -188,7 +193,13 @@ func (w ClickDetails) SendEmail() error { } func (w ClickDetails) SendGraphql() error { - oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: "Email: " + w.Email, Comments: ClickedLink} + oplog_entry := ghostwriter_oplog_entry{ + SourceIp: w.Address, + UserContext: w.Email, + Description: "User ID: " + w.ID + "\nCampaign ID: " + strconv.FormatUint(uint64(w.CampaignID), 10), + Output: "UserAgent: " + w.UserAgent, + Comments: ClickedLink + } return sendGraphql(oplog_entry) } @@ -250,6 +261,12 @@ func (w OpenedDetails) SendEmail() error { } func (w OpenedDetails) SendGraphql() error { - oplog_entry := ghostwriter_oplog_entry{SourceIp: w.Address, UserContext: w.UserAgent, Description: "User ID: " + string(w.ID) + "\nCampaign ID: " + string(w.CampaignID), Output: "Email: " + w.Email, Comments: EmailOpened} + oplog_entry := ghostwriter_oplog_entry{ + SourceIp: w.Address, + UserContext: w.Email, + Description: "User ID: " + w.ID + "\nCampaign ID: " + strconv.FormatUint(uint64(w.CampaignID), 10), + Output: "UserAgent: " + w.UserAgent, + Comments: EmailOpened + } return sendGraphql(oplog_entry) } From 9475dc2e96df14d470f576ead12ff8bb7e6b570c Mon Sep 17 00:00:00 2001 From: Dom Whewell Date: Thu, 9 May 2024 15:01:53 +0100 Subject: [PATCH 7/8] Made requested changes --- messages.go | 26 +++++++++++++------------- sending_helpers.go | 4 ++-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/messages.go b/messages.go index 954a1b5..66518cd 100644 --- a/messages.go +++ b/messages.go @@ -4,8 +4,8 @@ import ( "encoding/json" "html/template" "net/url" - "strings" "strconv" + "strings" "github.com/ashwanthkumar/slack-go-webhook" log "github.com/sirupsen/logrus" @@ -137,12 +137,12 @@ func (w SubmittedDetails) SendGraphql() error { if !viper.GetBool("ghostwriter.disable_credentials") { output = "\nUsername: " + w.Username + "\nPassword: " + w.Password } - oplog_entry := ghostwriter_oplog_entry{ - SourceIp: w.Address, + oplog_entry := ghostwriterOplogEntry{ + SourceIp: w.Address, UserContext: w.Email, Description: "User ID: " + w.ID + "\nCampaign ID: " + strconv.FormatUint(uint64(w.CampaignID), 10), - Output: output, - Comments: SubmittedData + Output: output, + Comments: SubmittedData, } return sendGraphql(oplog_entry) } @@ -193,12 +193,12 @@ func (w ClickDetails) SendEmail() error { } func (w ClickDetails) SendGraphql() error { - oplog_entry := ghostwriter_oplog_entry{ - SourceIp: w.Address, + oplog_entry := ghostwriterOplogEntry{ + SourceIp: w.Address, UserContext: w.Email, Description: "User ID: " + w.ID + "\nCampaign ID: " + strconv.FormatUint(uint64(w.CampaignID), 10), - Output: "UserAgent: " + w.UserAgent, - Comments: ClickedLink + Output: "UserAgent: " + w.UserAgent, + Comments: ClickedLink, } return sendGraphql(oplog_entry) } @@ -261,12 +261,12 @@ func (w OpenedDetails) SendEmail() error { } func (w OpenedDetails) SendGraphql() error { - oplog_entry := ghostwriter_oplog_entry{ - SourceIp: w.Address, + oplog_entry := ghostwriterOplogEntry{ + SourceIp: w.Address, UserContext: w.Email, Description: "User ID: " + w.ID + "\nCampaign ID: " + strconv.FormatUint(uint64(w.CampaignID), 10), - Output: "UserAgent: " + w.UserAgent, - Comments: EmailOpened + Output: "UserAgent: " + w.UserAgent, + Comments: EmailOpened, } return sendGraphql(oplog_entry) } diff --git a/sending_helpers.go b/sending_helpers.go index b3ce290..a1c9dc4 100644 --- a/sending_helpers.go +++ b/sending_helpers.go @@ -10,7 +10,7 @@ import ( "github.com/spf13/viper" ) -type ghostwriter_oplog_entry struct { +type ghostwriterOplogEntry struct { Oplog int StartDate string EndDate string @@ -56,7 +56,7 @@ func sendEmail(subject, body string) error { return nil } -func sendGraphql(data ghostwriter_oplog_entry) error { +func sendGraphql(data ghostwriterOplogEntry) error { url := viper.GetString("ghostwriter.graphql_endpoint") api_key := viper.GetString("ghostwriter.api_key") query := viper.GetString("graphql_default_query") From 568b83f9dc36f38aef5a64c00d0c7a6a031b0ace Mon Sep 17 00:00:00 2001 From: Max Harley Date: Thu, 9 May 2024 17:11:52 +0000 Subject: [PATCH 8/8] Fix for extraFields --- README.md | 2 ++ config.go | 4 ++-- sending_helpers.go | 24 +++++++++++++++++++----- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 9e0bd71..42709e6 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,8 @@ ghostwriter: oplog_id: 1 # (Optional) Disable email, username, and credentials from being sent to ghostwriter disable_credentials: true + # Ignore SSL Self Signed error + ignore_self_signed_certificate: true # You can also supply an email template for each notification email_submitted_credentials_template: | diff --git a/config.go b/config.go index 608a66d..ea7eb9c 100644 --- a/config.go +++ b/config.go @@ -22,8 +22,8 @@ Email Address - {{ .Email }} IP Address - {{ .Address }} User Agent - {{ .UserAgent }}` -var defaultgraphqlTemplate = `mutation InsertGophishLog ($oplog: bigint!, $sourceIp: String, $tool: String, $userContext: String, $description: String, $output: String, $comments: String) { - insert_oplogEntry(objects: {oplog: $oplog, sourceIp: $sourceIp, tool: $tool, userContext: $userContext, description: $description, comments: $comments, output: $output}) { +var defaultgraphqlTemplate = `mutation InsertGophishLog ($oplog: bigint!, $sourceIp: String, $tool: String, $userContext: String, $description: String, $output: String, $comments: String, $extraFields: jsonb!) { + insert_oplogEntry(objects: {oplog: $oplog, sourceIp: $sourceIp, tool: $tool, userContext: $userContext, description: $description, comments: $comments, output: $output, extraFields: $extraFields}) { returning { id } diff --git a/sending_helpers.go b/sending_helpers.go index a1c9dc4..b7a93bd 100644 --- a/sending_helpers.go +++ b/sending_helpers.go @@ -2,7 +2,9 @@ package main import ( "context" + "crypto/tls" "fmt" + "net/http" "net/smtp" "github.com/ashwanthkumar/slack-go-webhook" @@ -58,20 +60,32 @@ func sendEmail(subject, body string) error { func sendGraphql(data ghostwriterOplogEntry) error { url := viper.GetString("ghostwriter.graphql_endpoint") - api_key := viper.GetString("ghostwriter.api_key") + apiKey := viper.GetString("ghostwriter.api_key") + ignoreSelfSigned := viper.GetBool("ghostwriter.ignore_self_signed_certificate") query := viper.GetString("graphql_default_query") - oplog_id := viper.GetInt("ghostwriter.oplog_id") - client := graphql.NewClient(url) + oplogId := viper.GetInt("ghostwriter.oplog_id") + + var client *graphql.Client + if ignoreSelfSigned { + tr := &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + httpClient := &http.Client{Transport: tr} + client = graphql.NewClient(url, graphql.WithHTTPClient(httpClient)) + } else { + client = graphql.NewClient(url) + } req := graphql.NewRequest(query) - req.Header.Set("Authorization", "Bearer "+api_key) - req.Var("oplog", oplog_id) + req.Header.Set("Authorization", "Bearer "+apiKey) + req.Var("oplog", oplogId) req.Var("sourceIp", data.SourceIp) req.Var("tool", "gophish") req.Var("userContext", data.UserContext) req.Var("description", data.Description) req.Var("output", data.Output) req.Var("comments", data.Comments) + req.Var("extraFields", "") ctx := context.Background() var respData map[string]interface{}