ssh_filter_btrbk.sh: convert to POSIX sh

This commit finishes the work from the previous one and converts
ssh_filter_btrbk.sh to (mostly) pure POSIX Shell Command Language.

Instead of bash’s `=~`-operator for its `[[ … ]]`-compound-command it uses
`grep`.
At the time of writing, bash has at least the `nocasematch`-shell-option which
would have a negatve security impact for this program. While it’s not enabled
per default single users could potentially change that, not realising the
consequences.
Thus, moving away from this may also provide some hardening.

`grep` matches the pattern per line of input, which would allow for attacks by
including a newline in the string to be matched like in:
	SSH_ORIGINAL_COMMAND="cat /proc/self/mountinfo
	evil-command"
A separate check for newlines is done in the basic checks.

It should be noted, that while bash’s `=~`-operator seems to match against the
whole string at once (and not per lines of it), this behaviour seems to be not
documented and is thus possibly not guranteed.

`grep` may return an exit status of `0` when used with its `-q`-option, even
when an errors occurred.
Since this program is intended specifically for security purposes this shall be
avoided, even if such case is unlikely, and therefore its standard output and
standard error are redirected to `/dev/null` instead.

Further, the form:
	local var=""; var="$(...)"
rather than just:
	local var="$(...)"
is used because the latter would not return the exit status of the most recent
pipeline within the command substitution of the assignment, but `0` (if setting
the local attribute succeeded), which would also evade the desired effect of
`set -e`.

Signed-off-by: Christoph Anton Mitterer <mail@christoph.anton.mitterer.name>
improve-ssh_filter_btrbk.sh
Christoph Anton Mitterer 2022-11-21 04:33:10 +01:00 committed by Axel Burri
parent e3b33cc9a3
commit 0eb2cb47f8
1 changed files with 8 additions and 4 deletions

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/bin/sh
set -e
set -u
@ -87,17 +87,21 @@ reject_filtered_cmd()
stream_in_match="(${decompress_match} \| )?(${mbuffer_match} \| )?"
stream_out_match="( \| ${mbuffer_match})?( \| ${compress_match}$)?"
# `grep`s `-q`-option is not used as it may cause an exit status of `0` even
# when an error occurred.
allow_stream_match="^${stream_in_match}${allow_cmd_match}${stream_out_match}"
if [[ $SSH_ORIGINAL_COMMAND =~ $allow_stream_match ]] ; then
if printf '%s' "$SSH_ORIGINAL_COMMAND" | grep -E "$allow_stream_match" >/dev/null 2>/dev/null; then
return 0
fi
exact_cmd_match="^(${allow_exact_list})$";
if [[ $SSH_ORIGINAL_COMMAND =~ $exact_cmd_match ]] ; then
if printf '%s' "$SSH_ORIGINAL_COMMAND" | grep -E "$exact_cmd_match" >/dev/null 2>/dev/null; then
return 0
fi
reject_and_die "disallowed command${restrict_path_list:+ (restrict-path: \"${restrict_path_list//|/\", \"}\")}"
local formatted_restrict_path_list=""; formatted_restrict_path_list="$(printf '%s' "$restrict_path_list" | sed 's/|/", "/g')"
reject_and_die "disallowed command${restrict_path_list:+ (restrict-path: \"$formatted_restrict_path_list\")}"
}