Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Security issue in Zsh restricted mode (zsh -r) – escape via history built‑ins



cyber security wrote:
> I am reporting a security issue in Zsh restricted mode (`zsh -r`).

Do you actually make use of the restricted mode feature (either of
bash or zsh)? It is hard to secure it properly unless you have a good
knowledge of all shell features. Only a very limited range of commands
can be made available and write permissions should be withheld from just
about everything. Shell builtins should be liberally disabled, probably
including fc. Unfortunately, there is no good documentation or guide on
how to do this, probably in large part because nobody uses the feature.
I've never seen it deployed.

I actually had an item noted in my list of zsh related tasks to check
whether sysopen in the zsh/system module should honour RESTRICTED along
with checking other file writes. The patch below does block this along
with fc -W or -A when a filename is specified.

Digging further, it is all too easy to find things that potentially
should be blocked.

Just checking for writes, zcompile does writing. Trying, e.g.
  zcompile $ZDOTDIR/.zshrc =(echo echo bad)
Will write a .zwc file but it doesn't get used because the original
filename is stored and doesn't match. Which leads me to wonder if
TMPPREFIX (and TMPSUFFIX?) should be marked as RESTRICTED? They are set
with setsparam() so adding flags isn't trivial. An administrator marking
them readonly may not be sufficient as that can be overriden with a
local in a function.

Should we even be caring about RESTRICTED in loadable modules? zsh/files
would also be dangerous. Perhaps we should just advise administrators to
disable zmodload (and enable of course).

> Mitigation:
> Administrators should disable or restrict the use of `history -w` and
> `history -a` in restricted environments, ensure $HOME is unwritable,
> and harden startup file permissions. Symlinks into writable
> directories should also be removed.

Your mitigation is nothing new. All of that would have been a normal
part of deploying a restricted shell thirty years ago.

> I am requesting acknowledgment of this issue and guidance on whether a
> patch or configuration hardening will be provided upstream. I am also
> requesting a CVE identifier for tracking.

The only thing a CVE would achieve is wasting a lot of people's time
rushing to patch something that isn't a security concern because they
don't use the restricted feature.

Oliver

diff --git a/Src/Modules/system.c b/Src/Modules/system.c
index f1c0d7042..644fa7f1a 100644
--- a/Src/Modules/system.c
+++ b/Src/Modules/system.c
@@ -336,6 +336,10 @@ bin_sysopen(char *nam, char **args, Options ops, UNUSED(int func))
 	zwarnnam(nam, "file descriptor not specified");
 	return 1;
     }
+    if (write || append) {
+	zwarnnam(nam, "writing not allowed in restricted mode");
+	return 1;
+    }
 
     /* file descriptor, either 0-9 or a variable name */
     fdvar = OPT_ARG(ops, 'u');
diff --git a/Src/builtin.c b/Src/builtin.c
index 49fab93da..b2a2af10d 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -1506,12 +1506,20 @@ bin_fc(char *nam, char **argv, Options ops, int func)
 	return 0;
     }
     if (OPT_ISSET(ops,'W')) {
+	if (*argv && isset(RESTRICTED)) {
+	    zwarnnam(nam, "writing not allowed in restricted mode");
+	    return 1;
+	}
 	/* write history to a file */
 	savehistfile(*argv, 1, OPT_ISSET(ops,'I') ? HFILE_SKIPOLD : 0);
 	unqueue_signals();
 	return 0;
     }
     if (OPT_ISSET(ops,'A')) {
+	if (*argv && isset(RESTRICTED)) {
+	    zwarnnam(nam, "writing not allowed in restricted mode");
+	    return 1;
+	}
 	/* append history to a file */
 	savehistfile(*argv, 1, HFILE_APPEND |
 		     (OPT_ISSET(ops,'I') ? HFILE_SKIPOLD : 0));




Messages sorted by: Reverse Date, Date, Thread, Author