diff --git a/api.go b/api.go index 23aa7c5a..4c3a6ca8 100644 --- a/api.go +++ b/api.go @@ -95,6 +95,22 @@ func (h *Headscale) RegisterWebAPI( vars := mux.Vars(req) nodeKeyStr, ok := vars["nkey"] + if !NodePublicKeyRegex.Match([]byte(nodeKeyStr)) { + log.Warn().Str("node_key", nodeKeyStr).Msg("Invalid node key passed to registration url") + + writer.Header().Set("Content-Type", "text/plain; charset=utf-8") + writer.WriteHeader(http.StatusUnauthorized) + _, err := writer.Write([]byte("Unauthorized")) + if err != nil { + log.Error(). + Caller(). + Err(err). + Msg("Failed to write response") + } + + return + } + // We need to make sure we dont open for XSS style injections, if the parameter that // is passed as a key is not parsable/validated as a NodePublic key, then fail to render // the template and log an error. diff --git a/utils.go b/utils.go index 666683cf..7ef054de 100644 --- a/utils.go +++ b/utils.go @@ -17,6 +17,7 @@ import ( "os" "path/filepath" "reflect" + "regexp" "strconv" "strings" @@ -64,6 +65,8 @@ const ( ZstdCompression = "zstd" ) +var NodePublicKeyRegex = regexp.MustCompile("nodekey:[a-fA-F0-9]+") + func MachinePublicKeyStripPrefix(machineKey key.MachinePublic) string { return strings.TrimPrefix(machineKey.String(), machinePublicHexPrefix) }