
A proof-of-concept of a vulnerability in custom shell prompt scripts - njhartwell
https://github.com/njhartwell/pw3nage
======
rahiel
The "official" git prompt[1] is safe on Bash; the script doesn't run.

[1]:
[https://github.com/git/git/blob/master/contrib/completion/gi...](https://github.com/git/git/blob/master/contrib/completion/git-
prompt.sh)

~~~
caf
In particular see the long comment at line 324.

~~~
adito
> If the shell would expand the contents of PS1 when drawing the prompt, a raw
> ref name must not be included in PS1. This protects the user from arbitrary
> code execution via specially crafted ref names. For example, a ref named
> 'refs/heads/$(IFS=_;cmd=sudo_rm_-rf_/;$cmd)' might cause the shell to
> execute 'sudo rm -rf /' when the prompt is drawn.

[1]:
[https://github.com/git/git/blob/9d77b0405ce6b471cb5ce3a90436...](https://github.com/git/git/blob/9d77b0405ce6b471cb5ce3a904368fc25e55643d/contrib/completion/git-
prompt.sh#L331-L336)

------
abbeyj
Tab autocompletion looks to be affected too, at least on my system. Create a
branch called 'complete_$(./foo)'. Then type 'git checkout comp<TAB>'. This
gets autocompleted to

    
    
        git checkout complete_$(./foo)
    

If you hit Enter at this point without thinking you'll end up running './foo'.
It should have expanded instead to something like

    
    
        git checkout 'complete_$(./foo)'
    

or

    
    
        git checkout complete_\$\(./foo\)

~~~
oconnor663
Zsh seems to do the escaping correctly there.

~~~
junkblocker
Confirming what GP said on version 5.3.1, not seeing any escaping

    
    
        git checkout <Tab>
        git checkout $(./pwd)

~~~
Freaky
Escaped here. How are you configuring your completion?

    
    
        -% zsh -f
        voi% echo $ZSH_VERSION
        5.3.1
        voi% autoload -U compinit
        voi% compinit
        voi% git checkout <tab><tab>\$\(./pw3n\)
        Already on '$(./pw3n)'
        Your branch is up-to-date with 'origin/$(./pw3n)'.
        voi% git checkout com<tab>plete_\$\(./foo\)
        Switched to branch 'complete_$(./foo)'

------
koolba
It's always cute to find new vectors for command injection. Really anytime you
mix data and commands this type of crap is bound to happen (ex: sql
injection).

Still not as worrisome to me as the full scripts that get executed by package
managers when you install dependencies. Effectively every time you run
something like "npm install" you're putting your faith in the entire tree of
ancestor dependencies as any of them could have a pwnage script as a post
install.

~~~
goodplay
More often than not, building and deploying is secondary for developers to
writing the library itself, if that. Build scripts and installation don't get
the same treatment and care the library does.

The is one of the primary reasons why I prefer distribution-packaged libraries
to pulling a library and its dependencies directly from developers. Staleness
is a small price to pay relative to having at least two sets of eyes glance
over the source and not execute arbitrary build scripts on my system.

------
lillesvin
Cute idea. I'm willing to bet that the Bash script I wrote for some of my co-
workers is vulnerable. I guess that's something I should find out ... by
making their computers do stuff.

However, I currently use Fish shell myself and it seems to be safe:
[http://imgur.com/a/rjocA](http://imgur.com/a/rjocA)

~~~
simlevesque
Maybe someone could craft a similar vulnerability for Fish.

------
pyreal
Confirmed that default bash-it Git shell prompt is vulnerable on OS X.

[https://github.com/Bash-it/bash-it](https://github.com/Bash-it/bash-it)

------
mikey_p
On fish and omf here, not vulnerable. I suppose I should test fisherman on my
other machine as well.

~~~
nathankleyn
I've confirmed fisherman is safe on my machine.

~~~
simplehuman
Omf is also safe

------
Hexcles
TIL. Never expected bash would do an expansion on PS1 by default. Thanks a
bunch.

bash-powerline is affected. I've sent out a PR:
[https://github.com/riobard/bash-
powerline/pull/12/](https://github.com/riobard/bash-powerline/pull/12/)

My own fork (with some additional features) is already patched:
[https://github.com/Hexcles/bash-powerline](https://github.com/Hexcles/bash-
powerline)

------
junkblocker
Since branch name parsing is done by a lot of scripts, and I can't control the
default branch name, I've installed this global post-checkout hook for now
until I can stop panicking and think clearly.

    
    
        #!/bin/sh
        prev_head=$1
        new_head=$2
        changing_branch=$3
    
        REPO_DIR="$(git rev-parse --show-toplevel 2>/dev/null)"
    
        if [ "$changing_branch" = 1 -a "$prev_head" = "0000000000000000000000000000000000000000" ]; then
            new_head_name="$(git name-rev --name-only "$new_head"|sed -e 's|`|_|g' -e 's|$(|_|g')"
            new_head_name_untaint="$(git name-rev --name-only "$new_head"|sed -e 's|`|x|g' -e 's|$(|x|g')"
            if [ "$new_head_name" != "$new_head_name_untaint" ]; then
                echo "
        DANGER! INSECURE BRANCH NAME.
        ">&2
                git name-rev --name-only "$new_head"
    
                echo "
        MOVING $REPO_DIR TO TRASH.
        ">&2
                mkdir -p ~/.Trash
                mv "$REPO_DIR" "$HOME/.Trash/${REPO_DIR##*/}.$(date +"%Y%m%d%H%M%S")"
            fi
        fi

------
ejcx
Dang. Unfortunately I am not vulnerable, and I use default ohmyzsh.

This is a neat bug, though. Lots of package managers have similar problems,
and I would not be surprised if there's a lot of git/shell/environment
problems left to find.

~~~
Ajedi32
Why is it unfortunate that you're not vulnerable? Isn't that a good thing?

~~~
caust1c
He's an applications security researcher. That stuff is fun for him.

------
klodolph
Neat. My fancy Git prompt is a program I wrote in C, though. I'm sure it's
vulnerable to something, but not to this. Maybe it should escape shell
metacharacters in branch names, though.

------
tristor
Nice find. Luckily I am hyper-paranoid about escaping, so even though my
custom jankery is probably not as performant as it could be, it's not
vulnerable to this or similar exploits.

------
junkblocker
This is worrisome. Even carelessly trying to checkout a branch named like that
is vulnerable without a prompt being involved:

    
    
        git co -b foo <Tab> to complete branch names
        git co -b foo $(./pw3n) <- execution right here

------
shawkinaw
Liquid Prompt [0] seems safe.

[0]
[https://github.com/nojhan/liquidprompt](https://github.com/nojhan/liquidprompt)

------
jaegerpicker
My OSX shell prompt is vunerable, I'm using zsh, oh-my-zsh, and
powerlevel9k/powerlevel9k as my theme.

------
chadgeidel
Forgive me if I'm misunderstanding the vulnerability, but isn't this one of
Raymond Chen's "It rather involved being on the other side of this airtight
hatchway" exploits? That is, any commands you run has the same permissions as
you have.

Now, I understand that you may not intimately understand 100% the code of the
commands and shell extensions you use, but is that a "vulnerability"?

~~~
geofft
The privilege escalation is from "can push code to a repository that you pull
from" to "can run code as you". The idea is that you trust the shell extension
you're using, but a particular git repo exploits a vulnerability in that shell
extension.

git cloning code vs. running code is sometimes a security boundary and
sometimes not. For instance, if you go cd into that directory and then run
make or ./configure or ./setup.py install or docker run or something, then
yeah, you've removed that boundary. But in general, it's reasonable to keep
the boundary there. Perhaps you're doing code review of code by an untrusted
author, either of someone else's project or of a pull request to your own
project. Perhaps you're packaging up the software to run it as a less-
privileged account. Perhaps you're a sysadmin helping a user figure something
out. And so forth.

~~~
chadgeidel
Thanks for the explanation.

------
eridius
Confirmed that the official git prompt for Fish is not vulnerable.

~~~
gutnor
edit: nevermind - pbkac, does not appear to be vulnerable !

Did you try creating a branch called "(./pw3n)" ?

I'm running fish with git-radar. I'm not vulnerable to that specific attack
but to a similar one with the branch name (./pw3n)

------
yasserkaddour
ohmyzsh `pure` theme is vulnerable, most of the other themes seems fine to me,
but no theme is safe when using ohmyzsh in tmux.

------
grosser
only allowing know characters is a simple fix: branch=${BRANCH//[^a-z0-9\/]/-}

------
wnevets
git for windows seems to be fine.

------
SrslyJosh
bash-git-prompt is vulnerable.

------
neoromantique
ohmyzsh is vulnerable.

~~~
Chlorus
Didn't work for me - I'm using oh-my-zsh in iTerm2, and I'm just using the git
plugin & a custom theme, nothing else. Maybe we're using different plugins?

