scanner

package
v0.12.11 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 25, 2026 License: MIT Imports: 25 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BruteforcePlugins added in v0.6.0

func BruteforcePlugins(req BruteforceRequest) ([]string, map[string]string)

BruteforcePlugins attempts to detect plugins by parsing their readme.txt for version. It updates the progress bar message with a fixed-width plugin name.

func CheckVulnerabilities added in v0.9.0

func CheckVulnerabilities(req VulnerabilityCheckRequest) (map[string]string, []file.PluginEntry)

CheckVulnerabilities checks vulnerabilities for detected plugins and themes.

func DisplayFabricatedContentWarning added in v0.12.6

func DisplayFabricatedContentWarning(progress Progress)

DisplayFabricatedContentWarning tells the user the target answers for slugs that cannot exist, so brute-force results on this host rest entirely on the calibrated baseline rather than on "the file was served".

func FetchEndpoints

func FetchEndpoints(ctx context.Context, target string, cfg http.Config) []string

func HTTPConfigFromOpts added in v0.10.13

func HTTPConfigFromOpts(opts ScanOptions) wphttp.Config

HTTPConfigFromOpts builds an http.Config from ScanOptions. Uses the global shared rate limiter from opts, or creates one if not set.

func HybridScan added in v0.6.0

func HybridScan(req HybridScanRequest) ([]string, map[string]string)

HybridScan performs a hybrid scan: first stealthy, then brute-forces remaining plugins.

func LoadPluginEndpointsFromData

func LoadPluginEndpointsFromData(data []byte) (map[string][]string, error)

LoadPluginEndpointsFromData loads plugin endpoints from JSONL data.

Decoded with goccy/go-json, which on this typed shape is both faster and lighter than encoding/json: 0.86 ms against 2.5 ms on the embedded file, at 300 KB instead of 482 KB.

Lines are walked in place rather than through bytes.Split, which would materialize a slice header for every line in the file up front, and each line is decoded into one reused map instead of a fresh one, which halves the allocations. A line that does not parse is skipped, as before, so one bad record cannot cost the whole file.

func LoadPluginFingerprints added in v0.12.0

func LoadPluginFingerprints() (map[string][]string, error)

