Page tree
Skip to end of metadata
Go to start of metadata

Quite often we need to pull in artefacts from outside of OPNFV in the form of virtual machine images, tarballs of software releases or scripts (which are then piped through a shell).

When doing this it can introduce known security risks, when steps are not made to insure integrity of the retrieved object.

In this wiki page, we will take a look at the risks and then outline steps to migrate those risks.

CURL and WGET of images and tarballs

Example code:

wget http://example.com/releases/image.iso
 
curl -O http://example.com/release/file.tar.gz

This is quite a common occurrence in deployment and test based scripts. An ISO file is download and instantiated as a virtual machine or some software is retrieved in the form of a tarball, and its contents are deployed onto the desired system.

What's wrong with this?

The problem is that infrastructure does get hacked (everyday), and files can be swapped out for a doctored version that can contain a backdoor / malware.

If this were to happen at OPNFV, then anyone deploying the platform could end up with a malicious VM running and active in their network.

Such a VM could then 'dial home' and allow someone to then use the VM as a jump box and start performing network reconnaissance, with a view to attacking other adjacent nodes.

A real world example of this is with the distribution Linux Mint. Hackers got into the infrastructure of the website and replaced the ISO with a version that was nefarious. Unsuspecting users then installed the ISO and were compromised.

You can read more about the attack here.

OK, so how do I do this in a more secure way?

Essentially we need to insure the file has not been tampered with, and the best way to do this is by means of GPG signing with a strong crypto (preferably sha256).

Most decent software projects and Linux distributors supply these GPG signings that can be used for verification (if they don't, you should tell them that they should).

Let's take for example node.js tarballs

http://nodejs.org/dist/latest/

Alongside the tarballs are files named 'SHASUMS256.txt.asc' - these sig files are created by the developer each release, and only the developer has the private keys to allow that release signing to occur.

Using this gpg sig we can then verify the file:

curl -SLO "https://nodejs.org/dist/latest/node-v8.1.4-linux-x64.tar.gz"
curl -SLO "https://nodejs.org/dist/latest/SHASUMS256.txt.asc"
# Import the developers keys
gpg --keyserver pool.sks-keyservers.net --recv-key \
	94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
	FD3A5288F042B6850C66B31F09FE44734EB7990E \
	71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
	DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
	C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
	B9AE9905FFD7803F25714661B63B535A4C206CA9 \
	56730D5401028683275BD23C23EFEFE93C4CFFFE
# Verify the has was signed by the above developers
gpg --verify SHASUMS256.txt.asc
# Verify the tar ball file has the correct same sha256 checksum / hash
grep node-v8.1.4-linux-x64.tar.gz  SHASUMS256.txt.asc | shasum -a 256 -c 

These CLI examples can then of course be wrapped into a shell script

#!/bin/bash

echo -e "Installing release keys\n"
gpg --keyserver pool.sks-keyservers.net --recv-key \
	94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
	FD3A5288F042B6850C66B31F09FE44734EB7990E \
	71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
	DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
	C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
	B9AE9905FFD7803F25714661B63B535A4C206CA9 \
	56730D5401028683275BD23C23EFEFE93C4CFFFE
 
echo -e "Downloading tarball\n"
curl -SLO "https://nodejs.org/dist/latest/node-v8.1.4-linux-x64.tar.gz"
 
echo -e "Downloading signature\n"
curl -SLO "https://nodejs.org/dist/latest/SHASUMS256.txt.asc"

echo -e "Verifying signatures\n"
gpg --verify SHASUMS256.txt.asc

echo -e "Verifying tarball integrity..\n"

if grep node-v8.1.4-linux-x64.tar.gz  SHASUMS256.txt.asc | shasum -a 256 -c ; then
    echo -e "Good signature\n"
else
    echo -e "Bad signature!\n"
    exit
fi

For a python example, check Justin chi's patch which uses a sha256 checksum to validate an ubuntu ISO download. He wrapped the logic into its own function `safecurl`

def get_from_safecurl(cache, package):
    filename = package.get("name")
    localfile = cache + "/" + filename
    cmd = "curl --connect-timeout 10 -o " + cache + "/"
    cmd += filename + " " + package.get("url")
    os.system(cmd)
    cmd = "sha256sum " + localfile + "|cut -d ' ' -f 1"
    shasum = os.popen(cmd).readlines()
    if (shasum[0][0:-1] != package.get("sha")):
        print "shasum error %s and %s" % (shasum[0], package.get("sha"))
        sys.exit(1)
    else:
        print "shasum pass!"
  - name: ubuntu-16.04-server-amd64.iso
    description: "Ubuntu ISO of each host for provisioning"
    get_method: safecurl
    url: http://releases.ubuntu.com/16.04.2/ubuntu-16.04.2-server-amd64.iso
    sha: 737ae7041212c628de5751d15c3016058b0e833fdc32e7420209b76ca3d0a535

Use https

If the hosting site provides TLS (using a up to date signed certificate), make use of it! A TLS / https connection will help mitigate against MiTM attacks.

Curl | Bash

Another commonly used method to leverage externally hosted scripts, is to curl a script and pipe it through bash, sometimes coupled with sudo.

curl http://somedomain.com/install.sh | sudo bash

What's wrong with this?

The problem here is that a user is allowing scripts to run directly on their machines, right from the internet, sometimes as root (when using sudo bash).

If we then consider the previous example of where infrastructure has been hacked, and then a scenario where a hacker replaces `install.sh` with their own script, then we can see how dangerous this can be.

For example, `install.sh` script could be swapped out for a script which still installs the desired software, and yet at the same time silently installs malware or a trojan on the machine, and then self deletes the nefarious line from the script.

You now have a machine infected with a trojan and no evidence left for the user to realise their machine is compromised. 

OK, so how do I do this in a more secure way?

Pretty much the same as before, use some sort of strong hash checksum verification to insure the script has not been tampered with. For an example of how to do this pro-grammatically, check out qi liang's work in progress patch for quickstart.sh

Use https

Same as before! If the hosting site provides TLS (using a up to date signed certificate), make use of it!

Summary

By putting in these integrity verification checks, we protect our end users from possible attack vectors and we also save 'brand damage' to our community should a breach connected to our scripts ever occur.

Anteater will continue to flag these insecurities, so its recommended to start to patch your code in advance, as for F release, patches will be blocked that contain the above illustrated risks. I will also flag up the more dangerous instances to release and ask them to consider if we should include these risks in an OPNFV release that will be consumed by end users.

 

  • No labels