M HYPE SPLASH
// updates

wget script, but pipe it to bash only if SHA256 of script matches one-liner

By Emily Wilson

wget -O - | bash runs the script automatically but due to possible (TLS) MITM attacks etc, this is not safe. Is is possible to construct a one-liner that downloads the script, but executes it only if it's hash matches the one specified in the one-liner? It would be nice if the one-liner would print something like Warning! Hash mismatch if hash check fails.

4

2 Answers

So you want to download and run .

For now I assume that you have its SHA256 hash stored locally in a file called my-sha256.txt. The file contains only the hash itself and a Unix-style linebreak character, so its size must be exactly 65 bytes. You can create it by simply running this:

sha256sum ORIGINAL_FILE.SH | grep -Eo '^\w+' > my-sha256.txt

How you distribute this hash file from your development machine to the client is not part of this answer (yet, you might clarify your question and ask me to update this part based on your detailed specifications).


The actual command your client has to run to download, verify, and on success execute the script could look like this:

t=$(mktemp) && wget ' -qO "$t" && if sha256sum "$t" | grep -Eo '^\w+' | cmp -s my-sha256.txt ; then bash "$t" ; else echo FAIL ; fi ; rm "$t"

Slightly shortened and ugly version without whitespace:

t=$(mktemp)&&wget ' -qO"$t"&&if sha256sum "$t"|grep -Eo '^\w+'|cmp -s my-sha256.txt;then bash "$t";else echo FAIL;fi;rm "$t"

Placed on multiple lines for readability:

t=$(mktemp) &&
wget ' -qO "$t" &&
if sha256sum "$t" | grep -Eo '^\w+' | cmp -s my-sha256.txt then bash "$t" else echo FAIL
fi
rm "$t"

If you want to directly provide the hash inside the command as string instead of reading from a file, simply use one of my original command versions above and replace the occurrence of my-sha256.txt with <(echo YOUR_HASH), inserting your real hash instead of the "YOUR_HASH" placeholder of course.

Explanation:

The script/one-liner first creates a temporary file using mktemp (uses the system's temp folder /tmp).
Then it uses wget to download your installation script from the specified URL and save it in the temp file.
Now we calculate its hash sum, filter only the hash value from the output of sha256sum and compare that to what we have stored in out my-sha256.txt.
If both hashes equal, we will invoke bash with our temporary script file as argument, else we echo FAIL or you could output a custom error message.
In the end we clean up by deleting our temporary file in both cases.


However, coming back to the problem of securely distributing the hash to verify the original script, this solution above will not help you much, as it solves one problem by creating another one of the same kind.

What you actually should do is to create a GPG key pair (and publish your public key to a keyserver), sign your script with it and offer the compressed signed binary for download. Then let the client verify and decrypt the script using gpg again and run it on success.

7

Since GPG fingerprints use insecure SHA-1 hash, here is a one-liner that allows authentication with unofficial SHA256 hash calculated from public key with

gpg --export <key ID> | sha256sum

command:

h="<SHA256 hash of exported public key>"; fp="<PGP key SHA1 fingerprint>"; f='key.pub'; gpg --keyserver pgp.mit.edu --recv $fp && gpg --export $fp > $f && if sha256sum $f | grep -Eo '^\w+' | cmp -s <(echo $h); then rm $f && wget -q && gpg --verify install.sh{.asc,} && bash install.sh; else rm $f; echo "ERROR: Signing key had invalid SHA256 hash"; fi;

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy