BUG in arithcomp: bypass of the check condition and arbitrary read/write of shell variables

2020-04-10 Thread Raffaele Florio via Bug reports for the GNU Bourne Again SHell
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS: -O2 -g -pipe -Wall -Werror=format-security 
-Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions 
-fstack-protector-strong -grecord-gcc-switches 
-specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 
-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic 
-fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection 
-Wno-parentheses -Wno-format-security
uname output: Linux x230 5.5.10-100.fc30.x86_64 #1 SMP Wed Mar 18 14:34:46 UTC 
2020 x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-redhat-linux-gnu

Bash Version: 5.0
Patch Level: 11
Release Status: release

Description:
A bug in the function arithcomp (in test.c) allows an attacker to bypass every 
arithmetic check. Furthermore, this bug, allows an attacker to read/write 
arbitrary shell variables. The bug could be also triggered with the test 
built-in.
The check bypass and the arbitrary read/write is related to the same logic. 
Precisely by the functions called by arithcomp.
Indeed the functions called by arithcomp cause the evaluation of the supplied 
arithcomp function argument, potentially fed by user input.
The chain of the called functions is: evalexp (defined in expr.c) -> subexpr -> 
readtok + EXP_HIGHEST. In this way every arithmetic/bitwise/logical expressions 
or variable assignment is evaluated.
The cahin is triggered by the L347 or L350:
337 static int
338 arithcomp (s, t, op, flags)
339  char *s, *t;
340  int op, flags;
341 {
...
345   if (flags & TEST_ARITHEXP)
346 {
-> 347   l = evalexp (s, 0, &expok);
348   if (expok == 0)
349 return (FALSE); /* should probably longjmp here */
-> 350   r = evalexp (t, 0, &expok);
351   if (expok == 0)
352 return (FALSE); /* ditto */
353 }
.

I've also tried on MacOS with bash and sh. On Windows it works with git bash. 
Furthermore zsh is also affected. I didn't try other *sh shell.

Repeat-By:
== Arithmetic check bypass ==
Give in input "y" (as string) to the below script and the equality will be 
satisfied. This is caused by the fact that the y given in input is evaluated as 
shell variable by the expression evaluator.
Here the script:
#!/path/to/bash

y=$RANDOM
read input
if [[ "$y" -eq "$input" ]]; then
echo "OK"
fi

= read/write of arbitrary shell variables ==
Give in input "x=42,xyz=UID" to the below script. After the test x will contain 
42 and xyz the UID value. The same logic in this bug. Furthermore if PWD is 
given, instead of UID, the PWD value is printed thanks the evaluation error.
Here the script:
#!/path/to/bash

x="VAL"
y=1234
read input

if [[ "$y" -eq "$input" ]]; then
echo "OK"
fi

echo "x = $x"
echo "xyz = $xyz"

Fix:
A solution could be to use a simpler equality strategy for the arithmetic 
comparison. More or less like the logic of the string comparison implemented in 
the same file (test.c). Basically, the latter, use a strcmp.

Re: BUG in arithcomp: bypass of the check condition and arbitrary read/write of shell variables

2020-04-10 Thread Greg Wooledge
On Fri, Apr 10, 2020 at 09:44:31AM +, Raffaele Florio via Bug reports for 
the GNU Bourne Again SHell wrote:
> Indeed the functions called by arithcomp cause the evaluation of the supplied 
> arithcomp function argument, potentially fed by user input.

> Give in input "x=42,xyz=UID" to the below script. After the test x will 
> contain 42 and xyz the UID value. The same logic in this bug. Furthermore if 
> PWD is given, instead of UID, the PWD value is printed thanks the evaluation 
> error.

Yeah, this is a "well known feature".  Arithmetic expansions of all kinds
in bash are susceptible to arbitrary code execution, if any part of
the arithmetic expansion is fed by unsafe input.

This applies to every single place an arithmetic context can appear,
including the let and (( commands, the $(( expansion, the -eq operator
of the [[ command, indexed array indices, and the numeric parts of
the ${variable:start:length} expansion.  And possibly more.

unicorn:~$ x='a[$(id >&2)0]' a=7
unicorn:~$ [[ "$x" -eq 42 ]]
uid=1000(greg) gid=1000(greg) 
groups=1000(greg),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),108(netdev)
unicorn:~$ echo "${y[x]}"
uid=1000(greg) gid=1000(greg) 
groups=1000(greg),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),108(netdev)

unicorn:~$ echo "${PWD:x}"
uid=1000(greg) gid=1000(greg) 
groups=1000(greg),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),108(netdev)
reg
unicorn:~$ 

To the best of my knowledge, this is not considered a bug in bash,
but rather a bug in your script, if you fail to sanitize user input
before passing it to an arithmetic context.



SEGFAULT ON TILDE EXPANSION

2020-04-10 Thread kutay üner
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS: -O0 -ggdb -Wno-parentheses -Wno-format-security
uname output: Linux hk 5.6.3-arch1-1 #9 SMP PREEMPT Thu, 09 Apr 2020
03:39:30 + x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 5.0
Patch Level: 16
Release Status: release

Description:
Trying to tab expand a tilde causes segfault. This action requires us to
get user entries by calling getpwent which is provided by
libnss_systemd.so
on my system.
If we compile bash with it's malloc implementation, libraries it depends
on also start to use this version of malloc.
getpwent function in libnss_systemd.so takes advantage of the C malloc
returning max_align_t aligned memory. Bash malloc returns 8 byte
aligned
memory which is less than 16 byte requirement on my x86-64 system. This
is the root cause of segfault.

Repeat-By:
$ echo ~u

Fix:
./configure --without-bash-malloc