Bash is incorrectly and inconsistently expanding tilde in $PATH

2017-05-04 Thread Nikolay Aleksandrovich Pavlov (ZyX)
configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: x86_64-pc-linux-gnu-gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu' 
-DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL 
-DHAVE_CONFIG_H   -I. -I./include -I. -I./include -I./lib  
-DDEFAULT_PATH_VALUE='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
 -DSTANDARD_UTILS_PATH='/bin:/usr/bin:/sbin:/usr/sbin' 
-DSYS_BASHRC='/etc/bash/bashrc' -DSYS_BASH_LOGOUT='/etc/bash/bash_logout' 
-DNON_INTERACTIVE_LOGIN_SHELLS -DSSH_SOURCE_BASHRC -DUSE_MKTEMP -DUSE_MKSTEMP 
-O2 -march=native -mtune=native -pipe
uname output: Linux zyx-desktop 4.10.12-gentoo #1 SMP Tue Apr 25 19:08:41 MSK 
2017 x86_64 AMD FX(tm)-6200 Six-Core Processor AuthenticAMD GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 4.3
Patch Level: 48
Release Status: release

Description:
If $PATH in bash contains ~ (e.g. `PATH='~/bin'`) it is incorrectly 
treated 
as if $HOME is present.

This may even present a small security risk under certain 
circumstances: 
e.g. consider an unexperienced admin which has `PATH="~/bin:$PATH"` in 
his 
bashrc. He received an archive with potentially malicious software and 
wants 
to analyze it. To do this he created a new directory, made it current 
and 
unpacked archive to the place. After that he found that archive 
contains 
executables `~/bin/init.sh` and `~/bin/python3`. So to determine what 
this 
software targets he opens `~/bin/init.sh` like this: `nvim 
\~/bin/init.sh`. 
And whoops, he just has some keylogger running as his user: he has 
https://github.com/Shougo/denite.nvim installed for his nvim so nvim 
needs 
python3 and just executed `./~/bin/python3`, because the only 
application 
which expands `~/` in `$PATH` is bash and Neovim python provider is 
using 
`system([])` form which calls in libuv directly.

Of course, analyzing potential malware not in a VM is unwise and it 
requires 
a combination of factors to make the attack successfull. Specifically 
these 
factors are:

- Admin needs to have `~/bin` in `$PATH` and not `$HOME/bin`, 
preferably at 
  near the start of the `$PATH`.
- Attacker needs to be able to somehow put an executable to `./~/bin/…`.
- Attacker needs to make admin run something not with bash while 
current 
  directory is still set to where executables were put to.

  Though last part is not too hard: `#!/bin/sh` scripts are using 
`dash` in 
  debian and it does not expand tilde. Neovim has run-without-a-shell 
  feature for functions like `system()`, `jobstart()`, etc and it is 
  actively used in a plugins where compatibility with Vim does not 
matter.

---

Second point behind disabling this behaviour is inconsistency. Consider 
another use-case: user has compiled custom Python and wants to use it 
in 
Neovim. He has `~/bin` in `$PATH`, put link to his Python installation 
there, verified that `python --version` shows correct output and 
started 
Neovim. Suddenly it appears that Neovim is still using system Python. 
He 
checked that `:!python --version` in Neovim is still his custom version 
(`:!` uses shell) and now goes to Neovim bug tracker and wastes a lot 
of 
time waiting for the reply and makes other people waste time deducing 
the 
solution. If his configuration was correct not only in bash there would 
be 
no such waste on either side, but bash hides the incorrectness.

---

Some note: I have found

> nn. Bash no longer expands tildes in $PATH elements while in Posix 
mode.

in the 4.4 changelog, but it does not look like it is solving the 
issue. 
What I am talking about is that tilde must *never* be expanded in 
`$PATH`.

Repeat-By:
Create script.sh with the following contents:

