about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMarc Cornellà <hello@mcornella.com>2022-01-24 09:43:28 +0100
committerdana <dana@dana.is>2022-02-12 07:21:28 -0600
commitfdb8b0ce6244ff26bf55e0fd825310a58d0d3156 (patch)
tree50f51101ff49b32fa158d5d8e1fbd222993b2ae4
parentc187154f47697cdbf822c2f9d714d570ed4a0fd1 (diff)
downloadzsh-fdb8b0ce6244ff26bf55e0fd825310a58d0d3156.tar.gz
zsh-fdb8b0ce6244ff26bf55e0fd825310a58d0d3156.tar.xz
zsh-fdb8b0ce6244ff26bf55e0fd825310a58d0d3156.zip
security/89: Add patch which can optionally be used to work around CVE-2021-45444 in VCS_Info
-rw-r--r--ChangeLog5
-rw-r--r--Etc/CVE-2021-45444-VCS_Info-workaround.patch98
2 files changed, 103 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index eb248ec06..678d46fca 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2022-01-27  dana  <dana@dana.is>
 
+	* Marc Cornellà: security/89:
+	Etc/CVE-2021-45444-VCS_Info-workaround.patch: Add patch which
+	can optionally be used to work around recursive PROMPT_SUBST
+	issue in VCS_Info
+
 	* Oliver Kiddle: security/41: Src/prompt.c: Prevent recursive
 	PROMPT_SUBST
 
diff --git a/Etc/CVE-2021-45444-VCS_Info-workaround.patch b/Etc/CVE-2021-45444-VCS_Info-workaround.patch
new file mode 100644
index 000000000..13e54be77
--- /dev/null
+++ b/Etc/CVE-2021-45444-VCS_Info-workaround.patch
@@ -0,0 +1,98 @@
+From 972887bbe5eb6a00e5f0e73781d6d73bfdcafb93 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc=20Cornell=C3=A0?= <hello@mcornella.com>
+Date: Mon, 24 Jan 2022 09:43:28 +0100
+Subject: [PATCH] security/89: Partially work around CVE-2021-45444 in VCS_Info
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This patch is a partial, VCS_Info-specific work-around for CVE-2021-45444,
+which is mitigated in the shell itself in 5.8.1 and later versions. It is
+offered for users who are concerned about an exploit but are unable to update
+their binaries to receive the complete fix.
+
+The patch works around the vulnerability by pre-escaping values substituted
+into format strings in VCS_Info. Please note that this may break some user
+configurations that rely on those values being un-escaped (which is why it was
+not included directly in 5.8.1). It may be possible to limit this breakage by
+adjusting exactly which ones are pre-escaped, but of course this may leave
+them vulnerable again.
+
+If applying the patch to the file system is inconvenient or not possible, the
+following script can be used to idempotently patch the relevant function
+running in memory (and thus must be re-run when the shell is restarted):
+
+
+# Impacted versions go from v5.0.3 to v5.8 (v5.8.1 is the first patched version)
+autoload -Uz is-at-least
+if is-at-least 5.8.1 || ! is-at-least 5.0.3; then
+  return
+fi
+
+# Quote necessary $hook_com[<field>] items just before they are used
+# in the line "VCS_INFO_hook 'post-backend'" of the VCS_INFO_formats
+# function, where <field> is:
+#
+#   base:       the full path of the repository's root directory.
+#   base-name:  the name of the repository's root directory.
+#   branch:     the name of the currently checked out branch.
+#   revision:   an identifier of the currently checked out revision.
+#   subdir:     the path of the current directory relative to the
+#               repository's root directory.
+#   misc:       a string that may contain anything the vcs_info backend wants.
+#
+# This patch %-quotes these fields previous to their use in vcs_info hooks and
+# the zformat call and, eventually, when they get expanded in the prompt.
+# It's important to quote these here, and not later after hooks have modified the
+# fields, because then we could be quoting % characters from valid prompt sequences,
+# like %F{color}, %B, etc.
+#
+#  32   │ hook_com[subdir]="$(VCS_INFO_reposub ${hook_com[base]})"
+#  33   │ hook_com[subdir_orig]="${hook_com[subdir]}"
+#  34   │
+#  35 + │ for tmp in base base-name branch misc revision subdir; do
+#  36 + │     hook_com[$tmp]="${hook_com[$tmp]//\%/%%}"
+#  37 + │ done
+#  38 + │
+#  39   │ VCS_INFO_hook 'post-backend'
+#
+# This is especially important so that no command substitution is performed
+# due to malicious input as a consequence of CVE-2021-45444, which affects
+# zsh versions from 5.0.3 to 5.8.
+#
+autoload -Uz +X regexp-replace VCS_INFO_formats
+
+# We use $tmp here because it's already a local variable in VCS_INFO_formats
+typeset PATCH='for tmp (base base-name branch misc revision subdir) hook_com[$tmp]="${hook_com[$tmp]//\%/%%}"'
+# Unique string to avoid reapplying the patch if this code gets called twice
+typeset PATCH_ID=vcs_info-patch-9b9840f2-91e5-4471-af84-9e9a0dc68c1b
+# Only patch the VCS_INFO_formats function if not already patched
+if [[ "$functions[VCS_INFO_formats]" != *$PATCH_ID* ]]; then
+  regexp-replace 'functions[VCS_INFO_formats]' \
+    "VCS_INFO_hook 'post-backend'" \
+    ': ${PATCH_ID}; ${PATCH}; ${MATCH}'
+fi
+unset PATCH PATCH_ID
+
+
+---
+ Functions/VCS_Info/VCS_INFO_formats | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/Functions/VCS_Info/VCS_INFO_formats b/Functions/VCS_Info/VCS_INFO_formats
+index e0e1dc738..4d88e28b6 100644
+--- a/Functions/VCS_Info/VCS_INFO_formats
++++ b/Functions/VCS_Info/VCS_INFO_formats
+@@ -32,6 +32,10 @@ hook_com[base-name_orig]="${hook_com[base_name]}"
+ hook_com[subdir]="$(VCS_INFO_reposub ${hook_com[base]})"
+ hook_com[subdir_orig]="${hook_com[subdir]}"
+ 
++for tmp in base base-name branch misc revision subdir; do
++    hook_com[$tmp]="${hook_com[$tmp]//\%/%%}"
++done
++
+ VCS_INFO_hook 'post-backend'
+ 
+ ## description (for backend authors):
+-- 
+2.34.1