mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2026-06-19 07:36:59 +00:00
fix(host): verify fingerprint and use distinct error for key parsing
- Adds ErrPublicKeyParse (510010) so TrustHostKey returns a semantically correct error instead of reusing ErrHostKeyMismatch's expected/got template. - The TrustHostKey HTTP handler now recomputes the SHA256 fingerprint of the submitted public key and rejects requests where the client-confirmed fingerprint does not match. Closes a security gap where a tampered request body could install an unverified key in known_hosts.
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/uozi-tech/cosy"
|
||||
gossh "golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// Preview renders all snippets from the posted SetupParams (or current
|
||||
@@ -103,11 +104,32 @@ type knownHostRequest struct {
|
||||
}
|
||||
|
||||
// TrustHostKey appends a known_hosts entry after the user confirms a fingerprint.
|
||||
// It recomputes the SHA256 fingerprint of the submitted public key and rejects
|
||||
// requests where the client-provided fingerprint does not match.
|
||||
func TrustHostKey(c *gin.Context) {
|
||||
var req knownHostRequest
|
||||
if !cosy.BindAndValid(c, &req) {
|
||||
return
|
||||
}
|
||||
|
||||
// Parse the public key so we can recompute its fingerprint and reject
|
||||
// requests where the client-provided fingerprint disagrees with the key.
|
||||
parsed, _, _, _, err := gossh.ParseAuthorizedKey([]byte(req.PublicKey))
|
||||
if err != nil {
|
||||
cosy.ErrHandler(c, cosy.WrapErrorWithParams(hostssh.ErrPublicKeyParse, err.Error()))
|
||||
return
|
||||
}
|
||||
actual := gossh.FingerprintSHA256(parsed)
|
||||
// Require an exact match of the SHA256: form we computed.
|
||||
if req.Fingerprint != actual {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": "fingerprint mismatch",
|
||||
"expected": actual,
|
||||
"got": req.Fingerprint,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
path := settings.NginxSettings.HostKnownHostsPath
|
||||
if path == "" {
|
||||
path = "/etc/nginx-ui/known_hosts"
|
||||
|
||||
@@ -14,4 +14,5 @@ var (
|
||||
ErrSessionFailed = e.New(510007, "failed to open ssh session: {0}")
|
||||
ErrKnownHostsRead = e.New(510008, "failed to read known_hosts: {0}")
|
||||
ErrKnownHostsWrite = e.New(510009, "failed to write known_hosts: {0}")
|
||||
ErrPublicKeyParse = e.New(510010, "failed to parse public key: {0}")
|
||||
)
|
||||
|
||||
@@ -14,7 +14,7 @@ func TrustHostKey(path, hostPort, publicKeyOpenSSH string) error {
|
||||
}
|
||||
parsed, _, _, _, err := gossh.ParseAuthorizedKey([]byte(publicKeyOpenSSH))
|
||||
if err != nil {
|
||||
return cosy.WrapErrorWithParams(ErrHostKeyMismatch, "parse public key", err.Error())
|
||||
return cosy.WrapErrorWithParams(ErrPublicKeyParse, err.Error())
|
||||
}
|
||||
return kh.Trust(hostPort, parsed)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user