fingerprinters

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Feb 21, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package fingerprinters provides HTTP fingerprinting for JFrog Artifactory.

Detection Strategy

JFrog Artifactory is a universal artifact repository manager that stores and manages software packages and dependencies. It's a critical infrastructure component that represents a security concern due to:

  • Storage of proprietary software artifacts
  • Access to internal source code and binaries
  • Potential supply chain attack vector
  • Often contains credentials and API tokens

Detection uses a two-pronged approach: 1. Passive: Check for Artifactory-specific response headers (X-JFrog-Version, X-Artifactory-Id, X-Artifactory-Node-Id) 2. Active: Query /artifactory/api/system/ping endpoint (no authentication required)

API Response Format

The /artifactory/api/system/ping endpoint returns "OK" with headers:

X-JFrog-Version: Artifactory/7.136.0 83600900
X-Artifactory-Id: 82452a18829b4122b65e8033d68e59c338b0cc06
X-Artifactory-Node-Id: a0rnvpm6mmcdc-artifactory-primary-0

Format breakdown:

  • X-JFrog-Version: "Artifactory/<VERSION> <REVISION>"
  • X-Artifactory-Id: Unique instance identifier
  • X-Artifactory-Node-Id: Node identifier for clustered deployments

Cloud vs On-Prem Differences

Both cloud and on-prem instances:

  • Use /artifactory/api/system/ping endpoint
  • Ping endpoint works WITHOUT authentication
  • Version information is provided in headers (X-JFrog-Version)

Cloud instances (e.g., jfrog.io):

  • Use /artifactory/ prefix for all API endpoints

On-prem instances (e.g., port 8081):

  • May use /api/ prefix directly for some endpoints
  • Ping endpoint still requires /artifactory/ prefix

Port Configuration

Artifactory typically runs on:

  • 8081: Default Artifactory web port (on-prem)
  • 8082: JFrog Platform Router port
  • 443: HTTPS in production and cloud deployments

Example Usage

fp := &ArtifactoryFingerprinter{}
if fp.Match(resp) {
	result, err := fp.Fingerprint(resp, body)
	if err == nil && result != nil {
		fmt.Printf("Detected: %s version %s\n", result.Technology, result.Version)
	}
}

Package fingerprinters provides HTTP fingerprinting for HashiCorp Consul.

Detection Strategy:

  • Active probe: /v1/agent/self endpoint
  • Required field: Config.Datacenter (Consul-specific)
  • Version extraction: Config.Version with Enterprise (+ent) detection
  • Ports: 8500 (HTTP), 8501 (HTTPS)

Package fingerprinters provides HTTP fingerprinting for Grafana.

Detection Strategy

Grafana is an open-source analytics and monitoring platform. Exposed instances represent a security concern due to:

  • Dashboard access with potentially sensitive data
  • Data source configurations with credentials
  • API key management
  • Often exposed without authentication

Detection uses active probing:

  • Active: Query /api/health endpoint (no authentication required)
  • Response must contain all three fields: database, version, commit

API Response Format

The /api/health endpoint returns JSON without authentication:

{
  "commit": "abc123def456",
  "database": "ok",
  "version": "10.4.1"
}

Port Configuration

Grafana typically runs on:

  • 3000: Default Grafana HTTP port
  • 443: HTTPS in production

Example Usage

fp := &GrafanaFingerprinter{}
if fp.Match(resp) {
	result, err := fp.Fingerprint(resp, body)
	if err == nil && result != nil {
		fmt.Printf("Detected: %s version %s\n", result.Technology, result.Version)
	}
}

Package fingerprinters provides HTTP fingerprinting for Jaeger.

Detection Strategy

Jaeger is a widely deployed distributed tracing system. Exposed instances represent a security concern due to:

  • Access to application tracing data revealing system architecture
  • Potential information disclosure about service dependencies
  • Exposure of performance metrics and call patterns
  • Query capabilities that could reveal sensitive information
  • Administrative endpoints that may be exposed

Detection uses two approaches: 1. Passive HTML detection: Check for <title>Jaeger UI</title> in root response and extract version from embedded JAEGER_VERSION JSON 2. Active JSON detection: Query /api/services endpoint (no authentication required)

API Response Format

The /api/services endpoint returns JSON without authentication:

{
  "data": ["service-a", "service-b", "checkout", "frontend"],
  "errors": null,
  "limit": 0,
  "offset": 0,
  "total": 4
}

Fresh instances with no traced services may return:

{
  "data": null,
  "errors": null,
  "limit": 0,
  "offset": 0,
  "total": 0
}

Or:

