File manager - Edit - /usr/share/cagefs/safeprograms/cagefs.proxy.crontab
Back
#!/bin/bash ##CageFS proxyexec wrapper - ver 18 if [[ $EUID -eq 0 ]]; then echo 'Cannot be run as root' exit 1 fi # POSIX single-quote escaping for values embedded in the ssh remote # command. Unlike `printf %q`, single-quoted output re-parses correctly # under any POSIX shell (the origin login shell need not be bash) and is # lossless for arbitrary bytes. Each embedded ' becomes the '\'' sequence. sq() { local s=${1//\'/\'\\\'\'} printf "'%s'" "$s" } USR=`/usr/bin/whoami` CWD=`pwd` TOKEN=`/bin/cat /var/.cagefs/.cagefs.token` # It's user's tmp directory and write to it is secure procedure # because this script is running only under usual user LOCKFILE=/tmp/.crontab.lock # automatically obtain next available fd # previous strategy with `ulimit -n` failed # in environment where limit is very high (e.g. 1073741816) exec {FD}>$LOCKFILE # Sibling-wrapper hardening of the same command-injection vector named # in cagefs.proxy.program for F-05 / CLOS-4596: caller-controlled $CWD # (`pwd` — attacker controls via mkdir+cd inside the cage) and $USR # are embedded into a command that runs under `eval` (needed for the # `$FD> $LOCKFILE` dynamic-fd redirection). Single-quote each value # with sq() so metacharacters cannot be re-interpreted. The number of # quoting passes must match the number of shell re-parses the value # crosses, which depends on the mode. $TOKEN is a bearer credential and # is intentionally NOT embedded in the shell command line — see F-21 / # CLOS-5408 handling below. if [[ -e /var/.cagefs/origin ]]; then ORIGIN=`/bin/cat /var/.cagefs/origin` # F-45 / CLOS-5432: /var/.cagefs/origin is admin-provisioned under # a root-owned parent, but its contents flow through three local # `eval` re-parses below and ultimately land as ssh(1)'s destination # argv element. CLOS-4596 sq()-hardened USR/CWD/TOKEN in the same # block but overlooked ORIGIN. Any operator/toolchain mishap # (whitespace, `; ...`, backticks, `$(...)`, or a leading # `-oProxyCommand=...`) would either inject a local command via # eval or an ssh option via argv parsing — shell-quoting alone # cannot neutralise a leading `-`. Allow-list to hostname / IPv4 / # IPv6-literal characters and refuse a leading `-`. case "$ORIGIN" in ""|-*|*[!A-Za-z0-9.:-]*) /usr/bin/logger -t cagefs.proxy.crontab \ "refusing to proxy: /var/.cagefs/origin has invalid contents" exit 1 ;; esac # Defense-in-depth: even after content validation, wrap ORIGIN # with sq() so the local eval below cannot word-split on it. # ORIGIN is ssh's destination argv element — the local eval # re-parses the surrounding command string once, but ssh itself # does not hand ORIGIN to the remote shell (that is the remote # command payload's job). One sq() pass is therefore correct here; # a two-pass wrap (like Q_USR / Q_CWD below, which DO reach the # remote shell) would leave literal single quotes in the ssh # destination and break normal name resolution. Q_ORIGIN=$(sq "$ORIGIN") REMOTE="/usr/bin/ssh -F /etc/ssh/cagefs-rexec_config $USR@$Q_ORIGIN" # Distributed mode: the eval'd command is shipped by ssh and the # origin login shell re-parses it, so values cross TWO re-parses # (local eval, then remote shell) — quote twice. Q_USR=$(sq "$(sq "$USR")") Q_CWD=$(sq "$(sq "$CWD")") # F-21 / CLOS-5408: keep the CAGEFS_TOKEN bearer secret out of the # local ssh process's argv (readable via /proc/<ssh-pid>/cmdline # under hidepid<2 or by a same-UID sibling regardless of hidepid). # Ship the token as the first stdin line to ssh; the origin login # shell reads it into CAGEFS_TOKEN via `read` and exports it, then # invokes proxyexec, which authenticates from env as before. `IFS=` # and `-r` protect against leading whitespace / backslash escapes, # and the `&&` operators — quoted here so the local shell passes # them to ssh as literal argv tokens — are re-interpreted as shell # operators by the origin login shell after ssh space-joins argv. STDIN_PREFIX="printf '%s\\n' \"\$TOKEN\";" REMOTE_WRAP_PRE="$REMOTE IFS= read -r CAGEFS_TOKEN '&&' export CAGEFS_TOKEN '&&'" else REMOTE="" # Local mode: the eval'd command runs here with no ssh hop, so values # cross only ONE re-parse (the eval) — quote once. A second pass would # survive the single eval as literal quote characters and corrupt the # arguments proxyexec receives. Q_USR=$(sq "$USR") Q_CWD=$(sq "$CWD") Q_TOKEN=$(sq "$TOKEN") # Local mode is not vulnerable to the F-21 argv-leak — the env # prefix `CAGEFS_TOKEN=…` applies to the immediately-following # proxyexec exec, so the token lives in proxyexec's own environ, # never in any argv on this host. STDIN_PREFIX="" REMOTE_WRAP_PRE="CAGEFS_TOKEN=$Q_TOKEN" fi eval "( /usr/bin/flock -x -w 10 $FD || exit 1 { $STDIN_PREFIX echo -n \"\"; } | $REMOTE_WRAP_PRE /usr/sbin/proxyexec -c cagefs.sock $Q_USR $Q_CWD CRONTAB_CHECK $$ ) $FD> $LOCKFILE" [ $? -ne 0 ] && exit 1 eval "( /usr/bin/flock -x -w 10 $FD || exit 1 { $STDIN_PREFIX echo -n \"\"; } | $REMOTE_WRAP_PRE /usr/sbin/proxyexec -c cagefs.sock $Q_USR $Q_CWD CRONTAB_LIST $$ 2>/dev/null |cat > /var/spool/cron/$USR ) $FD> $LOCKFILE" /usr/bin/crontab.cagefs $@ eval "( /usr/bin/flock -x -w 10 $FD || exit 1 if [ -e /var/spool/cron/$USR ]; then { $STDIN_PREFIX cat /var/spool/cron/$USR; } | $REMOTE_WRAP_PRE /usr/sbin/proxyexec -c cagefs.sock $Q_USR $Q_CWD CRONTAB_SAVE $$ 2>/dev/null else { $STDIN_PREFIX echo -n \"\"; } | $REMOTE_WRAP_PRE /usr/sbin/proxyexec -c cagefs.sock $Q_USR $Q_CWD CRONTAB_SAVE $$ 2>/dev/null fi ) $FD>$LOCKFILE"
| ver. 1.4 |
Github
|
.
| PHP 8.1.34 | Generation time: 0.04 |
proxy
|
phpinfo
|
Settings