mirror of
https://github.com/juanfont/headscale.git
synced 2024-11-30 13:35:23 +00:00
Merge pull request #823 from kradalby/sanitise-machine-key-url
Protect against user injection for registration CLI page
This commit is contained in:
commit
d575dac73a
@ -15,6 +15,7 @@
|
|||||||
- Give a warning when running Headscale with reverse proxy improperly configured for WebSockets [#788](https://github.com/juanfont/headscale/pull/788)
|
- Give a warning when running Headscale with reverse proxy improperly configured for WebSockets [#788](https://github.com/juanfont/headscale/pull/788)
|
||||||
- Fix subnet routers with Primary Routes [#811](https://github.com/juanfont/headscale/pull/811)
|
- Fix subnet routers with Primary Routes [#811](https://github.com/juanfont/headscale/pull/811)
|
||||||
- Added support for JSON logs [#653](https://github.com/juanfont/headscale/issues/653)
|
- Added support for JSON logs [#653](https://github.com/juanfont/headscale/issues/653)
|
||||||
|
- Sanitise the node key passed to registration url [#823](https://github.com/juanfont/headscale/pull/823)
|
||||||
- Add support for generating pre-auth keys with tags [#767](https://github.com/juanfont/headscale/pull/767)
|
- Add support for generating pre-auth keys with tags [#767](https://github.com/juanfont/headscale/pull/767)
|
||||||
- Add support for evaluating `autoApprovers` ACL entries when a machine is registered [#763](https://github.com/juanfont/headscale/pull/763)
|
- Add support for evaluating `autoApprovers` ACL entries when a machine is registered [#763](https://github.com/juanfont/headscale/pull/763)
|
||||||
- Add config flag to allow Headscale to start if OIDC provider is down [#829](https://github.com/juanfont/headscale/pull/829)
|
- Add config flag to allow Headscale to start if OIDC provider is down [#829](https://github.com/juanfont/headscale/pull/829)
|
||||||
|
32
api.go
32
api.go
@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
"tailscale.com/types/key"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -93,7 +94,34 @@ func (h *Headscale) RegisterWebAPI(
|
|||||||
) {
|
) {
|
||||||
vars := mux.Vars(req)
|
vars := mux.Vars(req)
|
||||||
nodeKeyStr, ok := vars["nkey"]
|
nodeKeyStr, ok := vars["nkey"]
|
||||||
if !ok || nodeKeyStr == "" {
|
|
||||||
|
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.
|
||||||
|
var nodeKey key.NodePublic
|
||||||
|
err := nodeKey.UnmarshalText(
|
||||||
|
[]byte(NodePublicKeyEnsurePrefix(nodeKeyStr)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if !ok || nodeKeyStr == "" || err != nil {
|
||||||
|
log.Warn().Err(err).Msg("Failed to parse incoming nodekey")
|
||||||
|
|
||||||
writer.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
writer.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
writer.WriteHeader(http.StatusBadRequest)
|
writer.WriteHeader(http.StatusBadRequest)
|
||||||
_, err := writer.Write([]byte("Wrong params"))
|
_, err := writer.Write([]byte("Wrong params"))
|
||||||
@ -130,7 +158,7 @@ func (h *Headscale) RegisterWebAPI(
|
|||||||
|
|
||||||
writer.Header().Set("Content-Type", "text/html; charset=utf-8")
|
writer.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
writer.WriteHeader(http.StatusOK)
|
writer.WriteHeader(http.StatusOK)
|
||||||
_, err := writer.Write(content.Bytes())
|
_, err = writer.Write(content.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().
|
log.Error().
|
||||||
Caller().
|
Caller().
|
||||||
|
7
utils.go
7
utils.go
@ -17,6 +17,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -64,6 +65,8 @@ const (
|
|||||||
ZstdCompression = "zstd"
|
ZstdCompression = "zstd"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var NodePublicKeyRegex = regexp.MustCompile("nodekey:[a-fA-F0-9]+")
|
||||||
|
|
||||||
func MachinePublicKeyStripPrefix(machineKey key.MachinePublic) string {
|
func MachinePublicKeyStripPrefix(machineKey key.MachinePublic) string {
|
||||||
return strings.TrimPrefix(machineKey.String(), machinePublicHexPrefix)
|
return strings.TrimPrefix(machineKey.String(), machinePublicHexPrefix)
|
||||||
}
|
}
|
||||||
@ -325,7 +328,9 @@ func GenerateRandomStringDNSSafe(size int) (string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
str = strings.ToLower(strings.ReplaceAll(strings.ReplaceAll(str, "_", ""), "-", ""))
|
str = strings.ToLower(
|
||||||
|
strings.ReplaceAll(strings.ReplaceAll(str, "_", ""), "-", ""),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return str[:size], nil
|
return str[:size], nil
|
||||||
|
Loading…
Reference in New Issue
Block a user