{
  "data": [],
  "errors": null,
  "limit": 0,
  "offset": 0,
  "total": 0
}

Format breakdown:

  • data: Array of service name strings, or null on fresh instances (required field)
  • errors: Error field, typically null (required field to exist - distinguishes from other JSON APIs)
  • total: Total count of services (required field)
  • limit: Pagination limit (required field)
  • offset: Pagination offset (required field)

Detection is based on the structural signature: the presence of all 5 fields (data, errors, total, limit, offset) uniquely identifies Jaeger's /api/services endpoint. No other common HTTP API returns this exact structure.

Port Configuration

Jaeger typically runs on:

  • 16686: Default Jaeger Query service HTTP port
  • 443: HTTPS in production deployments
  • 80: HTTP in some deployments

Example Usage

fp := &JaegerFingerprinter{}
if fp.Match(resp) {
	result, err := fp.Fingerprint(resp, body)
	if err == nil && result != nil {
		fmt.Printf("Detected: %s with %d services\n", result.Technology, result.Metadata["serviceCount"])
	}
}

Package fingerprinters provides HTTP fingerprinting for Jenkins CI/CD.

Detection Strategy

Jenkins is an open-source automation server used for CI/CD. It's a critical infrastructure component that represents a security concern due to:

  • Script Console access (Groovy RCE)
  • Build history with credentials
  • Pipeline configurations with secrets
  • Often exposed without authentication

Detection uses passive-only approach:

  • Check for Jenkins-specific response headers (X-Jenkins, X-Hudson)
  • Version extraction from X-Jenkins header (direct value, no parsing)
  • X-Hudson header indicates legacy Hudson compatibility

Response Headers

Jenkins sends identifying headers on all HTTP responses:

X-Jenkins: 2.541.1
X-Hudson: 1.395
X-Jenkins-Session: f55df8ea

Header breakdown:

  • X-Jenkins: Version string (primary detection and version extraction)
  • X-Hudson: Legacy Hudson compatibility version
  • X-Jenkins-Session: Session identifier (not used for detection)

Port Configuration

Jenkins typically runs on:

  • 8080: Default Jenkins web port
  • 443: HTTPS in production
  • 8443: Alternative HTTPS port

Example Usage

fp := &JenkinsFingerprinter{}
if fp.Match(resp) {
	result, err := fp.Fingerprint(resp, body)
	if err == nil && result != nil {
		fmt.Printf("Detected: %s version %s\n", result.Technology, result.Version)
	}
}

Package fingerprinters provides HTTP fingerprinting for Prometheus.

Detection Strategy

Prometheus is a widely deployed monitoring and alerting system. Exposed instances represent a security concern due to:

  • Access to infrastructure metrics and monitoring data
  • Potential information disclosure about system architecture
  • Query capabilities that could reveal sensitive information
  • Administrative endpoints that may be exposed

Detection uses a two-pronged approach: 1. Passive: Check for Content-Type: application/json header (weak pre-filter) 2. Active: Query /api/v1/status/buildinfo endpoint (no authentication required)

API Response Format

The /api/v1/status/buildinfo endpoint returns JSON without authentication:

{
  "status": "success",
  "data": {
    "version": "2.45.0",
    "revision": "abc123def456",
    "branch": "HEAD",
    "buildUser": "root@buildhost",
    "buildDate": "20231215-08:42:32",
    "goVersion": "go1.21.5"
  }
}

Format breakdown:

  • status: API response status (required, must be "success")
  • data: Build information object (required)
  • data.version: Prometheus version string (required for detection)
  • data.goVersion: Go version used to build (required, distinguishes from other APIs)
  • data.revision: Git commit hash (optional)
  • data.branch: Git branch (optional)
  • data.buildUser: User who built the binary (optional)
  • data.buildDate: Build timestamp (optional)

Port Configuration

Prometheus typically runs on:

  • 9090: Default Prometheus HTTP API port
  • 443: HTTPS in production deployments

Example Usage

fp := &PrometheusFingerprinter{}
if fp.Match(resp) {
	result, err := fp.Fingerprint(resp, body)
	if err == nil && result != nil {
		fmt.Printf("Detected: %s version %s\n", result.Technology, result.Version)
	}
}

Package fingerprinters provides HTTP fingerprinting for QNAP NAS devices.

Detection Strategy

QNAP NAS devices run QTS (QNAP Turbo Station) operating system, which is commonly found on customer attack surfaces. Detection of exposed NAS devices is critical because:

  • Often contain sensitive business data and backups
  • Frequently exposed to the internet for remote access
  • Target for ransomware and data exfiltration
  • May have admin interfaces exposed without authentication
  • Historical vulnerabilities in QTS firmware

