mirror of
				https://github.com/juanfont/headscale.git
				synced 2025-10-28 10:51:44 +01: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)
 | 
			
		||||
- 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)
 | 
			
		||||
- 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 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)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										32
									
								
								api.go
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								api.go
									
									
									
									
									
								
							@ -9,6 +9,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	"github.com/gorilla/mux"
 | 
			
		||||
	"github.com/rs/zerolog/log"
 | 
			
		||||
	"tailscale.com/types/key"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
@ -93,7 +94,34 @@ func (h *Headscale) RegisterWebAPI(
 | 
			
		||||
) {
 | 
			
		||||
	vars := mux.Vars(req)
 | 
			
		||||
	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.WriteHeader(http.StatusBadRequest)
 | 
			
		||||
		_, 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.WriteHeader(http.StatusOK)
 | 
			
		||||
	_, err := writer.Write(content.Bytes())
 | 
			
		||||
	_, err = writer.Write(content.Bytes())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Error().
 | 
			
		||||
			Caller().
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										7
									
								
								utils.go
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								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)
 | 
			
		||||
}
 | 
			
		||||
@ -325,7 +328,9 @@ func GenerateRandomStringDNSSafe(size int) (string, error) {
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return "", err
 | 
			
		||||
		}
 | 
			
		||||
		str = strings.ToLower(strings.ReplaceAll(strings.ReplaceAll(str, "_", ""), "-", ""))
 | 
			
		||||
		str = strings.ToLower(
 | 
			
		||||
			strings.ReplaceAll(strings.ReplaceAll(str, "_", ""), "-", ""),
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return str[:size], nil
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user