Piping curl to s(hell)

Oh My Zsh, Calibre, Docker, Rust, Yarn.

At first glance those software projects don't have much in common. There is however one thing they share: a potential glaring security vulnerability which will manifest itself before you even run those programs. Developers of all of them are guilty of teaching people that the following command is safe to execute:

$ curl https://example.com/script.sh | bash

Some developers even have the audacity to include sudo on right side of the pipe. This practice has become more widespread recently with developers attempting to "help" the users by providing a nice, easy installation script for them to run. In reality they are desensitising them to a direct security threat. There are many ways in which copying a command like the one pictured above can backfire and I would like to list several of them as a cautionary measure. Below you can find both various types of attacks and honest mistakes which can be a threat to your machine.

Standard man-in-the-middle attacks

A problem so obvious and talked about so extensively that it shouldn't even exist anymore but unfortunately it still does (even though this is becoming less and less common). If the developers omit the usage of TLS in their links they expose the resource to a standard man-in-the-middle attack. This means that if any router, caching server or other device between you and the server from which the installation script is being served is malicious or becomes compromised your machine will be exposed to an attack as well.

Hidden text attacks

Below I prepared a harmless script for you to execute, please copy the following line and paste it into your terminal (or a text editor - you shouldn't trust a random blog post):

echo Oooops\!; echo Owned\! echo "Hello I am completely harmless!";

As you can see the text which you are copying may not be what you expect. A variety of available text-based attacks make the portion of the text invisible to even the most observant users. If the website you are copying the command from becomes compromised or simply is malicious you can be easily tricked into running unexpected code. This can be prevented by pasting the command into a text editor before executing it. This attack is even simpler if the website features a helpful button which lets you easily copy the command into your clipboard.

User-Agent based attacks

It is important to remember that the software which you may be using likely emits an easy to recognize User-Agent. This is the case for both widely used wget and curl . It is very easy to prepare a server which returns a harmless script when viewed using your browser but serves malicious code when downloading the same resource using curl or wget . This can be used to attack users which take the time to inspect the code being served. To mitigate this attack you can first redirect the script to a file and inspect it before execution.

Partial content returned by the server

When using curl to pipe the script directly into your shell it is teoretically possible for the connection to be interrupted in an unpredictable way. In this case curl or other program can only output a part of the script before failing. In this case we can imagine a scenario in which a script does something that it shouldn't do. For example the following command:

$ rm -r /usr/share/program

Could become:

$ rm -r /usr

This is of course a syntetic example but it is not hard to imagine a different scenario in which a command may fail in an equally devastating way.

A simple matter of not knowing what the script is going to do

A package manager is a common and welcome sight in the world of Linux-based operating systems. When installing software using a package manager we have a guarantee that all (or most) of the files used by the program will be tracked and accounted for and removed when uninstalling it. The same is true for various dependencies and the package manager also provides us with many other security measures such as ensuring that files belonging to an already installed program will not be overwritten by accident during the installation process. When executing an unknown script we don't know what is going to happen - we will not be able to easily find out what files were installed. This problem is mostly related to a simple necessity of keeping track of various entries in your file system. Imagine the chaos arising if every program was installed manually without the help a package manager. This also exposes you to unpached security issues as the installed program will not be automatically updated.

Examples of the offending commands

Below are the installation commands recommended by the projects listed at the beginning of this post.

sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"

sudo -v && wget -nv -O- https://download.calibre-ebook.com/linux-installer.sh | sudo sh /dev/stdin

curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh

curl https://sh.rustup.rs -sSf | sh

curl -o- -L https://yarnpkg.com/install.sh | bash

Conclusion

Be vigilant when copying and executing commands found on the Internet. The biggest threat to your system will most likely always be a simple mistake so try to make sure that you are aware of what you are doing. When possible you should be using your system's package manager to install new software.

And to the developers: remember that cutting corners is probably the main reason for various security weaknesses.

This post was inspired by a tweet posted by one of my friends.