{"record":{"id":"0002b8094dd7c8d3","repo":"shadow1ng/fscan","slug":"invalid-ber-tag","errorCode":null,"errorMessage":"invalid ber tag","messagePattern":"invalid ber tag","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"libs/grdp/protocol/t125/ber/ber.go","lineNumber":46,"sourceCode":"\tTAG_INTEGER               = 0x02\n\tTAG_BIT_STRING            = 0x03\n\tTAG_OCTET_STRING          = 0x04\n\tTAG_OBJECT_IDENFIER       = 0x06\n\tTAG_ENUMERATED            = 0x0A\n\tTAG_SEQUENCE              = 0x10\n\tTAG_SEQUENCE_OF           = 0x10\n)\n\nfunc berPC(pc bool) uint8 {\n\tif pc {\n\t\treturn PC_CONSTRUCT\n\t}\n\treturn PC_PRIMITIVE\n}\n\nfunc ReadEnumerated(r io.Reader) (uint8, error) {\n\tif !ReadUniversalTag(TAG_ENUMERATED, false, r) {\n\t\treturn 0, errors.New(\"invalid ber tag\")\n\t}\n\tlength, err := ReadLength(r)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tif length != 1 {\n\t\treturn 0, errors.New(fmt.Sprintf(\"enumerate size is wrong, get %v, expect 1\", length))\n\t}\n\treturn core.ReadUInt8(r)\n}\n\nfunc ReadUniversalTag(tag uint8, pc bool, r io.Reader) bool {\n\tbb, _ := core.ReadUInt8(r)\n\treturn bb == (CLASS_UNIV|berPC(pc))|(TAG_MASK&tag)\n}\n\nfunc WriteUniversalTag(tag uint8, pc bool, w io.Writer) {\n\tcore.WriteUInt8((CLASS_UNIV|berPC(pc))|(TAG_MASK&tag), w)","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/libs/grdp/protocol/t125/ber/ber.go#L28-L64","documentation":"ReadEnumerated parses a BER-encoded ENUMERATED value in the X.224/T.125 CONNECT_RESPONSE. It first checks the universal tag byte equals TAG_ENUMERATED; if the byte read from the stream does not match, the stream is not a valid BER enumerated field and this error is returned.","triggerScenarios":"ReadConnectResponse -> ReadEnumerated when the byte at the enumerated field position is not the TAG_ENUMERATED universal tag — i.e. the CONNECT_RESPONSE payload is misaligned, truncated, or not BER-encoded as expected.","commonSituations":"Pointing the client at a non-RDP service on port 3389; server response desynchronized by earlier protocol mismatch (wrong security/negotiation flags); proxies mangling bytes so field boundaries shift.","solutions":["Verify the target is a real RDP server (telnet/nc banner check or Wireshark capture of the X.224 exchange)","Dump the raw bytes around the enumerated field and compare the CONNECT_RESPONSE layout against T.125 to find the misalignment","Ensure X.224 negotiation (requestedProtocols) matches what the server supports so the response is well-formed","Check for TLS/proxy interference between client and server corrupting the stream"],"exampleFix":"// before\nif !ReadUniversalTag(TAG_ENUMERATED, false, r) {\n    return 0, errors.New(\"invalid ber tag\")\n}\n\n// after\nif !ReadUniversalTag(TAG_ENUMERATED, false, r) {\n    bb, _ := r.(io.ByteReader)\n    _ = bb\n    return 0, fmt.Errorf(\"invalid ber tag: expected ENUMERATED (0x0A), got 0x%02X\", lastByte)\n}","handlingStrategy":"validation","validationCode":"// validate the endpoint before running the full handshake\nfunc isRdpEndpoint(host string, port int) bool {\n    c, err := net.DialTimeout(\"tcp\", fmt.Sprintf(\"%s:%d\", host, port), 3*time.Second)\n    if err != nil { return false }\n    defer c.Close()\n    // send X.224 CR and check the response starts with a valid RDP negotiation header\n    return probeX224(c) == nil\n}","typeGuard":null,"tryCatchPattern":"if _, err := ber.ReadEnumerated(connBuf); err != nil {\n    if strings.Contains(err.Error(), \"invalid ber tag\") {\n        return fmt.Errorf(\"server response is not a valid T.125 CONNECT_RESPONSE: %w\", err)\n    }\n    return err\n}","preventionTips":["Always probe the port for an RDP server before full connect","Keep requestedProtocols aligned with what the server advertises","Log raw handshake bytes at debug level to diagnose tag mismatches quickly"],"tags":["rdp","ber","asn1","protocol-parsing"],"backgroundTag":"invalid-argument-format","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"}