LoadPluginFingerprints loads the per-plugin file fingerprint wordlist (files/plugin_fingerprints.txt). Each line is a relative path of the form "slug/file" (e.g. "woocommerce/woocommerce.php", "woocommerce/readme.txt"). Lines are grouped by slug into an ordered list of candidate files, with the priority order from the wordlist preserved. The bruteforce scanner probes these files and treats a 200 response as a confirmed hit (see issue #27). The result is cached globally since the embedded list never changes.

func LoadPluginsFromFile added in v0.6.0

func LoadPluginsFromFile(filename string) ([]string, error)

LoadPluginsFromFile loads a list of plugins from an embedded file or a user-specified file. The default embedded plugin list is cached globally since it never changes.

func ScanSite

func ScanSite(ctx ScanSiteContext)

func ScanTargets

func ScanTargets(opts ScanOptions)

Types

type AuthGroup added in v0.6.0

type AuthGroup struct {
	AuthTypes map[string][]CVEEntry
}

AuthGroup groups vulnerabilities by authentication type.

type BruteforceContext added in v0.9.0

type BruteforceContext struct {
	ScanContext
	Mu       *sync.Mutex
	Wg       *sync.WaitGroup
	Sem      chan struct{}
	Detected *[]string
	Versions *map[string]string
	// Forbidden collects slugs that matched ONLY via a 403 response. A bare 403 is
	// ambiguous: a plugin hardened with its own .htaccess and a WAF blocking the
	// slug for a plugin that is NOT installed look identical here (both forbid
	// every file under <slug>/). These are held and reconciled in aggregate after
	// the scan instead of being reported as confirmed installs (issue #27).
	Forbidden *[]string
	Ctx       context.Context
	Client    *wphttp.HTTPClientManager
	// Fingerprints maps a plugin slug to the ordered list of files to probe
	// (e.g. "woocommerce.php", "readme.txt"). The plugin is present on disk when
	// any of them returns a response that differs from the calibrated miss
	// baseline, even if it is installed but not activated.
	Fingerprints map[string][]string
	// Calibrator holds the per-target "not found" baseline so that file
	// detection works regardless of the web server (Apache/nginx) and its config.
	Calibrator *Calibrator
}

BruteforceContext contains context for bruteforce operations.

type BruteforceRequest added in v0.9.0

type BruteforceRequest struct {
	Target     string
	Plugins    []string
	Threads    int
	Progress   Progress
	HTTP       wphttp.Config
	Calibrator *Calibrator
}

BruteforceRequest contains request parameters for bruteforce operations.

type CVEEntry added in v0.11.3

type CVEEntry struct {
	ID    string
	Title string
}

CVEEntry holds a CVE ID and its title.

type Calibrator added in v0.12.0

type Calibrator struct {
	// contains filtered or unexported fields
}

Calibrator learns, per target, what a request for a NON-existent plugin file looks like. Detection then flags a probe as a hit only when its response does not match that learned "miss" baseline. This is what makes file probing work regardless of the web server and its config:

  • Apache routes any missing path to index.php -> WordPress answers with a canonical 301 to "<path>/" (or a 404).
  • nginx (try_files ... =404 in the php location) answers a missing .php with a hard 404, but a missing readme.txt with the same WordPress 301.
  • a hardened plugin (.htaccess deny) answers 403 for files that DO exist.
  • a soft-404 host answers 200 + the same page for everything.

In every case the response for a file that exists differs from the calibrated miss, so we never hardcode "200 = found".

func NewCalibrator added in v0.12.0

func NewCalibrator(ctx context.Context, client *http.HTTPClientManager, target string) *Calibrator

NewCalibrator probes each known-absent candidate several times because a host may answer inconsistently: BitFire, for instance, fabricates a plausible readme for roughly four requests out of five and 404s the rest, so a single probe per path can miss the template entirely. Every attempt is recorded, at calibrationAttempts * len(newCalibrationPaths()) requests per target, so the baseline covers each response the host alternates between.

func NewScanCalibrator added in v0.12.6

func NewScanCalibrator(ctx context.Context, target string, opts ScanOptions) *Calibrator

func (*Calibrator) FabricatesContent added in v0.12.6

func (calibrator *Calibrator) FabricatesContent() bool

FabricatesContent reports whether calibration was answered with a plausible plugin readme for a slug that cannot exist. Nothing keys off this beyond the user-facing warning: suppressing such a response is IsInstalled's job, which compares against the calibrated bodies with the response already in hand.

Re-probing a detected plugin to confirm it is fabricated cannot work on these hosts. Any path the confirmation picks is either the real file (which does not match the template) or an absent one such as Readme.txt, which the host fabricates for exactly the same reason it fabricated during calibration - so the check reports every real plugin as fake.

func (*Calibrator) IsInstalled added in v0.12.0

func (calibrator *Calibrator) IsInstalled(status int, body string) bool

IsInstalled reports whether a probe response indicates the file exists on disk, i.e. its signature does not match any calibrated miss.

type DisplayResultsContext added in v0.9.0

type DisplayResultsContext struct {
	Target    string
	Detected  map[string]string
	PluginRes PluginDetectionResult
	Results   []file.PluginEntry
	Opts      ScanOptions
	Progress  Progress
}

DisplayResultsContext contains context for displaying scan results.

type HTMLDiscoveryResult added in v0.11.0

type HTMLDiscoveryResult struct {
	Plugins []string
	Themes  []string
}

HTMLDiscoveryResult holds both plugins and themes discovered from HTML.

type HybridScanRequest added in v0.9.0

type HybridScanRequest struct {
	Target            string
	StealthyPlugins   []string
	BruteforcePlugins []string
	Threads           int
	Progress          Progress
	HTTP              wphttp.Config
}

HybridScanRequest contains request parameters for hybrid scan operations.

type PluginAuthGroups added in v0.6.0

type PluginAuthGroups struct {
	Plugins map[string]SeverityAuthGroup
}

PluginAuthGroups organizes vulnerabilities by plugin, severity, and auth type.

type PluginData added in v0.6.0

type PluginData struct {
	Score      int
	Confidence float64
	Ambiguous  bool
	Matches    []string
}

PluginData contains information about a detected plugin.

type PluginDetectionResult

type PluginDetectionResult struct {
	Plugins  map[string]*PluginData
	Detected []string
}

PluginDetectionResult contains the results of plugin detection.

func DetectPlugins

func DetectPlugins(
	detectedEndpoints []string,
	pluginEndpoints map[string][]string,
) PluginDetectionResult

DetectPlugins detects plugins by matching detected endpoints with known plugin endpoints.

type PluginVulnerabilities added in v0.6.0

type PluginVulnerabilities struct {
	Plugins map[string]VulnCategories
}

PluginVulnerabilities maps plugin names to their vulnerability categories.

type Progress added in v0.10.21

type Progress interface {
	Increment()
	Finish()
	SetTotal(int)
	SetMessage(string)
	RenderBlank()
	ClearLine()
	Bprintln(a ...interface{}) (int, error)
}

Progress defines the interface for progress reporting. The real implementation lives in internal/progress and is only imported by CLI code, keeping TUI dependencies out of the library path.

type ScanContext added in v0.9.0

type ScanContext struct {
	Target   string
	Threads  int
	HTTP     wphttp.Config
	Progress Progress
}

ScanContext contains context for scanning operations.

type ScanDetectionResult added in v0.11.0

type ScanDetectionResult struct {
	Plugins      []string
	Themes       []string
	PluginResult PluginDetectionResult
	Versions     map[string]string
}

ScanDetectionResult holds the combined results of plugin and theme detection.

type ScanExecutionConfig added in v0.9.0

type ScanExecutionConfig struct {
	Targets  []string
	Opts     ScanOptions
	Vulns    []wordfence.Vulnerability
	Config   scanConfig
	Progress Progress
	Writer   file.WriterInterface
}

ScanExecutionConfig contains all configuration for executing multiple scans.

type ScanExecutionContext added in v0.9.0

type ScanExecutionContext struct {
	Target   string
	Opts     ScanOptions
	Progress Progress
	Ctx      context.Context
}

ScanExecutionContext contains all context needed for executing a scan.

type ScanOptions

type ScanOptions struct {
	URL            string
	File           string
	NoCheckVersion bool
	Threads        int
	Output         string
	OutputFormat   string
	Verbose        bool
	ScanMode       string
	PluginList     string
	Headers        []string
	Proxy          string
	RateLimit      int                                      // Requests per second (0 = unlimited)
	MaxRedirects   int                                      // Maximum redirects to follow (0 = disable, -1 = default: 10)
	Context        context.Context                          // Context for cancellation
	HTTPClient     *http.Client                             // External HTTP client (optional, for connection pooling)
	SharedLimiter  *wphttp.RateLimiter                      // Global rate limiter shared across all targets
	Calibrator     *Calibrator                              // Per-target miss-response baseline
	NewProgress    func(total int, message string) Progress // Factory for creating progress bars (CLI only)
	DisplayFunc    func(DisplayResultsContext)              // Callback for displaying results (CLI only)
}

ScanOptions contains all configuration options for scanning.

type ScanSiteContext added in v0.9.0

type ScanSiteContext struct {
	Target   string
	Opts     ScanOptions
	Writer   file.WriterInterface
	Progress Progress
	Vulns    []wordfence.Vulnerability
}

ScanSiteContext contains all context needed for scanning a single site.

type SeverityAuthGroup added in v0.6.0

type SeverityAuthGroup struct {
	Severities map[string]AuthGroup
}

SeverityAuthGroup groups vulnerabilities by severity and auth type.

type TargetScanContext added in v0.9.0

type TargetScanContext struct {
	Target   string
	Opts     ScanOptions
	PerSite  int
	Writer   file.WriterInterface
	Progress Progress
	Vulns    []wordfence.Vulnerability
	Sem      chan struct{}
	Wg       *sync.WaitGroup
}

TargetScanContext contains context for scanning a single target.

type VulnCategories

type VulnCategories struct {
	Critical []string
	High     []string
	Medium   []string
	Low      []string
}

VulnCategories groups vulnerabilities by severity.

type VulnerabilityCheckContext added in v0.9.0

type VulnerabilityCheckContext struct {
	ScanContext
	Mu                  *sync.Mutex
	Wg                  *sync.WaitGroup
	Sem                 chan struct{}
	EntriesMap          *map[string]string
	EntriesList         *[]file.PluginEntry
	Vulnerabilities     []wordfence.Vulnerability
	VulnIndex           map[vulnIndexKeyType][]*wordfence.Vulnerability // Indexed by type and slug for fast lookup
	PreDetectedVersions map[string]string
	Ctx                 context.Context // Context for cancellation
	// Client is shared by every version lookup in the run. Building one per
	// plugin gives each its own empty connection pool, so no connection is ever
	// reused and every plugin pays a fresh TCP (and TLS) handshake.
	Client *wphttp.HTTPClientManager
}

VulnerabilityCheckContext contains context for vulnerability checking.

type VulnerabilityCheckRequest added in v0.9.0

type VulnerabilityCheckRequest struct {
	Plugins  []string
	Themes   []string
	Target   string
	Vulns    []wordfence.Vulnerability
	Opts     ScanOptions
	Progress Progress
	Versions map[string]string
	Ctx      context.Context // Context for cancellation
}

VulnerabilityCheckRequest contains request parameters for checking vulnerabilities.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL