shadow1ng/fscan · error

SASL authenticate error: %d

Error message

SASL authenticate error: %d

What it means

doKafkaAuth parses the SaslAuthenticate response and treats a non-zero big-endian int16 error_code in the first 2 bytes as an authentication failure. The broker accepted the handshake but rejected the PLAIN credentials token (wrong user/pass) or the auth state is illegal. The code is included in the wrapped message.

Source

Thrown at plugins/services/kafka.go:132

			}
		}

		// SaslAuthenticate: PLAIN token = \x00user\x00pass (api_key=36, api_version=0)
		token := []byte("\x00" + cred.Username + "\x00" + cred.Password)
		authBody := kafkaBytes(token)
		if err := kafkaSend(conn, 36, 0, authBody); err != nil {
			state.IncrementTCPFailedPacketCount()
			return &AuthResult{Success: false, ErrorType: ErrorTypeNetwork, Error: err}
		}
		resp, err = kafkaRecv(conn)
		if err != nil {
			state.IncrementTCPFailedPacketCount()
			return &AuthResult{Success: false, ErrorType: classifyKafkaErrorType(err), Error: err}
		}
		if len(resp) >= 2 {
			code := int16(binary.BigEndian.Uint16(resp[:2]))
			if code != 0 {
				return &AuthResult{Success: false, ErrorType: ErrorTypeAuth, Error: fmt.Errorf("SASL authenticate error: %d", code)}
			}
		}
	}

	// Step 3: Metadata 请求验证连接 (api_key=3, api_version=0)
	// body: [topics_array] -> empty array = request all topics
	metaBody := []byte{0x00, 0x00, 0x00, 0x00} // empty topics array + allow_auto_topic_creation=false
	if err := kafkaSend(conn, 3, 0, metaBody); err != nil {
		state.IncrementTCPFailedPacketCount()
		return &AuthResult{Success: false, ErrorType: ErrorTypeNetwork, Error: err}
	}
	_, err = kafkaRecv(conn)
	if err != nil {
		state.IncrementTCPFailedPacketCount()
		return &AuthResult{Success: false, ErrorType: ErrorTypeNetwork, Error: err}
	}

	state.IncrementTCPSuccessPacketCount()

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Verify credentials manually with kcat/kafka-console-producer to confirm they are wrong vs the mechanism being wrong
  2. Check sasl.enabled.mechanisms on the broker; if only SCRAM is enabled, PLAIN tokens will always fail
  3. Treat code 58 as an expected 'bad credential' result in scan output rather than an unexpected error
  4. Ensure JAAS/user ACLs permit the user on the target listener

Example fix

// before
if code != 0 {
    return &AuthResult{Success: false, ErrorType: ErrorTypeAuth, Error: fmt.Errorf("SASL authenticate error: %d", code)}
}
// after
if code != 0 {
    et := ErrorTypeAuth
    if code == 58 { et = ErrorTypeAuth } // explicit bad-credentials mapping
    return &AuthResult{Success: false, ErrorType: et, Error: fmt.Errorf("SASL authenticate error: %d", code)}
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify credentials out-of-band before scanning:
// kcat -b broker:9092 -X security.protocol=SASL_PLAINTEXT -X sasl.mechanisms=PLAIN -X sasl.username=u -X sasl.password=p -L

Type guard

func isBadCredentials(code int16) bool { return code == 58 } // SaslAuthenticationFailed

Try / catch

res := plugin.Scan(info, config, state)
for _, r := range res.AuthResults {
    if r.Error != nil && strings.Contains(r.Error.Error(), "SASL authenticate error") {
        if isBadCredentials(extractCode(r.Error)) {
            log.Println("kafka: invalid credential pair")
        } else {
            log.Printf("kafka: auth state error: %v", r.Error)
        }
    }
}

Prevention

When it happens

Trigger: doKafkaAuth: SaslAuthenticate request (api_key=36, PLAIN token \x00user\x00pass) receives a response with non-zero error code — typically code 58 (SaslAuthenticationFailed) for bad credentials.

Common situations: Wrong username/password in the credential list (expected during brute-force scanning); broker requires SCRAM instead of PLAIN so the token is rejected; credentials valid only for a different listener/mechanism; account locked or ACL-denied user.

Understand the failure class

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/2c253146373da723. Report an issue: GitHub.