In my last post I disclosed a vulnerability I found in BusyBox relating to escape sequences. The post covers the dangers of such vulnerabilities and shows how they can be abused with modern terminals. After publishing the post, I went on with my daily tasks, only more alert of the issues with escape characters. The next time I used git, I realized it may be a very interesting medium for abusing escape sequences.
First concern: git diff
The first git tool I could think of that is frequently used by git users is
git-diff, invoked by “git diff”. For those unfamiliar with git diff, it is a tool that compares two commits (or the working tree) and displays the changes between them. I’ve personally found myself relying on it many times, especially when working with repositories that were not cloned to GitHub, but also just because it is very convenient to use.
Unfortunately, git diff fails to sanitize all types of escape sequences. Some sequences in file contents are printed to the terminal, consequently putting git users at a risk.
To give git some credit, there is some sanitization taking place. In my attempts to write a PoC I found that sequences to erase characters or change the placement of the cursor were removed by the tool. In my previous post I mentioned many of the historical terminal vulnerabilities, using features such as screen clearing or title changing. These vulnerabilities will not be printed with git diff.
However, some sequences were left untreated, such as ones used for coloring text or other graphical escape sequences. I imagine there may be zero-day terminal vulnerabilities with the escape sequences that are allowed.
Even without any terminal issue, by using acceptable formatting sequences, one could add backdoor code to a file that would not be seen in the diff, by using the text hiding escape sequence! In that way, a commit that may seem legitimate could hold malicious code inside it.
See a PoC of such an attack (repo on GitHub):
Sure, that code could eventually be found by the developers when reviewing the code with a text editor, but the impact can be hazardous if a backdoor makes it into even one version of a popular project. Smart attackers may as well find ways to make sure it is not found by the developers.
Before approaching git diff, my first idea was to insert an escape sequence to a commit message. One of the most basic and common tools git provides is
git-log, called by running “git log”. It is used by many developers and users to review changes made to a repository. If escape characters are not sanitized, any commit message including escape sequences would be parsed by all of the repository users upon reading the repository’s change log.
Just like git diff issues, this is possible only with some escape sequences. Cursor control and similar sequences are removed. In git log messages however, there is not much that could be done with hidden content, so the risk here just includes terminal vulnerabilities.
Besides the two mentioned above, I looked into other git tools I know to find if they allow unsanitized content to be printed to the terminal. The tools I found vulnerable were not closely as dangerous as the previous ones, and can only be abused when an attacker has local access to a git repository. I decided to mention them nevertheless.
First, I found that
git-rm, called with “git rm” may print escape characters when included in a file’s name. When running git rm, git responds by printing the name of the files that were removed. If there is a local file that includes an escape sequence, it will printed and parsed by the terminal. To reproduce, create a file with escape sequences in it’s name, such as:
touch `echo -e "\e[45mTwistlock\e[0m"
Then add the file to a git repository and run “git rm *” on the repository (or any regex that would catch the file and remove it). The filename will be printed to your terminal, including the escape sequences in it.
The second issue is with branch names. Normally, escape characters aren’t allowed for branch names. However, I found that it is possible to get the
git-branch tool to print escape characters by including them in the filename of a ref file. I don’t mean to elaborate on git repositories’ structure here as I am unfamiliar with it myself, but I do know ref files are included in all git repositories, and that one of these files includes branch names.
To reproduce what I did, create a file in your
.git/refs/heads directory and include your payload in the filename. For instance:
touch `echo -e ".git/refs/heads/\e[45mTwistlock\e[0m"`
Upon running “git branch” you will see the following message:
"warning: ignoring ref with broken name refs/heads/Twistlock"
The escape sequence will be parsed in the terminal when that message is printed.
Git’s developers take
I sent an advisory to git’s security mailing list, listing all the issues I presented above. The initial responses I received were skeptical. One of the assertion suggested that the same problem can be reproduced with cat, so it is not git’s problem. I argued that this is something that git should change, as allowing escape sequences adds no real value to git users as far as I am concerned.
Personally, I agree that the issue of escape sequences is of terminal emulators, and not CLI programs. In reality, having possible zero-day vulnerabilities and users running outdated software, it is probably the best for popular tools such as git to add some content sanitization blocking the use of these sequences. As I showed in my last post, CVEs were assigned for programs like Apache, nginx, Ruby and others for the same issue.
The discussion is still ongoing, but it’s been agreed that we should take the conversation public, considering the issue of escape sequences isn’t new to anyone.
As shown in this post and the previous one, escape sequences are not something to treat lightheartedly. Using vulnerabilities, malicious users can abuse them to execute code on vulnerable users, or rely on legitimate sequences to mislead unwary users. We will keep our @TwistlockLabs Twitter channel updated on this issue. Follow us for more on this and other security updates!
Unpacking Envoy Vulnerabilities (CVE-2019-9900 and CVE-2019-9901) and How it Impacts IstioRead the Blog
Disclosing a directory traversal vulnerability in Kubernetes copy – CVE-2019-1002101Read the Blog
Breaking out of Docker via runC – Explaining CVE-2019-5736Read the Blog
T19 Challenge – Twistlock Lab’s first security challenge summary and solutionsRead the Blog