Detection uses active probing of the authLogin.cgi endpoint which returns identifying XML without requiring authentication. This endpoint is unique to QNAP devices.

Response Format

The /cgi-bin/authLogin.cgi endpoint returns XML with device information:

<?xml version="1.0" encoding="UTF-8" ?>
<QDocRoot version="1.0">
<firmware>
  <version><![CDATA[4.4.1]]></version>
  <number><![CDATA[1216]]></number>
  <build><![CDATA[20200214]]></build>
</firmware>
<hostname><![CDATA[NAS-NAME]]></hostname>
<model>
  <displayModelName><![CDATA[TS-873U-RP]]></displayModelName>
</model>
</QDocRoot>

Response breakdown:

  • <QDocRoot> - Root element unique to QNAP devices (primary detection)
  • <firmware><version> - QTS version string (e.g., "4.4.1", "5.1.0")
  • <firmware><number> - Build number (e.g., "1216")
  • <firmware><build> - Build date in YYYYMMDD format
  • <model><displayModelName> - Hardware model (e.g., "TS-873U-RP")
  • <hostname> - Device hostname

Port Configuration

QNAP NAS devices typically expose web interfaces on:

  • 8080: HTTP (default)
  • 443: HTTPS (default)
  • 8081: Alternative HTTP port

Security Relevance

QNAP devices are frequently targeted in attacks:

  • CVE-2024-27130: SQL injection in Music Station
  • CVE-2023-23368: Authentication bypass in QTS
  • CVE-2021-28799: Hardcoded credentials
  • Regular targets for Qlocker, eCh0raix ransomware

Detection helps identify exposed devices for vulnerability assessment and remediation.

Example Usage

fp := &QNAPFingerprinter{}
// Probe /cgi-bin/authLogin.cgi endpoint
if fp.Match(resp) {
	result, err := fp.Fingerprint(resp, body)
	if err == nil && result != nil {
		fmt.Printf("Detected: %s version %s\n", result.Technology, result.Version)
	}
}

Package fingerprinters provides HTTP application fingerprinting. These fingerprinters detect applications running over HTTP and return technology/CPE metadata to attach to the HTTP service payload.

Package fingerprinters provides HTTP fingerprinting for SOAP APIs.

Detection Strategy

SOAP (Simple Object Access Protocol) is an XML-based messaging protocol used for web service communication. Exposed SOAP endpoints represent a security concern due to:

  • Potential information disclosure via WSDL service descriptions
  • XML-based attack surface (XXE, SSRF, XML injection)
  • Often exposed without authentication
  • Legacy systems with known vulnerabilities

Detection uses two approaches:

  1. Passive: Check Content-Type headers and response body for SOAP envelope namespaces and WSDL definitions
  2. Active: Query ?wsdl endpoint to discover WSDL service descriptions

Detection Markers

SOAP 1.1 responses contain the namespace:

http://schemas.xmlsoap.org/soap/envelope/

SOAP 1.2 responses contain the namespace:

http://www.w3.org/2003/05/soap-envelope

WSDL responses contain the namespace:

http://schemas.xmlsoap.org/wsdl/

SOAP 1.2 also uses the definitive Content-Type:

application/soap+xml

Port Configuration

SOAP services typically run on standard HTTP/HTTPS ports:

  • 80: HTTP
  • 443: HTTPS
  • 8080: Alternative HTTP
  • 8443: Alternative HTTPS

Example Usage

fp := &SOAPFingerprinter{}
if fp.Match(resp) {
	result, err := fp.Fingerprint(resp, body)
	if err == nil && result != nil {
		fmt.Printf("Detected: %s (version: %s)\n", result.Technology, result.Metadata["soapVersion"])
	}
}

Package fingerprinters provides HTTP fingerprinting for JetBrains TeamCity.

Detection Strategy

JetBrains TeamCity is a CI/CD build management server. Exposed instances represent a security concern due to:

  • Build configuration access with potentially sensitive environment variables
  • Source code repository connection credentials
  • Deployment pipeline secrets and API tokens
  • Build agent access allowing code execution

Detection uses a two-pronged approach:

  1. Passive: Check for TeamCity-specific response headers (TeamCity-Node-Id, X-TC-CSRF-Token)
  2. Active: Query /app/rest/server endpoint (may require authentication)

API Response Format

The /app/rest/server endpoint returns JSON (with Accept: application/json):

