projectdiscovery/nuclei · info

NTLMSSP signature not found in response

Error message

NTLMSSP signature not found in response

What it means

ParseNTLMResponse (pkg/utils/telnetmini/ntlm.go) implements the Nmap telnet-ntlm-info.nse logic: it searches the telnet sub-option payload for the ASCII 'NTLMSSP' signature. If absent, the server never sent NTLM data and parsing cannot proceed — this is the expected negative path for any host that does not negotiate NTLM over telnet.

Source

Thrown at pkg/utils/telnetmini/ntlm.go:31

	NetBIOSDomainName   string // NetBIOS_Domain_Name from script
	NetBIOSComputerName string // NetBIOS_Computer_Name from script
	DNSDomainName       string // DNS_Domain_Name from script
	DNSComputerName     string // DNS_Computer_Name from script
	DNSTreeName         string // DNS_Tree_Name from script
	ProductVersion      string // Product_Version from script
	Timestamp           uint64 // Raw timestamp for skew calculation
}

// ParseNTLMResponse parses the NTLM response to extract system information
// This implements the exact parsing logic from the Nmap telnet-ntlm-info.nse script
func ParseNTLMResponse(data []byte) (*NTLMInfoResponse, error) {
	// Continue only if NTLMSSP response is returned.
	// Verify that the response is terminated with Sub-option End values as various
	// non Microsoft telnet implementations support NTLM but do not return valid data.
	// This matches the script's: local data = string.match(response, "(NTLMSSP.*)\xff\xf0")
	ntlmStart := bytes.Index(data, []byte("NTLMSSP"))
	if ntlmStart == -1 {
		return nil, fmt.Errorf("NTLMSSP signature not found in response")
	}

	// Find the end of NTLM data (Sub-option End: 0xFF 0xF0)
	ntlmEnd := bytes.Index(data[ntlmStart:], []byte{0xFF, 0xF0})
	if ntlmEnd == -1 {
		return nil, fmt.Errorf("NTLM response not properly terminated with Sub-option End")
	}

	// Extract NTLM data (NTLMSSP.*\xff\xf0)
	ntlmData := data[ntlmStart : ntlmStart+ntlmEnd]

	// Check message type (should be 2 for Challenge).
	// The fixed header runs to offset 48 (target-info offset field ends at byte 48),
	// so reject anything shorter before touching any field offsets.
	if len(ntlmData) < 48 {
		return nil, fmt.Errorf("NTLM response too short: need at least 48 bytes, got %d", len(ntlmData))
	}

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Gate the call: only parse NTLM when the encryption negotiation indicated support, or check bytes.Contains(data, []byte("NTLMSSP")) first
  2. Treat this error as 'NTLM not supported' — a normal finding, not a failure; make matchers/extractors handle its absence
  3. Add template conditions (e.g. service detection or banner match) before running the NTLM telnet probe
  4. Log it at debug/info level in custom tooling rather than surfacing as a scan error

Example fix

// before
info, err := telnetmini.ParseNTLMResponse(resp)
if err != nil { return err }

// after
if !bytes.Contains(resp, []byte("NTLMSSP")) {
    return nil // host does not speak NTLM over telnet; skip
}
info, err := telnetmini.ParseNTLMResponse(resp)
if err != nil { return err }
Defensive patterns

Strategy: validation

Validate before calling

// Cheap pre-check mirroring the parser's own first guard:
if !bytes.Contains(raw, []byte("NTLMSSP")) {
    // server does not speak NTLM over telnet — skip, not an error
    return nil, nil
}
info, err := telnetmini.ParseNTLMResponse(raw)

Type guard

func hasNTLMSignature(data []byte) bool {
    return bytes.Index(data, []byte("NTLMSSP")) != -1
}

Try / catch

info, err := telnetmini.ParseNTLMResponse(resp)
if err != nil {
    if strings.Contains(err.Error(), "signature not found") {
        return nil // expected on non-Windows hosts
    }
    return err // real parse problems propagate
}

Prevention

When it happens

Trigger: Calling ParseNTLMResponse on a telnet response from a non-Windows host (Linux telnetd, busybox, network gear) that answered the IAC DO ENCRYPT / IAC WILL ENCRYPT negotiation without NTLMSSP content; or calling it unconditionally on banners that never claimed NTLM support (skipping the supportsEncryption check from NegotiateEncryption).

Common situations: Network templates enumerating telnet info broadly across a /24; security scanning where most port-23 targets are embedded/Linux systems; template authors testing against a Windows lab and then running against mixed fleets.

Related errors


AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15). Data as JSON: /api/errors/1392d616753c57fb. Report an issue: GitHub.