shadow1ng/fscan · error
invalid saslStart response
Error message
invalid saslStart response
What it means
doMongoDBAuth performs a SCRAM-SHA-1 handshake against MongoDB. After sending saslStart, the server reply must set the conversation id and carry a non-empty payload containing the server-first message. If either is missing, the plugin rejects the reply as an 'invalid saslStart response' because the SCRAM challenge cannot proceed without it.
Source
Thrown at plugins/services/mongodb.go:145
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()
return &AuthResult{Success: false, ErrorType: ErrorTypeNetwork, Error: err}
}
resp, err = readMongoMsg(conn, timeout)View on GitHub (pinned to 95cc12e753)
Solutions
- Verify the target is a genuine MongoDB server by checking the hello/ismaster handshake response before attempting auth
- Bypass or remove intermediate proxies/load balancers that alter OP_MSG payloads
- Confirm the server supports SCRAM (authenticationMechanisms in getCmdLineOpts); if only MONGODB-CR/x509 is enabled use the appropriate plugin path
- Re-run the scan directly against the host to rule out transient packet corruption
Example fix
// before
if !startReply.conversationSet || len(startReply.payload) == 0 {
return &AuthResult{Success: false, ErrorType: ErrorTypeAuth, Error: fmt.Errorf("invalid saslStart response")}
}
// after
if !startReply.conversationSet || len(startReply.payload) == 0 {
return &AuthResult{Success: false, ErrorType: ErrorTypeAuth,
Error: fmt.Errorf("invalid saslStart response (conversationSet=%v payloadLen=%d)", startReply.conversationSet, len(startReply.payload))}
} Defensive patterns
Strategy: try-catch
Validate before calling
// Go: verify target speaks MongoDB before auth
if err := probeHello(ctx, addr); err != nil {
return fmt.Errorf("not a MongoDB endpoint: %w", err)
} Type guard
func validSaslStart(reply mongoReply) bool {
return reply.ok && reply.conversationSet && len(reply.payload) > 0
} Try / catch
res, err := doMongoDBAuth(ctx, addr, cred)
if err != nil {
var authErr *AuthResult
if errors.As(err, &authErr) && authErr.ErrorType == ErrorTypeAuth {
log.Warn("saslStart reply malformed; target may not be SCRAM-capable")
return
}
return err
} Prevention
- Run a hello/ismaster fingerprint before attempting SCRAM auth
- Scan direct connections without proxies on 27017
- Confirm authenticationMechanisms include SCRAM-SHA-1 on the target
When it happens
Trigger: The MongoDB server responds to the saslStart OpMsg command with ok=true but omits the 'conversationId' field or returns an empty 'payload' byte string — e.g. a proxy/middleware strips fields, or the server does not actually speak SCRAM.
Common situations: Scanning a mongod behind a load balancer or API gateway that mangles OP_MSG replies; targeting a non-MongoDB service on port 27017 that mimics minimal BSON responses; MongoDB versions/configurations with authentication mechanisms restricted so SCRAM negotiation behaves unexpectedly.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- invalid SCRAM server-first payload
- cassandra error: %s
- authentication failed: %s
- invalid SCRAM nonce
- invalid SCRAM salt: %w
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/aeac10e3f1a5b1ff.
Report an issue: GitHub.