ssh/knownhosts: verify declared key type matches decoded key
The parseLine function previously ignored the key type field (e.g., "ssh-rsa") in known_hosts entries, relying solely on the type information embedded within the base64-encoded key blob. OpenSSH's sshkey_read implementation explicitly verifies that the key type declared in the text matches the type of the parsed key, returning SSH_ERR_KEY_TYPE_MISMATCH if they differ. This change adds a check to ensure the declared key type matches key.Type(), returning an error for malformed lines where they diverge. This issue was found during a security audit by NCC Group Cryptography Services, sponsored by Teleport, and was assessed and is being fixed as a non-security bug. Change-Id: Id4f35c74055f5691088273630b50cdd02c81bfe9 Reviewed-on: https://go-review.googlesource.com/c/crypto/+/782427 Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Filippo Valsorda <filippo@golang.org> LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Junyang Shao <shaojunyang@google.com>
This commit is contained in:
@@ -192,8 +192,7 @@ func parseLine(line []byte) (marker, host string, key ssh.PublicKey, err error)
|
||||
return "", "", nil, errors.New("knownhosts: missing host pattern")
|
||||
}
|
||||
|
||||
// ignore the keytype as it's in the key blob anyway.
|
||||
_, line = nextWord(line)
|
||||
wantType, line := nextWord(line)
|
||||
if len(line) == 0 {
|
||||
return "", "", nil, errors.New("knownhosts: missing key type pattern")
|
||||
}
|
||||
@@ -209,6 +208,10 @@ func parseLine(line []byte) (marker, host string, key ssh.PublicKey, err error)
|
||||
return "", "", nil, err
|
||||
}
|
||||
|
||||
if key.Type() != wantType {
|
||||
return "", "", nil, fmt.Errorf("knownhosts: key type mismatch: found %q, want %q", key.Type(), wantType)
|
||||
}
|
||||
|
||||
return marker, host, key, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
@@ -446,3 +447,18 @@ func TestUnicodeSpaceTrimming(t *testing.T) {
|
||||
t.Errorf("Did not match dirty host, implying parsing issue")
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeyTypeMismatch(t *testing.T) {
|
||||
line := fmt.Sprintf("server.org ssh-rsa %s", base64.StdEncoding.EncodeToString(edKey.Marshal()))
|
||||
|
||||
db := newHostKeyDB()
|
||||
err := db.Read(bytes.NewBufferString(line), "testdb")
|
||||
if err == nil {
|
||||
t.Fatal("Read succeeded on line with key type mismatch, expected error")
|
||||
}
|
||||
|
||||
expectedErr := `knownhosts: key type mismatch: found "ssh-ed25519", want "ssh-rsa"`
|
||||
if !strings.Contains(err.Error(), expectedErr) {
|
||||
t.Fatalf("got error %q, want to contain %q", err.Error(), expectedErr)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user