{
  "version": "2023.11.4 (build 147571)",
  "versionMajor": 2023,
  "versionMinor": 11,
  "buildNumber": "147571",
  "buildDate": "20240301T000000+0000",
  "internalId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "webUrl": "https://teamcity.example.com"
}

Or XML (default format):

<server version="2023.11.4 (build 147571)" buildNumber="147571"
        internalId="a1b2c3d4-e5f6-7890-abcd-ef1234567890"
        webUrl="https://teamcity.example.com"/>

Port Configuration

TeamCity typically runs on:

  • 8111: Default TeamCity HTTP port
  • 443: HTTPS in production
  • 8443: Alternative HTTPS port

Example Usage

fp := &TeamCityFingerprinter{}
if fp.Match(resp) {
	result, err := fp.Fingerprint(resp, body)
	if err == nil && result != nil {
		fmt.Printf("Detected: %s version %s\n", result.Technology, result.Version)
	}
}

Package fingerprinters provides HTTP fingerprinting for UPnP services.

Detection Strategy

UPnP (Universal Plug and Play) devices expose HTTP endpoints that serve XML device descriptions containing UPnP-specific schemas. Detection targets these HTTP responses.

Security relevance:

  • UPnP devices may expose internal network topology
  • SOAP control endpoints can allow device manipulation
  • Often found on IoT devices with weak security
  • Can be abused for SSRF or port mapping attacks

Detection uses passive approach on root HTTP response:

  • Check for SERVER header containing "UPnP" (case-insensitive substring)
  • Check response body for UPnP XML namespace (urn:schemas-upnp-org)
  • Extract server string and UPnP version information

Response Headers

UPnP devices typically include identifying headers:

SERVER: Linux/3.0 UPnP/1.0 IpBridge/1.16.0
Content-Type: text/xml; charset="utf-8"

Response Body

UPnP device descriptions contain XML with UPnP namespace:

<root xmlns="urn:schemas-upnp-org:device-1-0">
  <specVersion><major>1</major><minor>0</minor></specVersion>
  <device>
    <deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType>
    <friendlyName>Philips hue</friendlyName>
  </device>
</root>

Port Configuration

UPnP HTTP endpoints typically run on:

  • 2869: Windows UPnP Device Host
  • 5000: Synology DSM, various UPnP devices
  • 8080: Common alternative HTTP port
  • 49152-65535: Dynamic ports advertised via SSDP

Example Usage

fp := &UPnPFingerprinter{}
if fp.Match(resp) {
	result, err := fp.Fingerprint(resp, body)
	if err == nil && result != nil {
		fmt.Printf("Detected: %s version %s\n", result.Technology, result.Version)
	}
}

Package fingerprinters provides HTTP fingerprinting for HashiCorp Vault.

Detection Strategy

HashiCorp Vault is the most widely deployed secrets management solution. Exposed instances represent a critical security concern due to:

  • Storage of secrets and credentials
  • Potential access to sensitive data if unsealed
  • Cluster configuration information leakage
  • Authentication and authorization bypass vulnerabilities

Detection uses a two-pronged approach: 1. Passive: Check for Cache-Control: no-store header (weak pre-filter) 2. Active: Query /v1/sys/health endpoint (no authentication required)

API Response Format

The /v1/sys/health endpoint returns JSON without authentication:

{
  "initialized": true,
  "sealed": false,
  "version": "1.12.3",
  "cluster_name": "vault-cluster-7089ef9c",
  "cluster_id": "9c5dcbaa-7361-202d-3dba-b235c6f7f443",
  "enterprise": false
}

Format breakdown:

  • version: Vault version string (required for detection)
  • sealed: Whether the Vault is sealed (security critical)
  • initialized: Whether Vault has been initialized
  • cluster_name: Cluster identifier (optional)
  • enterprise: Whether this is Vault Enterprise

Port Configuration

Vault typically runs on:

  • 8200: Default Vault HTTP API port
  • 443: HTTPS in production deployments

Example Usage

fp := &VaultFingerprinter{}
if fp.Match(resp) {
	result, err := fp.Fingerprint(resp, body)
	if err == nil && result != nil {
		fmt.Printf("Detected: %s version %s\n", result.Technology, result.Version)
	}
}

Package fingerprinters provides HTTP fingerprinting for WinRM.

Detection Strategy

WinRM (Windows Remote Management) is a Microsoft implementation of WS-Management protocol for remote Windows system management. Detection identifies:

  • WinRM endpoints via Microsoft-HTTPAPI/2.0 server header
  • Probe /wsman endpoint (standard WS-Management path)
  • 401 Unauthorized indicates auth-required WinRM instance

