[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Bash is incorrectly and inconsistently expanding tilde in $PATH
From: |
Nikolay Aleksandrovich Pavlov (ZyX) |
Subject: |
Bash is incorrectly and inconsistently expanding tilde in $PATH |
Date: |
Thu, 04 May 2017 01:40:50 +0300 |
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
the
above script to show places where that bash behaviour is not consistent
with
other applications:
```
% bash script.sh
script
% dash script.sh
vulnerable
% posh script.sh
vulnerable
% sh script.sh =fish -c script
vulnerable
% zsh script.sh
vulnerable
% mksh script.sh
vulnerable
% ksh script.sh
vulnerable
% echo 'main() { execlp("script", "script", "script"); }' > prog.c
% sh script.sh =tcc -run $PWD/prog.c
vulnerable
% sh script.sh =vim --cmd 'echo executable("script2")' --cmd qa
0
% sh script.sh =nvim --cmd 'echo system(["script"])' --cmd qa
vulnerable
% sh script.sh =python -c 'from subprocess import check_call ;
check_call(["script"])'
vulnerable
% sh script.sh =perl -e 'system "script", "x"'
vulnerable
```
(Note: script may be run as-is in zsh only, replace `=foo` with
`"$(which
foo)"` in other shells. Leaving as-is because `=…` is more readable.)
Re: Bash is incorrectly and inconsistently expanding tilde in $PATH, Chet Ramey, 2017/05/06