projectdiscovery/nuclei · warning
NTLM response too short: need at least 48 bytes, got %d
Error message
NTLM response too short: need at least 48 bytes, got %d
What it means
After locating NTLMSSP and the 0xFF 0xF0 terminator, ParseNTLMResponse enforces a 48-byte minimum: the fixed NTLM Challenge header (through the target-info offset field ending at byte 48) must be intact before any field offsets are read. Shorter blobs return 'NTLM response too short: need at least 48 bytes, got %d' — a hardening check to prevent out-of-range slices and panics on garbage data.
Source
Thrown at pkg/utils/telnetmini/ntlm.go:47
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))
}
messageType := binary.LittleEndian.Uint32(ntlmData[8:12])
if messageType != 2 {
return nil, fmt.Errorf("expected NTLM challenge message, got type %d", messageType)
}
// Parse target name fields
targetNameLen := binary.LittleEndian.Uint16(ntlmData[12:14])
targetNameOffset := binary.LittleEndian.Uint32(ntlmData[16:20])
// Parse target info fields
targetInfoLen := binary.LittleEndian.Uint16(ntlmData[40:42])
targetInfoOffset := binary.LittleEndian.Uint32(ntlmData[44:48])
// Extract target name (Target Name will always be returned under any implementation)
var targetName string
if targetNameLen > 0 && int(targetNameOffset) < len(ntlmData) {View on GitHub (pinned to 265b3a3dec)
Solutions
- Treat as malformed/unsupported NTLM and continue the scan — the data carries no parseable info
- Retry once to rule out transient truncation from read deadlines
- Raise the timeout if integrating telnetmini directly and targeting high-latency networks
- If it reproduces deterministically, hexdump the payload — likely a decoy or non-compliant device worth noting in findings
Defensive patterns
Strategy: validation
Validate before calling
// Enforce the same 48-byte floor before parsing:
start := bytes.Index(raw, []byte("NTLMSSP"))
end := bytes.Index(raw[start:], []byte{0xFF, 0xF0})
if end < 48 {
return nil, fmt.Errorf("NTLM blob too short (%d bytes) — malformed or decoy", end)
}
// safe to call ParseNTLMResponse Type guard
func ntlmLongEnough(data []byte) bool {
i := bytes.Index(data, []byte("NTLMSSP"))
if i == -1 { return false }
j := bytes.Index(data[i:], []byte{0xFF, 0xF0})
return j >= 48
} Try / catch
if err != nil && strings.Contains(err.Error(), "too short") {
// malformed/decoy payload — record host as 'NTLM malformed' and move on
return nil
} Prevention
- Never index NTLM fields without the length check — the parser's guard exists to prevent panics
- Hexdump persistently-short blobs; honeypots often fake the signature
- Rate-limit probes so slow servers can finish sending the blob
When it happens
Trigger: An NTLMSSP signature followed by a terminator but with fewer than 48 bytes between them: heavily truncated payloads, decoy/honeypot banners containing the literal string 'NTLMSSP', or non-standard implementations emitting abbreviated messages. The distance between signature and terminator is exactly what is measured.
Common situations: Honeypots and tarpits that echo keywords to elicit further probes; aggressive scanners pasting the NTLMSSP magic without a real message; responses cut by the 1-second read deadline mid-payload.
Related errors
- NTLMSSP signature not found in response
- NTLM response not properly terminated with Sub-option End
- expected NTLM challenge message, got type %d
- failed to send MS-TNAP login packet: %w
- no response received
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/acfb4a5773817ad4.
Report an issue: GitHub.