Port Configuration:

  • 5985: HTTP (unencrypted WinRM)
  • 5986: HTTPS (encrypted WinRM)

Example Usage

fp := &WinRMFingerprinter{}
if fp.Match(resp) {
	result, err := fp.Fingerprint(resp, body)
	if err == nil && result != nil {
		fmt.Printf("Detected: %s\n", result.Technology)
	}
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetProbeEndpoints

func GetProbeEndpoints() map[string]string

GetProbeEndpoints returns a map of fingerprinter name to probe endpoint for all registered ActiveHTTPFingerprinters.

func Register

func Register(fp HTTPFingerprinter)

Register adds a fingerprinter to the registry

Types

type ActiveHTTPFingerprinter

type ActiveHTTPFingerprinter interface {
	HTTPFingerprinter

	// ProbeEndpoint returns the endpoint path to probe for this fingerprinter.
	// Return "" to use the default "/" endpoint.
	// Examples: "/version", "/api/v1/version", "/_cluster/health"
	ProbeEndpoint() string
}

ActiveHTTPFingerprinter extends HTTPFingerprinter with the ability to make additional HTTP requests for enrichment. Use this when detection requires querying specific endpoints (e.g., Kubernetes /version).

type AnyConnectFingerprinter

type AnyConnectFingerprinter struct{}

AnyConnectFingerprinter detects Cisco AnyConnect SSL VPN

func (*AnyConnectFingerprinter) Fingerprint

func (f *AnyConnectFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*AnyConnectFingerprinter) Match

func (f *AnyConnectFingerprinter) Match(resp *http.Response) bool

func (*AnyConnectFingerprinter) Name

func (f *AnyConnectFingerprinter) Name() string

func (*AnyConnectFingerprinter) ProbeEndpoint

func (f *AnyConnectFingerprinter) ProbeEndpoint() string

type ArangoDBFingerprinter

type ArangoDBFingerprinter struct{}

ArangoDBFingerprinter detects ArangoDB via /_api/version endpoint

func (*ArangoDBFingerprinter) Fingerprint

func (f *ArangoDBFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*ArangoDBFingerprinter) Match

func (f *ArangoDBFingerprinter) Match(resp *http.Response) bool

func (*ArangoDBFingerprinter) Name

func (f *ArangoDBFingerprinter) Name() string

func (*ArangoDBFingerprinter) ProbeEndpoint

func (f *ArangoDBFingerprinter) ProbeEndpoint() string

type ArtifactoryFingerprinter

type ArtifactoryFingerprinter struct{}

ArtifactoryFingerprinter detects JFrog Artifactory instances via /artifactory/api/system/ping endpoint

func (*ArtifactoryFingerprinter) Fingerprint

func (f *ArtifactoryFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*ArtifactoryFingerprinter) Match

func (f *ArtifactoryFingerprinter) Match(resp *http.Response) bool

func (*ArtifactoryFingerprinter) Name

func (f *ArtifactoryFingerprinter) Name() string

func (*ArtifactoryFingerprinter) ProbeEndpoint

func (f *ArtifactoryFingerprinter) ProbeEndpoint() string

type BigIPFingerprinter

type BigIPFingerprinter struct{}

BigIPFingerprinter detects F5 BIG-IP management interfaces and load balancers

func (*BigIPFingerprinter) Fingerprint

func (f *BigIPFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*BigIPFingerprinter) Match

func (f *BigIPFingerprinter) Match(resp *http.Response) bool

func (*BigIPFingerprinter) Name

func (f *BigIPFingerprinter) Name() string

func (*BigIPFingerprinter) ProbeEndpoint

func (f *BigIPFingerprinter) ProbeEndpoint() string

type ChromaDBFingerprinter

type ChromaDBFingerprinter struct{}

ChromaDBFingerprinter detects ChromaDB vector database via /api/v1/heartbeat endpoint

func (*ChromaDBFingerprinter) Fingerprint

func (f *ChromaDBFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*ChromaDBFingerprinter) Match

func (f *ChromaDBFingerprinter) Match(resp *http.Response) bool

func (*ChromaDBFingerprinter) Name

func (f *ChromaDBFingerprinter) Name() string

func (*ChromaDBFingerprinter) ProbeEndpoint

func (f *ChromaDBFingerprinter) ProbeEndpoint() string

type ConsulFingerprinter

type ConsulFingerprinter struct{}

ConsulFingerprinter detects HashiCorp Consul via /v1/agent/self

func (*ConsulFingerprinter) Fingerprint

func (f *ConsulFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*ConsulFingerprinter) Match

func (f *ConsulFingerprinter) Match(resp *http.Response) bool

func (*ConsulFingerprinter) Name

func (f *ConsulFingerprinter) Name() string

func (*ConsulFingerprinter) ProbeEndpoint

func (f *ConsulFingerprinter) ProbeEndpoint() string

type CouchDBFingerprinter

type CouchDBFingerprinter struct{}

CouchDBFingerprinter detects Apache CouchDB via root endpoint

func (*CouchDBFingerprinter) Fingerprint

func (f *CouchDBFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*CouchDBFingerprinter) Match

func (f *CouchDBFingerprinter) Match(resp *http.Response) bool

func (*CouchDBFingerprinter) Name

func (f *CouchDBFingerprinter) Name() string

func (*CouchDBFingerprinter) ProbeEndpoint

func (f *CouchDBFingerprinter) ProbeEndpoint() string

type ElasticsearchFingerprinter

type ElasticsearchFingerprinter struct{}

ElasticsearchFingerprinter detects Elasticsearch via root endpoint (/)

func (*ElasticsearchFingerprinter) Fingerprint

func (f *ElasticsearchFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*ElasticsearchFingerprinter) Match

func (f *ElasticsearchFingerprinter) Match(resp *http.Response) bool

func (*ElasticsearchFingerprinter) Name

type EtcdFingerprinter

type EtcdFingerprinter struct{}

EtcdFingerprinter detects etcd distributed key-value store via /version endpoint. Detection is based on the presence of "etcdserver" field in the JSON response.

func (*EtcdFingerprinter) Fingerprint

func (f *EtcdFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

Fingerprint performs etcd detection by parsing the /version JSON response.

func (*EtcdFingerprinter) Match

func (f *EtcdFingerprinter) Match(resp *http.Response) bool

Match returns true if the response might be from etcd (JSON content type).

func (*EtcdFingerprinter) Name

func (f *EtcdFingerprinter) Name() string

func (*EtcdFingerprinter) ProbeEndpoint

func (f *EtcdFingerprinter) ProbeEndpoint() string

ProbeEndpoint returns the endpoint needed for etcd detection. etcd exposes version info at /version endpoint.

type FingerprintResult

type FingerprintResult struct {
	Technology string         // e.g., "kubernetes"
	Version    string         // e.g., "1.29.0"
	CPEs       []string       // e.g., ["cpe:2.3:a:kubernetes:kubernetes:1.29.0:*:*:*:*:*:*:*"]
	Metadata   map[string]any // service-specific additional data
}

FingerprintResult contains the detected technology information

func RunFingerprinters

func RunFingerprinters(resp *http.Response, body []byte) []*FingerprintResult

RunFingerprinters executes all matching fingerprinters and returns results

type FortiGateFingerprinter

type FortiGateFingerprinter struct{}

FortiGateFingerprinter detects Fortinet FortiGate appliances.

Detection Strategy: FortiGate appliances run FortiOS with a distinctive obfuscated Server header (xxxxxxxx-xxxxx) and characteristic HTTP responses. Detection uses:

1. Server Header: xxxxxxxx-xxxxx (primary indicator, highest confidence) 2. ETag Format: "XX-XXXXXXXX" where second hex is Unix timestamp (firmware build date) 3. Body Patterns: /remote/login redirect, ftnt-fortinet-grid icon class (only with Server/ETag)

This fingerprinter addresses a detection gap where 3 FortiGate appliances on non-standard ports were invisible to the Chariot pipeline. FortiGate is a common enterprise security appliance, and detection is critical for attack surface visibility.

func (*FortiGateFingerprinter) Fingerprint

func (f *FortiGateFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*FortiGateFingerprinter) Match

func (f *FortiGateFingerprinter) Match(resp *http.Response) bool

func (*FortiGateFingerprinter) Name

func (f *FortiGateFingerprinter) Name() string

type GlobalProtectFingerprinter

type GlobalProtectFingerprinter struct{}

GlobalProtectFingerprinter detects Palo Alto GlobalProtect SSL VPN

func (*GlobalProtectFingerprinter) Fingerprint

func (f *GlobalProtectFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*GlobalProtectFingerprinter) Match

func (f *GlobalProtectFingerprinter) Match(resp *http.Response) bool

func (*GlobalProtectFingerprinter) Name

func (*GlobalProtectFingerprinter) ProbeEndpoint

func (f *GlobalProtectFingerprinter) ProbeEndpoint() string

type GrafanaFingerprinter

type GrafanaFingerprinter struct{}

GrafanaFingerprinter detects Grafana instances via /api/health endpoint

func (*GrafanaFingerprinter) Fingerprint

func (f *GrafanaFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*GrafanaFingerprinter) Match

func (f *GrafanaFingerprinter) Match(resp *http.Response) bool

func (*GrafanaFingerprinter) Name

func (f *GrafanaFingerprinter) Name() string

func (*GrafanaFingerprinter) ProbeEndpoint

func (f *GrafanaFingerprinter) ProbeEndpoint() string

type HTTPFingerprinter

type HTTPFingerprinter interface {
	// Name returns the fingerprinter identifier
	Name() string

	// Match returns true if this fingerprinter should attempt detection
	// This is a fast pre-filter based on headers/status before reading body
	Match(resp *http.Response) bool

	// Fingerprint performs full detection and extracts technology info
	// body is the response body (already read)
	Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)
}

HTTPFingerprinter detects applications running over HTTP

func GetFingerprinterByName

func GetFingerprinterByName(name string) HTTPFingerprinter

GetFingerprinterByName returns the fingerprinter with the given name

func GetFingerprinters

func GetFingerprinters() []HTTPFingerprinter

GetFingerprinters returns all registered fingerprinters

type JaegerFingerprinter

type JaegerFingerprinter struct{}

JaegerFingerprinter detects Jaeger instances via /api/services endpoint

func (*JaegerFingerprinter) Fingerprint

func (f *JaegerFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*JaegerFingerprinter) Match

func (f *JaegerFingerprinter) Match(resp *http.Response) bool

func (*JaegerFingerprinter) Name

func (f *JaegerFingerprinter) Name() string

func (*JaegerFingerprinter) ProbeEndpoint

func (f *JaegerFingerprinter) ProbeEndpoint() string

type JenkinsFingerprinter

type JenkinsFingerprinter struct{}

JenkinsFingerprinter detects Jenkins instances via X-Jenkins and X-Hudson headers

func (*JenkinsFingerprinter) Fingerprint

func (f *JenkinsFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*JenkinsFingerprinter) Match

func (f *JenkinsFingerprinter) Match(resp *http.Response) bool

func (*JenkinsFingerprinter) Name

func (f *JenkinsFingerprinter) Name() string

type KubernetesFingerprinter

type KubernetesFingerprinter struct{}

KubernetesFingerprinter detects Kubernetes API servers via /version endpoint

func (*KubernetesFingerprinter) Fingerprint

func (f *KubernetesFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*KubernetesFingerprinter) Match

func (f *KubernetesFingerprinter) Match(resp *http.Response) bool

func (*KubernetesFingerprinter) Name

func (f *KubernetesFingerprinter) Name() string

func (*KubernetesFingerprinter) ProbeEndpoint

func (f *KubernetesFingerprinter) ProbeEndpoint() string

type NATSFingerprinter

type NATSFingerprinter struct{}

NATSFingerprinter detects NATS monitoring via /varz endpoint. Detection is based on the presence of "server_id" field in the JSON response.

func (*NATSFingerprinter) Fingerprint

func (f *NATSFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

Fingerprint performs NATS detection by parsing the response (JSON or HTML).

func (*NATSFingerprinter) Match

func (f *NATSFingerprinter) Match(resp *http.Response) bool

Match returns true if the response might be from NATS (JSON or HTML content type).

func (*NATSFingerprinter) Name

func (f *NATSFingerprinter) Name() string

func (*NATSFingerprinter) ProbeEndpoint

func (f *NATSFingerprinter) ProbeEndpoint() string

ProbeEndpoint returns the endpoint needed for NATS detection. NATS exposes monitoring info at /varz endpoint.

type PineconeFingerprinter

type PineconeFingerprinter struct{}

PineconeFingerprinter detects Pinecone Vector Database instances via header-based detection.

Detection Strategy: Pinecone is a managed vector database (SaaS) that runs on HTTPS. When an unauthenticated request is sent to a Pinecone endpoint, the service returns a 401 Unauthorized response with Pinecone-specific headers:

  • X-Pinecone-Api-Version (PRIMARY marker - unique to Pinecone)
  • X-Pinecone-Auth-Rejected-Reason (SECONDARY marker)

Version Detection: The X-Pinecone-Api-Version header contains the API version (e.g., "2025-01"), not the internal Pinecone service version. Since Pinecone is closed-source SaaS, the internal version cannot be determined. Therefore, the CPE uses a wildcard version.

func (*PineconeFingerprinter) Fingerprint

func (f *PineconeFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

Fingerprint performs detection by checking for Pinecone-specific headers.

Detection Phases:

  1. PRIMARY: Check for X-Pinecone-Api-Version header (unique to Pinecone)
  2. SECONDARY: Check for X-Pinecone-Auth-Rejected-Reason header (fallback)

Returns:

  • *FingerprintResult with Pinecone detection if headers present
  • nil if not detected
  • error is always nil (no parsing errors possible for header-based detection)

func (*PineconeFingerprinter) Match

func (f *PineconeFingerprinter) Match(resp *http.Response) bool

Match returns true for ALL responses. We need to check headers regardless of content type since detection is header-based.

func (*PineconeFingerprinter) Name

func (f *PineconeFingerprinter) Name() string

type PrometheusFingerprinter

type PrometheusFingerprinter struct{}

PrometheusFingerprinter detects Prometheus instances via /api/v1/status/buildinfo endpoint

func (*PrometheusFingerprinter) Fingerprint

func (f *PrometheusFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*PrometheusFingerprinter) Match

func (f *PrometheusFingerprinter) Match(resp *http.Response) bool

func (*PrometheusFingerprinter) Name

func (f *PrometheusFingerprinter) Name() string

func (*PrometheusFingerprinter) ProbeEndpoint

func (f *PrometheusFingerprinter) ProbeEndpoint() string

type QNAPFingerprinter

type QNAPFingerprinter struct{}

QNAPFingerprinter detects QNAP NAS devices via authLogin.cgi endpoint

func (*QNAPFingerprinter) Fingerprint

func (f *QNAPFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*QNAPFingerprinter) Match

func (f *QNAPFingerprinter) Match(resp *http.Response) bool

func (*QNAPFingerprinter) Name

func (f *QNAPFingerprinter) Name() string

func (*QNAPFingerprinter) ProbeEndpoint

func (f *QNAPFingerprinter) ProbeEndpoint() string

type SOAPFingerprinter

type SOAPFingerprinter struct{}

SOAPFingerprinter detects SOAP API services via envelope namespaces and WSDL

func (*SOAPFingerprinter) Fingerprint

func (f *SOAPFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*SOAPFingerprinter) Match

func (f *SOAPFingerprinter) Match(resp *http.Response) bool

func (*SOAPFingerprinter) Name

func (f *SOAPFingerprinter) Name() string

func (*SOAPFingerprinter) ProbeEndpoint

func (f *SOAPFingerprinter) ProbeEndpoint() string

type TeamCityFingerprinter

type TeamCityFingerprinter struct{}

TeamCityFingerprinter detects JetBrains TeamCity instances via /app/rest/server endpoint

func (*TeamCityFingerprinter) Fingerprint

func (f *TeamCityFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*TeamCityFingerprinter) Match

func (f *TeamCityFingerprinter) Match(resp *http.Response) bool

func (*TeamCityFingerprinter) Name

func (f *TeamCityFingerprinter) Name() string

func (*TeamCityFingerprinter) ProbeEndpoint

func (f *TeamCityFingerprinter) ProbeEndpoint() string

type UPnPFingerprinter

type UPnPFingerprinter struct{}

UPnPFingerprinter detects UPnP services via HTTP response headers and body content

func (*UPnPFingerprinter) Fingerprint

func (f *UPnPFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*UPnPFingerprinter) Match

func (f *UPnPFingerprinter) Match(resp *http.Response) bool

func (*UPnPFingerprinter) Name

func (f *UPnPFingerprinter) Name() string

type VaultFingerprinter

type VaultFingerprinter struct{}

VaultFingerprinter detects HashiCorp Vault instances via /v1/sys/health endpoint

func (*VaultFingerprinter) Fingerprint

func (f *VaultFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*VaultFingerprinter) Match

func (f *VaultFingerprinter) Match(resp *http.Response) bool

func (*VaultFingerprinter) Name

func (f *VaultFingerprinter) Name() string

func (*VaultFingerprinter) ProbeEndpoint

func (f *VaultFingerprinter) ProbeEndpoint() string

type WinRMFingerprinter

type WinRMFingerprinter struct{}

WinRMFingerprinter detects WinRM instances via Microsoft-HTTPAPI header on /wsman endpoint

func (*WinRMFingerprinter) Fingerprint

func (f *WinRMFingerprinter) Fingerprint(resp *http.Response, body []byte) (*FingerprintResult, error)

func (*WinRMFingerprinter) Match

func (f *WinRMFingerprinter) Match(resp *http.Response) bool

func (*WinRMFingerprinter) Name

func (f *WinRMFingerprinter) Name() string

func (*WinRMFingerprinter) ProbeEndpoint

func (f *WinRMFingerprinter) ProbeEndpoint() string

Jump to

Keyboard shortcuts

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