Closed abakum closed 4 months ago
Thank you for the report, but more concrete information on the nature of the issue is needed:
@revoked
as well as a normal non-revoked knownhosts line? (That situation seems incredibly rare in the real world I'd think?)Does this only come up with non-standard ports, or can it be reproduced with standard ports?
No, but OpenSSH acts predictably, unlike golang known_hosts:
* ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBARrpBl177hs/ykMnXHfkjmyKTbsax/vtSl+rInZvJoF8LfJaWCZSrai0uD5qRuYhy4QnJs563NBTmCgSBhm/MA=
@revoked [10.161.115.189]:2222 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBARrpBl177hs/ykMnXHfkjmyKTbsax/vtSl+rInZvJoF8LfJaWCZSrai0uD5qRuYhy4QnJs563NBTmCgSBhm/MA=
ssh user_@10.161.115.189
- connect
dssh user_@10.161.115.189
- not connect
* ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDIXl2FNkUIHkxjfhb5oaonzI1zsXL6rUW9mrFXcJ5xP
@revoked 10.161.115.143 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDIXl2FNkUIHkxjfhb5oaonzI1zsXL6rUW9mrFXcJ5xP
ssh -p 12 koka@10.161.115.143
- connect
dssh -p 12 koka@10.161.115.143
- not connect
Does this only come up if the same key is both used as @revoked as well as a normal non-revoked knownhosts line? (That situation seems incredibly rare in the real world I'd think?)
I agree. I just tried to find possible problems from a different implementation of wildcards
Does this reproduce when using x/crypto/ssh/knownhosts instead of skeema/knownhosts?
Yes. This is the behavior of x/crypto/ssh/knownhosts - skeema/knownhosts just inherited it. Maybe you can fix it?
When you say "then OpenSSH and golang react the same way" at the end, what specifically do they do?
Both not connected
* ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDIXl2FNkUIHkxjfhb5oaonzI1zsXL6rUW9mrFXcJ5xP
@revoked [10.161.115.143]:12 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDIXl2FNkUIHkxjfhb5oaonzI1zsXL6rUW9mrFXcJ5xP
ssh -p 12 koka@10.161.115.143
- not connect
dssh -p 12 koka@10.161.115.143
- not connect
It looks like x/crypto/ssh/knownhosts treats @revoked
keys as applying to all hosts. The host pattern on the same line is ignored. It just tracks a map of revoked keys keyed only by a serialized string version of the host public key:
db.revoked[string(key.Marshal())] = &KnownKey{
Key: key,
Filename: filename,
Line: linenum,
}
and then during the callback check, it first sees if the key is known to be revoked, without even looking at the host at all:
if revoked := db.revoked[string(remoteKey.Marshal())]; revoked != nil {
return &RevokedError{Revoked: *revoked}
}
In contrast I assume OpenSSH is actually looking at the host pattern, and only applying @revoked
to that specific pattern.
Honestly, x/crypto/ssh/knownhosts's behavior here makes more sense to me than OpenSSH's. The purpose of @revoked
is to mark a host public key as unusable because the corresponding private key has been leaked/compromised. In that situation, you would presumably want to ban the key in general, regardless of what host is using it.
In any case, sorry but I don't think there is any way to adjust this behavior here in skeema/knownhosts. We rely on x/crypto/ssh/knownhosts for the core logic, and x/crypto/ssh/knownhosts will always return a RevokedError for any revoked key regardless of the host field. We could intercept that error in a wrapped callback, but then there's no way to re-do the key check in a way that then ignores a particular @revoked
line.
OpenSSH and golang understand known_hosts differently if it has marker
@revoked
known_hosts:config:
OpenSSH
ssh 12
:golang
dssh 12
:If known_hosts:
then OpenSSH and golang react the same way.