shadow1ng/fscan · warning

authentication failed: %s

Error message

authentication failed: %s

What it means

During the SCRAM-SHA-1 handshake (doMongoDBAuth), the server's saslStart reply parsed successfully but reported ok:false with an errmsg. fscan wraps the server's message as 'authentication failed: <errmsg>'. This is an application-level auth rejection from MongoDB (wrong user/password, user not found, mechanism not permitted), not a network failure; the AuthResult carries ErrorType ErrorTypeAuth.

Source

Thrown at plugins/services/mongodb.go:142

		kv("autoAuthorize", 1),
	))
	if _, err := sendMongoMsg(ctx, conn, saslStartCmd, timeout); err != nil {
		state.IncrementTCPFailedPacketCount()
		return &AuthResult{Success: false, ErrorType: ErrorTypeNetwork, Error: err}
	}
	resp, err = readMongoMsg(conn, timeout)
	if err != nil {
		state.IncrementTCPFailedPacketCount()
		return &AuthResult{Success: false, ErrorType: ErrorTypeNetwork, Error: err}
	}

	startReply, err := parseMongoCommandReply(resp)
	if err != nil {
		state.IncrementTCPFailedPacketCount()
		return &AuthResult{Success: false, ErrorType: ErrorTypeNetwork, Error: err}
	}
	if !startReply.ok {
		return &AuthResult{Success: false, ErrorType: ErrorTypeAuth, Error: fmt.Errorf("authentication failed: %s", startReply.errmsg)}
	}
	if !startReply.conversationSet || len(startReply.payload) == 0 {
		return &AuthResult{Success: false, ErrorType: ErrorTypeAuth, Error: fmt.Errorf("invalid saslStart response")}
	}

	serverFirst := string(startReply.payload)
	clientFinal, err := buildMongoSCRAMClientFinal(cred.Username, cred.Password, clientFirstBare, serverFirst)
	if err != nil {
		return &AuthResult{Success: false, ErrorType: ErrorTypeAuth, Error: err}
	}

	saslContinueCmd := buildMongoCommand("admin", orderedDoc(
		kv("saslContinue", 1),
		kv("conversationId", int(startReply.conversationID)),
		kv("payload", []byte(clientFinal)),
	))
	if _, err := sendMongoMsg(ctx, conn, saslContinueCmd, timeout); err != nil {
		state.IncrementTCPFailedPacketCount()

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Treat as an expected per-credential rejection in brute mode; check state counters instead of treating it as a hard failure.
  2. Verify the target MongoDB allows SCRAM-SHA-1 (getParameter authenticationMechanisms) or use SCRAM-SHA-256-capable tooling.
  3. Ensure the tested user exists in the 'admin' database, since the plugin authenticates against $db=admin.
  4. Confirm the username:password pair manually with mongosh --host ... -u user -p pass --authenticationDatabase admin.
  5. Inspect startReply.errmsg text: 'Authentication failed' means bad credentials; 'mechanism' errors point to server config.

Example fix

// before
result := TestCredentialsConcurrently(ctx, credentials, authFn, "mongodb", testConfig)
log.Println(result.Error) // authentication failed: Authentication failed.
// after
result := TestCredentialsConcurrently(ctx, credentials, authFn, "mongodb", testConfig)
if !result.Success && result.ErrorType == ErrorTypeAuth {
    log.Printf("credential rejected (auth): %v — continue with next candidate", result.Error)
} else if !result.Success {
    log.Printf("non-auth failure, aborting: %v", result.Error)
}
Defensive patterns

Strategy: type-guard

Validate before calling

// before brute-forcing, confirm SCRAM-SHA-1 is enabled on the target
status := shell("mongosh --quiet --host %s --eval 'db.runCommand({getParameter:1, authenticationMechanisms:1})'", target)
if !strings.Contains(status, "SCRAM-SHA-1") {
	log.Println("target does not advertise SCRAM-SHA-1; auth failures expected")
}

Type guard

func isAuthRejection(ar *services.AuthResult) bool {
	return ar != nil && !ar.Success && ar.ErrorType == services.ErrorTypeAuth
}

Try / catch

ar := authFn(ctx, cred)
if isAuthRejection(ar) {
	log.Printf("credential %s:%s rejected by server: %v", cred.Username, cred.Password, ar.Error)
	// continue to next credential; do not treat as network failure
} else if !ar.Success {
	log.Printf("transient/network failure: %v — retry eligible", ar.Error)
}

Prevention

When it happens

Trigger: Calling Scan (brute mode) which drives TestCredentialsConcurrently -> doMongoDBAuth whenever a saslStart/saslContinue command reply has ok=false, e.g. wrong username or password in Credential, user absent from the admin db, SCRAM-SHA-1 disabled via authenticationMechanisms, or the server rejecting the payload.

Common situations: Brute-forcing with dictionaries that don't match the deployment's users; testing users that exist only in a non-admin database (fscan authenticates against 'admin'); MongoDB instances with SCRAM-SHA-256-only configuration; typo'd or role-restricted credentials; servers where 'authorization' disallows the probe.

Understand the failure class

Related errors


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