2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-22 09:57:41 +00:00

Sanity check the TZ environment variable by special casing it in

env_check.  The --with-tzdir configure option can be used to
specify the zoneinfo directory if configure doesn't find it.
This commit is contained in:
Todd C. Miller 2015-02-06 11:01:05 -07:00
parent de11816198
commit c3c28773f5
10 changed files with 224 additions and 21 deletions

10
INSTALL
View File

@ -145,6 +145,16 @@ Directory and file names:
/var/db, /var/lib, /var/adm, /usr/adm
This directory should not be cleared when the system boots.
--with-tzdir=DIR
Set the directory to the system's time zone data files. This
is only used when sanitizing the TZ environment variable to
allow for fully-qualified paths in TZ.
By default, configure will look for an existing "zoneinfo"
directory in the following locations:
/usr/share /usr/share/lib /usr/lib /etc
If no zoneinfo directory is found, the TZ variable may not
contain a fully-qualified path.
Compilation options:
--disable-hardening
Disable the use of compiler/linker exploit mitigation options

3
NEWS
View File

@ -69,6 +69,9 @@ What's new in Sudo 1.8.12
* Fixed two potential crashes when sudo is run with very low
resource limits.
* The TZ environment variable is now checked for safety instead
of simply being copied to the environment of the command.
What's new in Sudo 1.8.11p2
* Fixed a bug where dynamic shared objects loaded from a plugin

33
configure vendored
View File

@ -889,6 +889,7 @@ with_timedir
with_rundir
with_vardir
with_iologdir
with_tzdir
with_sendmail
with_sudoers_mode
with_sudoers_uid
@ -1686,6 +1687,7 @@ Optional Packages:
--with-rundir=DIR path to the sudo time stamp parent dir
--with-vardir=DIR path to the sudo var dir
--with-iologdir=DIR directory to store sudo I/O log files in
--with-tzdir=DIR path to the time zone data directory
--with-sendmail set path to sendmail
--without-sendmail do not send mail at all
--with-sudoers-mode mode of sudoers file (defaults to 0440)
@ -4828,6 +4830,16 @@ fi
# Check whether --with-tzdir was given.
if test "${with_tzdir+set}" = set; then :
withval=$with_tzdir; case $with_tzdir in
yes) as_fn_error $? "\"must give --with-tzdir an argument.\"" "$LINENO" 5
;;
esac
fi
# Check whether --with-sendmail was given.
if test "${with_sendmail+set}" = set; then :
withval=$with_sendmail; case $with_sendmail in
@ -23367,6 +23379,27 @@ EOF
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $iolog_dir" >&5
$as_echo "$iolog_dir" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking time zone data directory" >&5
$as_echo_n "checking time zone data directory... " >&6; }
tzdir="$with_tzdir"
if test -z "$tzdir"; then
tzdir=no
for d in /usr/share /usr/share/lib /usr/lib /etc; do
if test -d "$d/zoneinfo"; then
tzdir="$d/zoneinfo"
break
fi
done
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tzdir" >&5
$as_echo "$tzdir" >&6; }
if test "${tzdir}" != "no"; then
cat >>confdefs.h <<EOF
#define _PATH_ZONEINFO "$tzdir"
EOF
fi
ac_c_werror_flag=yes

View File

