shadow1ng/fscan · warning
service_not_identified
Error message
service_not_identified
What it means
identifyService probes the target and tries to classify the response banner as MSSQL by looking for markers such as 'sql server' in the response/error text. When the banner cannot be identified as MSSQL, it returns a failed ScanResult with i18n message 'service_not_identified' parameterized with 'MSSQL'.
Source
Thrown at plugins/services/mssql.go:158
state.IncrementTCPSuccessPacketCount()
}
var banner string
errLower := ""
if err != nil {
errLower = strings.ToLower(err.Error())
}
if err == nil || (result != nil && result.isMSSQL()) ||
(strings.Contains(errLower, "login failed") ||
strings.Contains(errLower, "mssql") ||
strings.Contains(errLower, "sql server")) {
banner = "MSSQL"
} else {
return &ScanResult{
Success: false,
Service: "mssql",
Error: fmt.Errorf("%s", i18n.Tr("service_not_identified", "MSSQL")),
}
}
session.LogSuccess(i18n.Tr("mssql_service", target, banner))
return &ScanResult{
Type: plugins.ResultTypeService,
Success: true,
Service: "mssql",
Banner: banner,
}
}
func init() {
RegisterPluginWithPorts("mssql", func() Plugin {
return NewMSSQLPlugin()
}, []int{1433, 1434})
}View on GitHub (pinned to 95cc12e753)
Solutions
- Verify the target port actually runs MSSQL/TDS (1433 or configured port)
- Widen the banner match to include more SQL Server error markers or use a TDS prelogin probe
- Bypass identification by forcing the mssql plugin if the service is known
- Inspect the raw probe response to add the missing banner keyword to the match list
Example fix
// before
} else {
return &ScanResult{Success: false, Error: fmt.Errorf("%s", i18n.Tr("service_not_identified", "MSSQL"))}
}
// after
} else if strings.Contains(errLower, "microsoft") || strings.Contains(errLower, "tds") {
banner = "MSSQL"
} else {
return &ScanResult{Success: false, Error: fmt.Errorf("%s", i18n.Tr("service_not_identified", "MSSQL"))}
} Defensive patterns
Strategy: fallback
Validate before calling
// confirm the service before running MSSQL identification
conn, err := net.DialTimeout("tcp", target, 5*time.Second)
if err != nil { return err }
// send a TDS prelogin and check the response mentions SQL Server
banner, err := probeTDSBanner(conn)
if err != nil || !strings.Contains(strings.ToLower(banner), "sql server") {
return errors.New("target does not look like MSSQL; skipping plugin")
} Try / catch
res := plugin.Scan(info, config, state)
if !res.Success && res.Error != nil && strings.Contains(res.Error.Error(), "service_not_identified") {
// fall back to a generic port/service scan to classify the target
log.Printf("service not identified as MSSQL: %v", res.Error)
} Prevention
- Only run the mssql plugin against ports verified to speak TDS
- Extend banner-matching keywords when new SQL Server error variants appear
- Force the plugin explicitly when the service is already known
- Capture raw probe output when identification fails to refine matches
When it happens
Trigger: Scan → identifyService: the probe response (or its error text) contains none of the expected markers (e.g. 'sql server'), so the else-branch fires. Typical with non-MSSQL services on port 1433, TLS-wrapped TDS banners, or locally translated/obscure server error text.
Common situations: Scanning a MySQL/PostgreSQL port mislabeled as 1433; SQL Server configured to hide its version; proxy or VPN altering the banner; a case variant not matched by strings.Contains on errLower.
Related errors
- service_no_credentials
- failed to write realtime backup: %w
- failed to sync realtime backup: %w
- failed to create JSON file: %w
- failed to marshal result: %w
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/56a1cf1243c94af8.
Report an issue: GitHub.