```shell
dir="$(mktemp -d)"
cd "$dir"
mkdir -p home/bin
mkdir -p \~/bin
HOME="$dir/home"
printf '#!/bin/sh\necho script' > home/bin/script
printf '#!/bin/sh\necho script2'> home/bin/script2
printf '#!/bin/sh\necho vulnerable' > \~/bin/script
chmod a+x home/bin/script
chmod a+x home/bin/script2
chmod a+x \~/bin/script
PATH='~/bin'
if test $# -gt 0 ; then
"$@"
else
script
fi
cd /
/bin/rm -r "$dir"
```

Run it like `bash script.sh`, it will print `script`.

Additional information:
To defend a point raised in the title that this behaviour is 
“inconsistent” 
I have collected results of various different kind of invocations of 

Segmentation fault for read -e in _rl_copy_to_kill_ring

2017-05-04 Thread Eduardo Bustamante
Steps to reproduce:

Run: read -e
Type: 0 ESC 0 \C-? \C-w

dualbus@afl2-hjbw:~$ cat -A
amin/id:80,sig:11,src:005611+014207,op:splice,rep:16.min
0^[0^?^W

dualbus@afl2-hjbw:~$ xxd
amin/id:80,sig:11,src:005611+014207,op:splice,rep:16.min
: 301b 307f 17 0.0..

Starting program: /home/dualbus/src/gnu/bash/bash
bash-4.4$ read -e
0
Program received signal SIGSEGV, Segmentation fault.
strlen () at ../sysdeps/x86_64/strlen.S:106
106 ../sysdeps/x86_64/strlen.S: No such file or directory.
(gdb) bt
#0  strlen () at ../sysdeps/x86_64/strlen.S:106
#1  0x55647425 in _rl_copy_to_kill_ring (text=0x559417a0
"0", append=0) at kill.c:134
#2  0x55647568 in rl_kill_text (from=1, to=0) at kill.c:179
#3  0x556478f1 in rl_unix_word_rubout (count=-1, key=23) at kill.c:328
#4  0x5562d76e in _rl_dispatch_subseq (key=23,
map=0x55895140 , got_subseq=0) at
readline.c:851
#5  0x5562d4e5 in _rl_dispatch (key=0, map=0x55895140
) at readline.c:797
#6  0x5562d16d in readline_internal_char () at readline.c:629
#7  0x5562d1c5 in readline_internal_charloop () at readline.c:656
#8  0x5562d1e9 in readline_internal () at readline.c:670
#9  0x5562cc06 in readline (prompt=0x5566dc94 "") at readline.c:374
#10 0x55606f17 in edit_line (p=0x5566dc94 "", itext=0x0)
at ./read.def:1069
#11 0x55605e3d in read_builtin (list=0x0) at ./read.def:550
#12 0x555a2034 in execute_builtin (builtin=0x5560510e
, words=0x558d0b40, flags=0, subshell=0)
at execute_cmd.c:4605
#13 0x555a2f10 in execute_builtin_or_function
(words=0x558d0b40, builtin=0x5560510e , var=0x0,
redirects=0x0, fds_to_close=0x558d09b0, flags=0) at execute_cmd.c:5103
#14 0x555a193a in execute_simple_command
(simple_command=0x558d0970, pipe_in=-1, pipe_out=-1, async=0,
fds_to_close=0x558d09b0) at execute_cmd.c:4391
#15 0x5559b2f0 in execute_command_internal
(command=0x558d0c00, asynchronous=0, pipe_in=-1, pipe_out=-1,
fds_to_close=0x558d09b0) at execute_cmd.c:811
#16 0x5559a84c in execute_command (command=0x558d0c00) at
execute_cmd.c:393
#17 0x555849ca in reader_loop () at eval.c:172
#18 0x55582617 in main (argc=1, argv=0x7fffe498,
env=0x7fffe4a8) at shell.c:794



Re: Bash is incorrectly and inconsistently expanding tilde in $PATH

2017-05-04 Thread Eduardo Bustamante
On Wed, May 3, 2017 at 5:40 PM, Nikolay Aleksandrovich Pavlov (ZyX)
 wrote:
[...]
> If $PATH in bash contains ~ (e.g. `PATH='~/bin'`) it is incorrectly 
> treated
> as if $HOME is present.

Hm. You can start bash in POSIX mode
(https://www.gnu.org/software/bash/manual/bash.html#Bash-POSIX-Mode)
if you want to disable this feature. i.e.

dualbus@debian:~$ bash --posix -c 'printf "%s\n" "#!/bin/bash"
"echo hi" > ~/cmd; chmod +x ~/cmd; PATH=\~; declare -p PATH; cmd'
declare -x PATH="~"
bash: cmd: command not found

dualbus@debian:~$ bash -c 'printf "%s\n" "#!/bin/bash" "echo hi" >
~/cmd; chmod +x ~/cmd; PATH=\~; declare -p PATH; cmd'
declare -x PATH="~"
hi

Bash's behavior here is intentional by the way, review the function
find_in_path_element in
http://git.savannah.gnu.org/cgit/bash.git/tree/findcmd.c?h=devel#n527,
it will perform tilde expansion if the path component starts with a
tilde. Perhaps it should be documented under
https://www.gnu.org/software/bash/manual/bash.html#Bourne-Shell-Variables
that bash treats tildes inside PATH specially.

Also, I think it's a bit of a stretch to call this a security problem.
The scenario you describe (a user having a directory literally named
`~' with a bin subdirectory, a malicious program creating evil
binaries in $HOME/bin,  the user having a misconfigured PATH, ...) is
highly unlikely.



Re: Bash is incorrectly and inconsistently expanding tilde in $PATH

2017-05-04 Thread Eduardo Bustamante
Here's a previous discussion on that subject:

- http://lists.gnu.org/archive/html/bug-bash/2014-07/msg00022.html
- https://lists.gnu.org/archive/html/bug-bash/2014-08/msg2.html



Re: Bash is incorrectly and inconsistently expanding tilde in $PATH

2017-05-04 Thread Greg Wooledge
On Thu, May 04, 2017 at 09:54:07AM -0500, Eduardo Bustamante wrote:
> Also, I think it's a bit of a stretch to call this a security problem.
> The scenario you describe (a user having a directory literally named
> `~' with a bin subdirectory, a malicious program creating evil
> binaries in $HOME/bin,  the user having a misconfigured PATH, ...) is
> highly unlikely.

Without taking a side on whether this is a security bug in bash, I will
support the idea that users who put ~/bin (or similar) in PATH should
be educated to make sure the ~ is expanded, rather than literal.  This
will protect them even if bash gets patched, because most of them will
still be using an older/unpatched version.

I will also point out that bash expands ~ in PATH assignments such as
PATH=~/bin:$PATH or even PATH=$PATH:~/bin:/other/bin.  So, it really does
take a bit of work to get a literal ~ into PATH in bash, and users
should be discouraged from doing that extra, self-harming work.



Re: Bash is incorrectly and inconsistently expanding tilde in $PATH

2017-05-04 Thread Eduardo Bustamante
On Thu, May 4, 2017 at 10:01 AM, Greg Wooledge  wrote:
[...]
> Without taking a side on whether this is a security bug in bash, I will
> support the idea that users who put ~/bin (or similar) in PATH should
> be educated to make sure the ~ is expanded, rather than literal.  This
> will protect them even if bash gets patched, because most of them will
> still be using an older/unpatched version.

So should bash print a warning whenever it performs tilde expansion in
one of the PATH components? (similar to the warning it prints when
discarding NUL bytes).

Something like:

dualbus@debian:~/src/gnu/bash$ ./bash -c 'PATH="~"; cmd'
./bash: warning: command lookup: performing tilde expansion due to
literal `~' found in PATH
hi

dualbus@debian:~/src/gnu/bash$ git diff -- findcmd.c
diff --git a/findcmd.c b/findcmd.c
index c3f00a40..12d3ac2d 100644
--- a/findcmd.c
+++ b/findcmd.c
@@ -524,7 +524,12 @@ find_in_path_element (name, path, flags,
name_len, dotinfop)
   int status;
   char *full_path, *xpath;

-  xpath = (posixly_correct == 0 && *path == '~') ? bash_tilde_expand
(path, 0) : path;
+  if (posixly_correct == 0 && *path == '~') {
+internal_warning ("%s", "command lookup: performing tilde
expansion due to literal `~' found in PATH");
+xpath = bash_tilde_expand (path, 0);
+  } else {
+xpath = path;
+  }

   /* Remember the location of "." in the path, in all its forms
  (as long as they begin with a `.', e.g. `./.') */



