{"record":{"id":"ee293c5da8293ef8","repo":"shadow1ng/fscan","slug":"invalid-targetinfolen-value","errorCode":null,"errorMessage":"Invalid TargetInfoLen value","messagePattern":"Invalid TargetInfoLen value","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"libs/grdp/protocol/tpkt/tpkt.go","lineNumber":233,"sourceCode":"\t\t2: \"NetBIOSDomainName\",\n\t\t3: \"FQDN\", // DNS Computer Name\n\t\t4: \"DNSDomainName\",\n\t\t5: \"DNSTreeName\",\n\t\t7: \"Timestamp\",\n\t\t9: \"MsvAvTargetName\",\n\t}\n\n\ttype AVPair struct {\n\t\tAvID  uint16\n\t\tAvLen uint16\n\t\t// Value (variable)\n\t}\n\tvar avPairLen = 4\n\ttargetInfoLen := int(responseData.TargetInfoLen)\n\tif targetInfoLen > 0 {\n\t\tstartIdx := int(responseData.TargetInfoBufferOffset)\n\t\tif startIdx+targetInfoLen > len(response) {\n\t\t\treturn fmt.Errorf(\"Invalid TargetInfoLen value\")\n\t\t}\n\t\tvar avPair AVPair\n\t\tavPairBuf := bytes.NewBuffer(response[startIdx : startIdx+avPairLen])\n\t\terr = binary.Read(avPairBuf, binary.LittleEndian, &avPair)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcurrIdx := startIdx\n\t\tfor avPair.AvID != 0 {\n\t\t\tif field, exists := AvIDMap[avPair.AvID]; exists {\n\t\t\t\tvar value string\n\t\t\t\tr := response[currIdx+avPairLen : currIdx+avPairLen+int(avPair.AvLen)]\n\t\t\t\tif avPair.AvID == 7 {\n\t\t\t\t\tunixStamp := binary.LittleEndian.Uint64(r)/10000000 - 11644473600\n\t\t\t\t\ttm := time.Unix(int64(unixStamp), 0)\n\t\t\t\t\tvalue = tm.Format(\"2006-01-02 15:04:05\")\n\t\t\t\t} else {\n\t\t\t\t\tvalue = strings.ReplaceAll(string(r), \"\\x00\", \"\")","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/libs/grdp/protocol/tpkt/tpkt.go#L215-L251","documentation":"recvChallenge parses the NTLM CHALLENGE message returned by the RDP server during NLA (CredSSP) authentication. TargetInfoLen says how many bytes of AV_PAIR (server version, domain, SPN, etc.) data follow, and the library throws this when TargetInfoBufferOffset + TargetInfoLen runs past the end of the received buffer — i.e. the length/offset fields are inconsistent with the actual packet, so the TargetInfo would be read out of bounds. It guards against malformed or truncated server responses.","triggerScenarios":"Calling StartNLA when the server's NTLM CHALLENGE message declares a TargetInfoLen/TargetInfoBufferOffset pair whose range extends beyond the bytes actually captured (truncated read, misparsed negotiate response, or a non-Windows/gateway server sending a nonstandard NTLM message).","commonSituations":"Connecting to RDP behind gateways/proxies or non-Windows servers that emit shortened or reordered NTLM CHALLENGE fields; packet fragmentation causing response buffer truncation; TLS interception appliances mangling the CredSSP handshake.","solutions":["Verify the target is a genuine Windows RDP endpoint; test with a standard client (mstsc) to confirm the server's NLA handshake is well-formed","Upgrade grdp to a version that reassembles fragmented TPKT packets before parsing NTLM messages","Bypass middleboxes/gateways that rewrite CredSSP traffic, or connect directly to the RDP host","Capture the handshake (Wireshark, CREDSSP/NTLM filters) and compare TargetInfoLen/offset against the real message to identify where parsing diverges"],"exampleFix":"// before\nif startIdx+targetInfoLen > len(response) {\n    return fmt.Errorf(\"Invalid TargetInfoLen value\")\n}\n// after\nif startIdx < 0 || targetInfoLen < 0 || startIdx+targetInfoLen > len(response) {\n    return fmt.Errorf(\"Invalid TargetInfoLen value (offset=%d len=%d pkt=%d)\", startIdx, targetInfoLen, len(response))\n}","handlingStrategy":"validation","validationCode":"if targetInfoLen > 0 {\n    off := int(responseData.TargetInfoBufferOffset)\n    if off < 0 || off+targetInfoLen > len(response) {\n        return fmt.Errorf(\"truncated TargetInfo: need %d bytes at %d, have %d\", targetInfoLen, off, len(response))\n    }\n}","typeGuard":"func validTargetInfo(response []byte, offset, length int) bool {\n    return offset >= 0 && length >= 0 && offset+length <= len(response)\n}","tryCatchPattern":"if err := client.Login(host, user, pass); err != nil {\n    if strings.Contains(err.Error(), \"Invalid TargetInfoLen\") {\n        // malformed NTLM challenge from server; try non-NLA mode or different endpoint\n        return fallbackToNonNLA(host, user, pass)\n    }\n    return err\n}","preventionTips":["Connect only to servers that pass a standard RDP client handshake","Keep the grdp library updated for fragmented-packet reassembly fixes","Avoid routing CredSSP through rewriting proxies/inspection appliances","Log raw challenge bytes when debugging so offset/length mismatches are diagnosable"],"tags":["rdp","nla","ntlm","protocol-parsing"],"backgroundTag":"unexpected-response-shape","analyzedSha":"95cc12e753bf43de7004e5aef42a9ffba3934303","analyzedAt":"2026-09-06T17:07:30.094Z","contentChangedAt":"2026-09-06T17:07:30.094Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}