kgretzky/evilginx2 · warning
session already exists: %s
Error message
session already exists: %s
What it means
This error comes from the evilginx2-style Database layer backed by buntdb. sessionsCreate() first looks up an existing session by its session_id (sid) via sessionsGetBySid(); if that lookup succeeds, a session with this sid already exists in the 'sessions' table, so creation is refused to keep session_id unique. It is a guard against duplicate session records, not an internal failure.
Source
Thrown at database/db_session.go:45
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(),View on GitHub (pinned to 4c0988a1d9)
Solutions
- Check existence first with sessionsGetBySid(sid) and skip creation if it returns nil error
- Generate a cryptographically random, unique sid per visit instead of deriving it from a value that can repeat
- Delete the stale session (sessionsDeleteBySid) before re-creating if replacement is intended
- Treat the error as expected in the caller and fetch/reuse the existing session instead of failing
Example fix
// before
s, err := db.CreateSession(sid, phishlet, landingURL, ua, addr)
if err != nil { return err }
// after
if _, err := db.GetSessionBySid(sid); err == nil {
return nil // session already tracked, nothing to do
}
s, err := db.CreateSession(sid, phishlet, landingURL, ua, addr)
if err != nil { return err } Defensive patterns
Strategy: validation
Validate before calling
if _, err := db.GetSessionBySid(sid); err == nil {
return fmt.Errorf("sid %q already in use", sid)
}
_ = db.CreateSession(sid, phishlet, landingURL, ua, addr) Try / catch
s, err := db.CreateSession(sid, phishlet, landingURL, ua, addr)
if err != nil {
if strings.HasPrefix(err.Error(), "session already exists") {
return db.GetSessionBySid(sid)
}
return nil, err
} Prevention
- Always generate sids from a CSPRNG (e.g. crypto/rand) so collisions are negligible
- Check-before-insert with GetSessionBySid when sid may come from external input
- Never derive sid from client-supplied data that can repeat across requests
When it happens
Trigger: Calling CreateSession/sessionsCreate with a sid that already exists in the sessions table — e.g. re-invoking creation with the same session_id, a client retrying a request that already created a session, or a SID generator (cookie/token reuse) producing a duplicate value.
Common situations: A phishing victim's browser replays a request with an already-issued session cookie, causing the proxy to attempt creating the same session again; automation/scripts calling CreateSession twice with a fixed sid; restored/imported database files that already contain the sid being reused.
Related errors
- session ID not found: %d
- session not found: %s
- phishlet '%s' can't be deleted - you can only delete child p
- index out of bounds: %d
- lure for path '%s' not found
AI-assisted analysis of kgretzky/evilginx2@4c0988a1d9 (2026-09-05).
Data as JSON: /api/errors/e3b9ce40dea9bfc0.
Report an issue: GitHub.