Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions auth/halfauth_research.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,8 @@ func (s *HalfSigner) Sign(rand io.Reader, data []byte) (*ssh.Signature, error) {
copy(s.SignData, data)
return nil, ErrHalfAuth
}

// SignWithAlgorithm makes HalfSigner an ssh.AlgorithmSigner so RSA keys are probed with rsa-sha2-* instead of SHA-1 ssh-rsa.
func (s *HalfSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*ssh.Signature, error) {
return s.Sign(rand, data)
}
21 changes: 15 additions & 6 deletions auth/results.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,31 @@ func (r *AuthResult) SupportsHostKey(t string) bool {
}

func (r *AuthResult) SupportsPubKeyType(t string) bool {
// Example: ssh-ed25519,sk-ssh-ed25519@openssh.com,sk-ecdsa-sha2-nistp256@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,rsa-sha2-256,rsa-sha2-512,ssh-rsa,ssh-dss
okTypes, ok := r.Extensions["server-sig-algs"]
if !ok {
// Assume all types are supported unless the server
// has told us otherwise via the extension.
if !ok || strings.TrimSpace(okTypes) == "" {
return true
}
// ssh-rsa keys are usable when the server advertises any RSA signature algo;
// modern OpenSSH (>= 8.8) only offers rsa-sha2-256/rsa-sha2-512, not ssh-rsa.
wanted := sigAlgosForKeyType(t)
for kt := range strings.SplitSeq(okTypes, ",") {
kt = strings.TrimSpace(kt)
if strings.EqualFold(kt, t) {
return true
for _, w := range wanted {
if strings.EqualFold(kt, w) {
return true
}
}
}
return false
}

func sigAlgosForKeyType(t string) []string {
if t == "ssh-rsa" {
return []string{"ssh-rsa", "rsa-sha2-256", "rsa-sha2-512"}
}
return []string{t}
}

func (r *AuthResult) AddVuln(v VulnResult) {
r.Vulns = append(r.Vulns, v)
}
27 changes: 27 additions & 0 deletions auth/results_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package auth

import "testing"

func TestSupportsPubKeyType(t *testing.T) {
const modern = "ssh-ed25519,ecdsa-sha2-nistp256,rsa-sha2-512,rsa-sha2-256"
const legacy = "ssh-ed25519,rsa-sha2-256,rsa-sha2-512,ssh-rsa"

cases := []struct {
sigAlgs string
keyType string
want bool
}{
{modern, "ssh-rsa", true},
{modern, "ssh-ed25519", true},
{legacy, "ssh-rsa", true},
{"ssh-ed25519", "ssh-rsa", false},
{modern, "ecdsa-sha2-nistp521", false},
}

for _, tc := range cases {
r := &AuthResult{Extensions: map[string]string{"server-sig-algs": tc.sigAlgs}}
if got := r.SupportsPubKeyType(tc.keyType); got != tc.want {
t.Errorf("SupportsPubKeyType(%q) with %q = %v, want %v", tc.keyType, tc.sigAlgs, got, tc.want)
}
}
}
Loading