{"record":{"id":"d1e5edcc77d45238","repo":"shadow1ng/fscan","slug":"gssapi-bind-w","errorCode":null,"errorMessage":"GSSAPI bind: %w","messagePattern":"GSSAPI bind: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/local/systeminfo_dc_windows.go","lineNumber":97,"sourceCode":"\tclient, err := gssapi.NewSSPIClient()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"SSPI: %w\", err)\n\t}\n\tdefer func() { _ = client.Close() }()\n\n\tconn, err := ldap.DialURL(ldapURL(dcHost, 389))\n\tif err != nil {\n\t\tif ipv4, resolveErr := resolveIPv4(dcHost); resolveErr == nil {\n\t\t\tconn, err = ldap.DialURL(ldapURL(ipv4, 389))\n\t\t}\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"LDAP dial: %w\", err)\n\t\t}\n\t}\n\n\tif err := conn.GSSAPIBind(client, fmt.Sprintf(\"ldap/%s\", dcHost), \"\"); err != nil {\n\t\t_ = conn.Close()\n\t\treturn nil, fmt.Errorf(\"GSSAPI bind: %w\", err)\n\t}\n\n\tbaseDN, err := p.getBaseDN(conn, domain)\n\tif err != nil {\n\t\t_ = conn.Close()\n\t\treturn nil, err\n\t}\n\n\treturn &domainInfo{Domain: domain, BaseDN: baseDN, LDAPConn: conn}, nil\n}\n\nfunc (p *SystemInfoPlugin) findDC(domain string) (string, error) {\n\tif out, err := exec.Command(\"nslookup\", \"-type=SRV\", fmt.Sprintf(\"_ldap._tcp.dc._msdcs.%s\", domain)).Output(); err == nil {\n\t\tfor _, line := range strings.Split(string(out), \"\\n\") {\n\t\t\tif common.ContainsAny(line, \"svr hostname\", \"service\") {\n\t\t\t\tparts := strings.Split(line, \"=\")\n\t\t\t\tif len(parts) > 1 {\n\t\t\t\t\thost := strings.TrimSpace(parts[len(parts)-1])","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/plugins/local/systeminfo_dc_windows.go#L79-L115","documentation":"After dialing the DC over LDAP, connectToDomain attempts a Kerberos GSSAPI bind using the plugin's client credentials with the SPN \"ldap/<dcHost>\". If the bind is rejected or fails, the connection is closed and the error is wrapped as \"GSSAPI bind: %w\". This is an authentication failure against the directory, not a network failure.","triggerScenarios":"conn.GSSAPIBind(client, fmt.Sprintf(\"ldap/%s\", dcHost), \"\") returns non-nil: invalid/expired Kerberos ticket or credentials, missing cached TGT (kinit not run), SPN mismatch, clock skew breaking Kerberos, or the account being locked out/disabled.","commonSituations":"Scanner machine not domain-joined and no Kerberos ticket obtained (no kinit), wrong credentials supplied to the client, time drift >5 minutes between scanner and DC breaking Kerberos, DC rejecting the ldap/<host> SPN because hostname case/DNS alias differs from the registered SPN.","solutions":["Obtain a valid Kerberos ticket before scanning: run kinit (or use the domain account's credentials) on the scanning host and verify with klist.","Verify the supplied client credentials are valid and the account is not locked/disabled.","Synchronize clocks between the scanning host and the DC (w32tm /resync) — Kerberos tolerates at most ~5 minutes skew.","Confirm dcHost matches the DC's registered SPN (ldap/<fqdn>); use the FQDN rather than an IP or alias."],"exampleFix":"// before: bind fails because no ticket exists\nconn, err := ldap.DialURL(ldapURL(dcHost, 389))\nerr = conn.GSSAPIBind(client, fmt.Sprintf(\"ldap/%s\", dcHost), \"\") // GSSAPI bind: ...\n// after: ensure a ticket first (caller-side setup)\n//   kinit user@CORP.EXAMPLE.COM\n//   klist  # verify krb5 ticket\nconn, err := ldap.DialURL(ldapURL(dcHost, 389))\nerr = conn.GSSAPIBind(client, fmt.Sprintf(\"ldap/%s\", dcHost), \"\")","handlingStrategy":"try-catch","validationCode":"// Verify a Kerberos ticket exists before the scan\nout, err := exec.Command(\"klist\").Output()\nif err != nil || !strings.Contains(string(out), \"krbtgt\") {\n    return fmt.Errorf(\"no Kerberos ticket: run kinit first\")\n}","typeGuard":null,"tryCatchPattern":"result := plugin.Scan(ctx, host, session)\nif result != nil && !result.Success && strings.HasPrefix(result.Error.Error(), \"GSSAPI bind:\") {\n    // treat as auth failure: refresh credentials/ticket, resync time, do not blind-retry\n}","preventionTips":["Always kinit (or supply valid domain credentials) before running AD plugins.","Keep scanner clock in sync with the DC (w32tm) to avoid Kerberos skew rejection.","Use the DC's FQDN so the ldap/<host> SPN matches what the KDC expects."],"tags":["ldap","kerberos","authentication","windows","active-directory"],"backgroundTag":"authentication-required","analyzedSha":"95cc12e753bf43de7004e5aef42a9ffba3934303","analyzedAt":"2026-09-06T17:07:30.094Z","contentChangedAt":"2026-09-06T17:07:30.094Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}