ssh/tailssh: reject dangerous LD_/DYLD_ env vars in acceptEnv filtering (#19914)
Block dynamic linker environment variables (LD_PRELOAD, LD_LIBRARY_PATH, DYLD_INSERT_LIBRARIES, and friends) from being forwarded regardless of acceptEnv policy, preventing privilege escalation via wildcard patterns like "*". We are not aware of any legitimate use of these variables so they are safe to exclude from being passed. Thanks to Tim Sageser (dtrsecurity) for this report. Updates tailscale/corp#42033 Signed-off-by: Patrick O'Doherty <patrick@tailscale.com>
This commit is contained in:
@@ -9,6 +9,17 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// isDangerousEnvVar reports whether the given environment variable name
|
||||
// is unconditionally prohibited from being forwarded, regardless of
|
||||
// acceptEnv policy. This prevents privilege escalation via dynamic
|
||||
// linker environment variables (e.g. LD_PRELOAD, LD_LIBRARY_PATH,
|
||||
// DYLD_INSERT_LIBRARIES) even when a wildcard acceptEnv pattern like
|
||||
// "*" is configured.
|
||||
func isDangerousEnvVar(name string) bool {
|
||||
upper := strings.ToUpper(name)
|
||||
return strings.HasPrefix(upper, "LD_") || strings.HasPrefix(upper, "DYLD_")
|
||||
}
|
||||
|
||||
// filterEnv filters a passed in environ string slice (a slice with strings
|
||||
// representing environment variables in the form "key=value") based on
|
||||
// the supplied slice of acceptEnv values.
|
||||
@@ -18,6 +29,10 @@ import (
|
||||
//
|
||||
// acceptEnv values may contain * and ? wildcard characters which match against
|
||||
// zero or one or more characters and a single character respectively.
|
||||
//
|
||||
// Certain dangerous environment variables (such as those controlling the
|
||||
// dynamic linker) are always rejected regardless of the acceptEnv policy.
|
||||
// See isDangerousEnvVar.
|
||||
func filterEnv(acceptEnv []string, environ []string) ([]string, error) {
|
||||
var acceptedPairs []string
|
||||
|
||||
@@ -32,6 +47,12 @@ func filterEnv(acceptEnv []string, environ []string) ([]string, error) {
|
||||
return nil, fmt.Errorf(`invalid environment variable: %q. Variables must be in "KEY=VALUE" format`, envPair)
|
||||
}
|
||||
|
||||
// Always reject dangerous environment variables that could
|
||||
// enable privilege escalation, regardless of acceptEnv policy.
|
||||
if isDangerousEnvVar(variableName) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Short circuit if we have a direct match between the environment
|
||||
// variable and an AcceptEnv value.
|
||||
if slices.Contains(acceptEnv, variableName) {
|
||||
|
||||
Reference in New Issue
Block a user