Re: Bash is incorrectly and inconsistently expanding tilde in $PATH

2017-05-04 Thread Nikolay Aleksandrovich Pavlov (ZyX)


04.05.2017, 17:54, "Eduardo Bustamante" :
> On Wed, May 3, 2017 at 5:40 PM, Nikolay Aleksandrovich Pavlov (ZyX)
>  wrote:
> [...]
>>  If $PATH in bash contains ~ (e.g. `PATH='~/bin'`) it is incorrectly 
>> treated
>>  as if $HOME is present.
>
> Hm. You can start bash in POSIX mode
> (https://www.gnu.org/software/bash/manual/bash.html#Bash-POSIX-Mode)
> if you want to disable this feature. i.e.
>
> dualbus@debian:~$ bash --posix -c 'printf "%s\n" "#!/bin/bash"
> "echo hi" > ~/cmd; chmod +x ~/cmd; PATH=\~; declare -p PATH; cmd'
> declare -x PATH="~"
> bash: cmd: command not found
>
> dualbus@debian:~$ bash -c 'printf "%s\n" "#!/bin/bash" "echo hi" >
> ~/cmd; chmod +x ~/cmd; PATH=\~; declare -p PATH; cmd'
> declare -x PATH="~"
> hi

POSIX mode is inconvenient to use: different rc files, a bunch of differences 
regarding scripts, other things. No process substitution, this is a stopper.

>
> Bash's behavior here is intentional by the way, review the function
> find_in_path_element in
> http://git.savannah.gnu.org/cgit/bash.git/tree/findcmd.c?h=devel#n527,
> it will perform tilde expansion if the path component starts with a
> tilde. Perhaps it should be documented under
> https://www.gnu.org/software/bash/manual/bash.html#Bourne-Shell-Variables
> that bash treats tildes inside PATH specially.
>
> Also, I think it's a bit of a stretch to call this a security problem.
> The scenario you describe (a user having a directory literally named
> `~' with a bin subdirectory, a malicious program creating evil
> binaries in $HOME/bin, the user having a misconfigured PATH, ...) is
> highly unlikely.

There still is a consistency problem. $PATH is not a bash-specific variable for 
it to have bash-specific features, and I really saw such bugs in either vim-dev 
or neovim bug tracker (not sure, can’t construct a good search to look for 
non-letter characters like tilde). More likely in Neovim because in Vim it 
would need to have &shell set not to bash.

Also actually found an [issue][1] in powerline, it does not have that much bugs 
to search. This is going to be a problem in all cases when bash is used with 
something which searches in $PATH, but is not bash, so if intentional it is 
a misfeature.

[1]: https://github.com/powerline/powerline/issues/850



Re: Racing condition leads to unstable exit code

2017-05-04 Thread Chet Ramey
On 5/3/17 8:43 PM, Luiz Angelo Daros de Luca wrote:
> Yes, the devel one does work. Sorry for the confusion.
> It is the first time I see master as stable.

It was like that when I inherited it, and I didn't have enough git
expertise to fold in all of the previous commits where they should
go, so I left it as is and started a new branch.

> Would the fix be backported to stable?

Let me see if I can put together a patch for you to test.

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: Bash is incorrectly and inconsistently expanding tilde in $PATH

2017-05-04 Thread Ángel
On 2017-05-04 at 10:11 -0500, Eduardo Bustamante wrote:
> On Thu, May 4, 2017 at 10:01 AM, Greg Wooledge  wrote:
> [...]
> > Without taking a side on whether this is a security bug in bash, I will
> > support the idea that users who put ~/bin (or similar) in PATH should
> > be educated to make sure the ~ is expanded, rather than literal.  This
> > will protect them even if bash gets patched, because most of them will
> > still be using an older/unpatched version.
> 
> So should bash print a warning whenever it performs tilde expansion in
> one of the PATH components? (similar to the warning it prints when
> discarding NUL bytes).

No. IMHO the fix would be to expand ~ at assignment time, even when
quoted, ie. PATH='~/bin' would be equivalent to PATH=~/bin

Thus, assignments of ~/whatever done in bash would continue working, and
descendants using a execvp() function would not find a bare tilde but
the expanded path, which is the 'expected' thing.
(And for people that really want a literal ~ in PATH, that is already
«broken» in bash, so if they expect that to be kept, they should not be
doing so within bash)




double free or corruption read builtin

2017-05-04 Thread Eduardo Bustamante
dualbus@debian:~/bash-fuzzing/read$ cat -A 6b
M-^_0^A\$
^N

dualbus@debian:~/bash-fuzzing/read$ od -c 6b
000 237   0 001   \  \n 016
006

(gdb) file ~/src/gnu/bash/bash
Reading symbols from ~/src/gnu/bash/bash...done.
(gdb) r -c 'exec < 6b; read -N3 -d "" IFS; read a b'
Starting program: /home/dualbus/src/gnu/bash/bash -c 'exec < 6b; read
-N3 -d "" IFS; read a b'
*** Error in `/home/dualbus/src/gnu/bash/bash': double free or
corruption (out): 0x558b6ac0 ***
=== Backtrace: =
/lib/x86_64-linux-gnu/libc.so.6(+0x70bcb)[0x7767dbcb]
/lib/x86_64-linux-gnu/libc.so.6(+0x76f96)[0x77683f96]
/lib/x86_64-linux-gnu/libc.so.6(+0x7778e)[0x7768478e]
/home/dualbus/src/gnu/bash/bash(read_builtin+0x1a58)[0x55606b82]
/home/dualbus/src/gnu/bash/bash(+0x4e034)[0x555a2034]
/home/dualbus/src/gnu/bash/bash(+0x4ef10)[0x555a2f10]
/home/dualbus/src/gnu/bash/bash(+0x4d93a)[0x555a193a]
/home/dualbus/src/gnu/bash/bash(execute_command_internal+0x80a)[0x5559b2f0]
/home/dualbus/src/gnu/bash/bash(+0x4a49d)[0x5559e49d]
/home/dualbus/src/gnu/bash/bash(execute_command_internal+0xbc0)[0x5559b6a6]
/home/dualbus/src/gnu/bash/bash(parse_and_execute+0x548)[0x555fe2d9]
/home/dualbus/src/gnu/bash/bash(+0x2f32f)[0x5558332f]
/home/dualbus/src/gnu/bash/bash(main+0x83a)[0x555824aa]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf1)[0x7762d2b1]
/home/dualbus/src/gnu/bash/bash(_start+0x2a)[0x55581b6a]
=== Memory map: 
4000-5568e000 r-xp  fe:01 17570340
  /home/dualbus/src/gnu/bash/bash
5588e000-55891000 r--p 0013a000 fe:01 17570340
  /home/dualbus/src/gnu/bash/bash
55891000-5589b000 rw-p 0013d000 fe:01 17570340
  /home/dualbus/src/gnu/bash/bash
5589b000-558c6000 rw-p  00:00 0  [heap]
7000-70021000 rw-p  00:00 0
70021000-7400 ---p  00:00 0
773f6000-7740c000 r-xp  fe:01 1310769
  /lib/x86_64-linux-gnu/libgcc_s.so.1
7740c000-7760b000 ---p 00016000 fe:01 1310769
  /lib/x86_64-linux-gnu/libgcc_s.so.1
7760b000-7760c000 r--p 00015000 fe:01 1310769
  /lib/x86_64-linux-gnu/libgcc_s.so.1
7760c000-7760d000 rw-p 00016000 fe:01 1310769
  /lib/x86_64-linux-gnu/libgcc_s.so.1
7760d000-777a2000 r-xp  fe:01 1311151
  /lib/x86_64-linux-gnu/libc-2.24.so
777a2000-779a1000 ---p 00195000 fe:01 1311151
  /lib/x86_64-linux-gnu/libc-2.24.so
779a1000-779a5000 r--p 00194000 fe:01 1311151
  /lib/x86_64-linux-gnu/libc-2.24.so
779a5000-779a7000 rw-p 00198000 fe:01 1311151
  /lib/x86_64-linux-gnu/libc-2.24.so
779a7000-779ab000 rw-p  00:00 0
779ab000-779ae000 r-xp  fe:01 1311170
  /lib/x86_64-linux-gnu/libdl-2.24.so
779ae000-77bad000 ---p 3000 fe:01 1311170
  /lib/x86_64-linux-gnu/libdl-2.24.so
77bad000-77bae000 r--p 2000 fe:01 1311170
  /lib/x86_64-linux-gnu/libdl-2.24.so
77bae000-77baf000 rw-p 3000 fe:01 1311170
  /lib/x86_64-linux-gnu/libdl-2.24.so
77baf000-77bd4000 r-xp  fe:01 1310814
  /lib/x86_64-linux-gnu/libtinfo.so.5.9
77bd4000-77dd4000 ---p 00025000 fe:01 1310814
  /lib/x86_64-linux-gnu/libtinfo.so.5.9
77dd4000-77dd8000 r--p 00025000 fe:01 1310814
  /lib/x86_64-linux-gnu/libtinfo.so.5.9
77dd8000-77dd9000 rw-p 00029000 fe:01 1310814
  /lib/x86_64-linux-gnu/libtinfo.so.5.9
77dd9000-77dfc000 r-xp  fe:01 1310733
  /lib/x86_64-linux-gnu/ld-2.24.so
77e6-77e61000 rw-p  00:00 0
77e61000-77eb2000 r--p  fe:01 26351510
  /usr/lib/locale/aa_DJ.utf8/LC_CTYPE
77eb2000-77fe2000 r--p  fe:01 26351509
  /usr/lib/locale/aa_DJ.utf8/LC_COLLATE
77fe2000-77fe4000 rw-p  00:00 0
77fe4000-77fe5000 r--p  fe:01 26351533
  /usr/lib/locale/aa_ET/LC_NUMERIC
77fe5000-77fe6000 r--p  fe:01 26480725
  /usr/lib/locale/en_US.utf8/LC_TIME
77fe6000-77fe7000 r--p  fe:01 26355066
  /usr/lib/locale/chr_US/LC_MONETARY
77fe7000-77fe8000 r--p  fe:01 26355282
  /usr/lib/locale/en_AG/LC_MESSAGES/SYS_LC_MESSAGES
77fe8000-77fe9000 r--p  fe:01 26355068
  /usr/lib/locale/chr_US/LC_PAPER
77fe9000-77fea000 r--p  fe:01 26355067
  /usr/lib/locale/chr_US/LC_NAME
77fea000-77feb000 r--p  fe:01 26480723
  /usr/lib/locale/en_US.utf8/LC_ADDRESS
77feb000-77fec000 r--p  fe:01 26355069
  /usr/lib/locale/chr_US/LC_TELEPHONE
77fec000-77fed000 r--p  fe:01 26355064
  /usr/lib/locale/chr_US/LC_MEASUREMENT
77fed000-77ff4000 r--s  fe:01 25449459
  /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache
77ff4000-77ff5000 r--p  fe:01 26480724
  /usr/lib/locale/en_US.utf8/LC_IDENTIFICATION
77ff5000-77ff8000 rw-p  00:00 0
77ff8000-77ffa000 r--p  00:00 0