{"record":{"id":"00360091d5b28f8e","repo":"shadow1ng/fscan","slug":"parse-certificate-w","errorCode":null,"errorMessage":"parse certificate: %w","messagePattern":"parse certificate: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"libs/grdp/protocol/t125/gcc/gcc.go","lineNumber":415,"sourceCode":"\ntype CertBlob struct {\n\tCbCert uint32 `struc:\"little,sizeof=AbCert\"`\n\tAbCert []byte `struc:\"little\"`\n}\ntype X509CertificateChain struct {\n\tNumCertBlobs  uint32     `struc:\"little,sizeof=CertBlobArray\"`\n\tCertBlobArray []CertBlob `struc:\"little\"`\n\tPadding       []byte     `struc:\"[12]byte\"`\n}\n\nfunc (x *X509CertificateChain) GetPublicKey() (*rsa.PublicKey, error) {\n\tif len(x.CertBlobArray) == 0 {\n\t\treturn nil, errors.New(\"empty certificate chain\")\n\t}\n\tdata := x.CertBlobArray[len(x.CertBlobArray)-1].AbCert\n\tcert, err := x509.ParseCertificate(data)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"parse certificate: %w\", err)\n\t}\n\tif cert.PublicKey == nil {\n\t\tvar pubKeyInfo struct {\n\t\t\tAlgorithm        pkix.AlgorithmIdentifier\n\t\t\tSubjectPublicKey asn1.BitString\n\t\t}\n\t\t_, err = asn1.Unmarshal(cert.RawSubjectPublicKeyInfo, &pubKeyInfo)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"unmarshal public key info: %w\", err)\n\t\t}\n\t\trsaPublicKey, err := x509.ParsePKCS1PublicKey(pubKeyInfo.SubjectPublicKey.Bytes)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"parse PKCS1 public key: %w\", err)\n\t\t}\n\t\treturn rsaPublicKey, nil\n\t}\n\trsaPublicKey, ok := cert.PublicKey.(*rsa.PublicKey)\n\tif !ok {","sourceCodeStart":397,"sourceCodeEnd":433,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/libs/grdp/protocol/t125/gcc/gcc.go#L397-L433","documentation":"When extracting the server's public key from the X.509 certificate chain carried in the GCC data, x509.ParseCertificate failed on the last certificate blob (AbCert) of the chain. The library wraps the underlying ASN.1 parse error with 'parse certificate: %w'.","triggerScenarios":"The AbCert bytes from CertBlobArray are not a valid DER-encoded X.509 certificate — truncated data, proprietary (non-X.509) certificate format (e.g. PROPRIETARYCERT in the server cert chain), or a parser misalignment.","commonSituations":"Old/quirky RDP servers that use proprietary certificate types instead of X509_CERTIFICATE_CHAIN; MTU/truncation issues in handshake capture; grdp parser bugs on exotic server configs.","solutions":["Hex-dump the AbCert blob and verify it starts with a DER SEQUENCE (0x30 0x82).","Check the cert chain blob type; if the server sends PROPRIETARYCERT, this parser path does not apply.","Update grdp to a version with broader server-certificate handling.","Verify the ServerSecurityData/GCC parsing offsets are correct for this server's response."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"func looksLikeDER(b []byte) bool { return len(b) > 2 && b[0] == 0x30 }\nif !looksLikeDER(certBlob) { return errors.New(\"cert blob is not DER X.509; likely proprietary cert type\") }","typeGuard":null,"tryCatchPattern":"pub, err := certChain.PublicKey()\nif err != nil && strings.Contains(err.Error(), \"parse certificate:\") {\n\treturn fmt.Errorf(\"server certificate unreadable (possibly proprietary cert format): %w\", err)\n}","preventionTips":["Check the server cert chain blob type before assuming X.509.","Prefer NLA mode where server cert handling is TLS-based.","Hex-dump AbCert blobs when debugging nonstandard servers.","Keep grdp updated for proprietary-certificate handling."],"tags":["x509","certificate","parsing","rdp","gcc"],"backgroundTag":"schema-validation-failed","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"}