Package: tiger Version: 1:3.2.4~rc1-3.5 Severity: grave Tags: security patch X-Debbugs-Cc: [email protected]
scripts/find_files runs find on each mount point it scans through eval: eval nice -5 $FIND "$mountpt" $findpruneopt $findopt -print 2>/dev/null The double quotes go in the first expansion, so eval parses the mount point's path as shell code. The mount points come from gen_mounts, which keeps those whose type it counts as local, fuse.encfs and fuse.lxcfs among them. fusermount3 is setuid root and lets any user mount a FUSE file system on a directory they own, setting the reported type with -o subtype=, so any local user can make a "local" mount point whose name holds a command substitution. find_files runs that command as root the next time it runs: with the package's cronrc, at 02:00 on the 1st of every month, from the hourly tigercron job in /etc/cron.d/tiger. The precondition is fuse3 (or fuse) being installed. The line is the same in 1:3.2.4~rc1-3.2 (bookworm), -3.4 (trixie) and -3.5 (sid and forky), and in upstream TIGER 3.2.4. Verified in a privileged debian:sid container with 1:3.2.4~rc1-3.5 and Tiger_FSScan_WDIR=Y: with a tmpfs mounted on a directory whose name held a command substitution, find_files ran the command as root. With the attached patch it did not, and both that mount and one on a directory named with an apostrophe, which the eval had silently skipped, were scanned. On Ubuntu 24.04 I confirmed in October that an unprivileged user can make such a mount with fusermount3 -o subtype=encfs, and that mount prints its name unchanged. The patch (DEP-3, against 1:3.2.4~rc1-3.5; it applies unchanged to -3.2 and -3.4) passes the mount points to find as positional parameters, so eval sees only '$FIND "$mountpt"'. The find options, which come from tiger's own configuration, still go through eval. It applies with or without the reworked patch for #610785, in either order. I reported this privately to [email protected] on 11 October and followed up on 22 October, saying I would file it here on 29 October unless asked to wait; there was no reply. Tigris, the fork of TIGER I maintain, fixed it in 3.9.0, and its advisory is public as GHSA-p8g6-qw5j-8cgc, in the creativeheadz/tigris repository on GitHub. A CVE was requested through GitHub for that advisory and has not been assigned yet. The same report named two lower-impact problems, which need a non-default setting or an administrator's mistake: with Tiger_Check_PATHALL=Y (the default is N), check_path sources assignments it extracts from every user's .profile and .cshrc as root, and config reads ./tigerrc, ./.tigerrc and ./site from the directory tiger is started in, checking only that they are not group or world writable, not who owns them. I can file those separately. Andrei Trimbitas
Description: find_files: give find the mount points as arguments, not to eval find_files ran find on each mount point with eval nice -5 $FIND "$mountpt" $findpruneopt $findopt -print The double quotes go in the first expansion, so eval parsed the mount point's path as shell code. gen_mounts keeps the mount points whose type it counts as local, fuse.encfs and fuse.lxcfs among them, and fusermount3 lets any user mount a FUSE file system on a directory they own with the type they choose (-o subtype=encfs). A command substitution in that directory's name ran as root the next time find_files ran: at 02:00 on the 1st of the month with the package's cronrc. . The mount points are now positional parameters, and eval sees only '$FIND "$mountpt"', which it expands without parsing the value. The find options, which come from tiger's own configuration, still go through eval. Author: Andrei Trimbitas <[email protected]> Forwarded: no Last-Update: 2026-10-29 --- diff --git a/scripts/find_files b/scripts/find_files index a07707f..f6e5a96 100755 --- a/scripts/find_files +++ b/scripts/find_files @@ -304,12 +304,18 @@ rw=rw otherfile="${outfile}.other.$counter" # echo "$FIND x $findpruneopt $findopt -print" 1>&2 - for mountpt in $disklist + # The mount points are data: whoever mounted a filesystem named its + # mount point (any user can, with FUSE), so they reach find as + # arguments, never as text for eval to parse. + set -f + set -- $disklist + set +f + for mountpt do # Not sure why we're cd'ing to /, but it breaks all relative paths # being used in the find options. Commented out --mlk # cd / - eval nice -5 $FIND "$mountpt" $findpruneopt $findopt -print 2>/dev/null + eval nice -5 '$FIND "$mountpt"' $findpruneopt $findopt -print 2>/dev/null done | nice -6 $output 2>&1 | sed -e '/No such file/s/^.*:[[:space:]]\(.*\):[[:space:]].*$/\1/' | while read symlink ; do