@ -828,6 +828,12 @@ AC_ARG_WITH(iologdir, [AS_HELP_STRING([--with-iologdir=DIR], [directory to store
;;
esac])
AC_ARG_WITH(tzdir, [AS_HELP_STRING([--with-tzdir=DIR], [path to the time zone data directory])],
[case $with_tzdir in
yes) AC_MSG_ERROR(["must give --with-tzdir an argument."])
;;
esac])
AC_ARG_WITH(sendmail, [AS_HELP_STRING([--with-sendmail], [set path to sendmail])
AS_HELP_STRING([--without-sendmail], [do not send mail at all])],
[case $with_sendmail in
@ -3757,6 +3763,7 @@ SUDO_LOGFILE
SUDO_RUNDIR
SUDO_VARDIR
SUDO_IO_LOGDIR
SUDO_TZDIR
dnl
dnl Turn warnings into errors.

View File

@ -1662,19 +1662,35 @@ SSUUDDOOEERRSS OOPPTTIIOONNSS
LLiissttss tthhaatt ccaann bbee uusseedd iinn aa bboooolleeaann ccoonntteexxtt:
env_check Environment variables to be removed from the user's
environment if the variable's value contains `%' or `/'
environment if unless they are considered ``safe''.
For all variables except TZ, ``safe'' means that the
variable's value does not contain any `%' or `/'
characters. This can be used to guard against printf-
style format vulnerabilities in poorly-written
programs. The argument may be a double-quoted, space-
separated list or a single value without double-quotes.
The list can be replaced, added to, deleted from, or
disabled by using the =, +=, -=, and ! operators
respectively. Regardless of whether the env_reset
option is enabled or disabled, variables specified by
env_check will be preserved in the environment if they
pass the aforementioned check. The default list of
environment variables to check is displayed when ssuuddoo
is run by root with the --VV option.
programs. The TZ variable is considerd unsafe if any
of the following are true:
++oo It consists of a fully-qualified path name that
does not match the location of the _z_o_n_e_i_n_f_o
directory.
++oo It contains a _._. path element.
++oo It contains white space or non-printable
characters.
++oo It is longer than the value of PATH_MAX.
The argument may be a double-quoted, space-separated
list or a single value without double-quotes. The list
can be replaced, added to, deleted from, or disabled by
using the =, +=, -=, and ! operators respectively.
Regardless of whether the env_reset option is enabled
or disabled, variables specified by env_check will be
preserved in the environment if they pass the
aforementioned check. The default list of environment
variables to check is displayed when ssuuddoo is run by
root with the --VV option.
env_delete Environment variables to be removed from the user's
environment when the _e_n_v___r_e_s_e_t option is not in effect.
@ -2363,4 +2379,4 @@ DDIISSCCLLAAIIMMEERR
file distributed with ssuuddoo or http://www.sudo.ws/license.html for
complete details.
Sudo 1.8.12 January 21, 2015 Sudo 1.8.12
Sudo 1.8.12 February 6, 2015 Sudo 1.8.12

View File

@ -21,7 +21,7 @@
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
.\"
.TH "SUDOERS" "5" "January 21, 2015" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.TH "SUDOERS" "5" "February 6, 2015" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.nh
.if n .ad l
.SH "NAME"
@ -3415,13 +3415,44 @@ The default value is
.TP 18n
env_check
Environment variables to be removed from the user's environment if
the variable's value contains
unless they are considered
\(lqsafe\(rq.
For all variables except
\fRTZ\fR,
\(lqsafe\(rq
means that the variable's value does not contain any
\(oq%\(cq
or
\(oq/\(cq
characters.
This can be used to guard against printf-style format vulnerabilities
in poorly-written programs.
The
\fRTZ\fR
variable is considerd unsafe if any of the following are true:
.PP
.RS 18n
.PD 0
.TP 4n
\fB\(bu\fR
It consists of a fully-qualified path name that does not match
the location of the
\fIzoneinfo\fR
directory.
.PD
.TP 4n
\fB\(bu\fR
It contains a
\fI..\fR
path element.
.TP 4n
\fB\(bu\fR
It contains white space or non-printable characters.
.TP 4n
\fB\(bu\fR
It is longer than the value of
\fRPATH_MAX\fR.
.PP
The argument may be a double-quoted, space-separated list or a
single value without double-quotes.
The list can be replaced, added to, deleted from, or disabled by using
@ -3443,6 +3474,7 @@ is run by root with
the
\fB\-V\fR
option.
.RE
.TP 18n
env_delete
Environment variables to be removed from the user's environment when the

View File

@ -19,7 +19,7 @@
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
.\"
.Dd January 21, 2015
.Dd February 6, 2015
.Dt SUDOERS @mansectform@
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
@ -3171,13 +3171,38 @@ The default value is
.Bl -tag -width 16n
.It env_check
Environment variables to be removed from the user's environment if
the variable's value contains
unless they are considered
.Dq safe .
For all variables except
.Li TZ ,
.Dq safe
means that the variable's value does not contain any
.Ql %
or
.Ql /
characters.
This can be used to guard against printf-style format vulnerabilities
in poorly-written programs.
The
.Li TZ
variable is considerd unsafe if any of the following are true:
.Bl -bullet
.It
It consists of a fully-qualified path name that does not match
the location of the
.Pa zoneinfo
directory.
.It
It contains a
.Pa ..
path element.
.It
It contains white space or non-printable characters.
.It
It is longer than the value of
.Li PATH_MAX .
.El
.Pp
The argument may be a double-quoted, space-separated list or a
single value without double-quotes.
The list can be replaced, added to, deleted from, or disabled by using

View File

@ -1,6 +1,6 @@
dnl Local m4 macros for autoconf (used by sudo)
dnl
dnl Copyright (c) 1994-1996, 1998-2005, 2007-2014
dnl Copyright (c) 1994-1996, 1998-2005, 2007-2015
dnl Todd C. Miller <Todd.Miller@courtesan.com>
dnl
dnl XXX - should cache values in all cases!!!
@ -82,6 +82,26 @@ else
fi
])dnl
dnl
dnl Detect time zone file directory, if any.
dnl
AC_DEFUN([SUDO_TZDIR], [AC_MSG_CHECKING(time zone data directory)
tzdir="$with_tzdir"
if test -z "$tzdir"; then
tzdir=no
for d in /usr/share /usr/share/lib /usr/lib /etc; do
if test -d "$d/zoneinfo"; then
tzdir="$d/zoneinfo"
break
fi
done
fi
AC_MSG_RESULT([$tzdir])
if test "${tzdir}" != "no"; then
SUDO_DEFINE_UNQUOTED(_PATH_ZONEINFO, "$tzdir")
fi
])dnl
dnl
dnl Parent directory for time stamp dir.
dnl

View File

@ -179,6 +179,10 @@
# undef _PATH_NETSVC_CONF
#endif /* _PATH_NETSVC_CONF */
#ifndef _PATH_ZONEINFO
# undef _PATH_ZONEINFO
#endif /* _PATH_ZONEINFO */
/* On AIX, _PATH_BSHELL in paths.h is /usr/bin/bsh but we want /usr/bin/sh */
#ifndef _PATH_SUDO_BSHELL
# if defined(_AIX) && defined(HAVE_PATHS_H)

View File

@ -187,6 +187,7 @@ static const char *initial_checkenv_table[] = {
"LC_*",
"LINGUAS",
"TERM",
"TZ",
NULL
};
@ -202,7 +203,6 @@ static const char *initial_keepenv_table[] = {
"PATH",
"PS1",
"PS2",
"TZ",
"XAUTHORITY",
"XAUTHORIZATION",
NULL
@ -587,6 +587,54 @@ matches_env_delete(const char *var)
debug_return_bool(matches_env_list(var, &def_env_delete, &full_match));
}
/*
* Sanity-check the TZ environment variable.
* On many systems it is possible to set this to a pathname.
*/
static bool
tz_is_sane(const char *tzval)
{
const char *cp;
char lastch;
debug_decl(tz_is_sane, SUDOERS_DEBUG_ENV)
/* tzcode treats a value beginning with a ':' as a path. */
if (tzval[0] == ':')
tzval++;
/* Reject fully-qualified TZ that doesn't being with the zoneinfo dir. */
if (tzval[0] == '/') {
#ifdef _PATH_ZONEINFO
if (strncmp(tzval, _PATH_ZONEINFO, sizeof(_PATH_ZONEINFO) - 1) != 0 ||
tzval[sizeof(_PATH_ZONEINFO) - 1] != '/')
debug_return_bool(false);
#else
/* Assume the worst. */
debug_return_bool(false);
#endif
}
/*
* Make sure TZ only contains printable non-space characters
* and does not contain a '..' path element.
*/
lastch = '/';
for (cp = tzval; *cp != '\0'; cp++) {
if (isspace((unsigned char)*cp) || !isprint((unsigned char)*cp))
debug_return_bool(false);
if (lastch == '/' && cp[0] == '.' && cp[1] == '.' &&
(cp[2] == '/' || cp[2] == '\0'))
debug_return_bool(false);
lastch = *cp;
}
/* Reject extra long TZ values (even if not a path). */
if ((size_t)(cp - tzval) >= PATH_MAX)
debug_return_bool(false);
debug_return_bool(true);
}
/*
* Apply the env_check list.
* Returns true if the variable is allowed, false if denied
@ -600,10 +648,15 @@ matches_env_check(const char *var, bool *full_match)
/* Skip anything listed in env_check that includes '/' or '%'. */
if (matches_env_list(var, &def_env_check, full_match)) {
if (strncmp(var, "TZ=", 3) == 0) {
/* Special case for TZ */
keepit = tz_is_sane(var + 3);
} else {
const char *val = strchr(var, '=');
if (val != NULL)
keepit = !strpbrk(++val, "/%");
}
}
debug_return_bool(keepit);
}