From 533fb3f7e4a5ae23f69d1837cd851d35ff5b76ce Mon Sep 17 00:00:00 2001 From: Neal Patel Date: Fri, 15 May 2026 19:57:52 +0000 Subject: [PATCH] ssh: fix source-address critical option bypass Previously, CVE-2024-45337 fixed an authorization bypass for misused ssh server configurations; if any other type of callback is passed other than public key, then the source-address validation would be skipped. Fixes CVE-2026-46595 Fixes golang/go#79570 Change-Id: I08d86a961048a232c8672f23000e693ed5a0e2fd Reviewed-on: https://go-review.googlesource.com/c/crypto/+/781642 LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com Reviewed-by: Neal Patel Reviewed-by: Roland Shoemaker --- ssh/server.go | 7 +++++++ ssh/server_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/ssh/server.go b/ssh/server.go index dd1c327..0192a67 100644 --- a/ssh/server.go +++ b/ssh/server.go @@ -837,6 +837,13 @@ userAuthLoop: // considered verified and the callback must not run. perms, authErr = config.VerifiedPublicKeyCallback(s, pubKey, perms, algo) } + if authErr == nil && perms != nil && perms.CriticalOptions != nil { + if saco := perms.CriticalOptions[sourceAddressCriticalOption]; saco != "" { + if err := checkSourceAddress(s.RemoteAddr(), saco); err != nil { + authErr = err + } + } + } } case "gssapi-with-mic": if authConfig.GSSAPIWithMICConfig == nil { diff --git a/ssh/server_test.go b/ssh/server_test.go index 2982ca3..2900b61 100644 --- a/ssh/server_test.go +++ b/ssh/server_test.go @@ -669,6 +669,44 @@ func TestVerifiedPubKeyCallbackError(t *testing.T) { } } +func TestVerifiedPubKeyCallbackSourceAddress(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + serverConf := &ServerConfig{ + PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { + return nil, nil + }, + VerifiedPublicKeyCallback: func(conn ConnMetadata, key PublicKey, permissions *Permissions, signatureAlgorithm string) (*Permissions, error) { + return &Permissions{ + CriticalOptions: map[string]string{ + sourceAddressCriticalOption: "192.168.99.99", + }, + }, nil + }, + } + serverConf.AddHostKey(testSigners["rsa"]) + + clientConf := ClientConfig{ + User: "user", + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"]), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + go NewServerConn(c1, serverConf) + + _, _, _, err = NewClientConn(c2, "", &clientConf) + if err == nil { + t.Fatal("client login succeed with VerifiedPublicKeyCallback returning mismatching source-address") + } +} + func TestVerifiedPublicCallbackPartialSuccessBadUsage(t *testing.T) { c1, c2, err := netPipe() if err != nil {