Hacker News new | ask | show | jobs
by kseifried 781 days ago

    #!/bin/bash
    SHA512="485fe3502978ad95e99f865756fd64c729820d15884fc735039b76de1b5459d32f8fadd050b66daf80d929d1082ad8729620925fb434bb09455304a639c9bc87"
    # This line and everything later gets SHA512'ed and put in the above line.
    # To generate the sha512 simply: tail -n +3 [SCRIPTNAME].sh | sha512sum
    check_sha512() {
        # Compute the SHA512 hash of the script excluding the first two lines
        local current_sha=$(tail -n +3 "$0" | sha512sum | awk '{print $1}')
    
        # Compare the computed SHA512 hash with the predefined one
        if [[ "$current_sha" != "$SHA512" ]]; then
            echo "Error: SHA512 hash does not match!"
            exit 1
        fi
    }
    
    # Call the function to perform the hash check
    check_sha512
    
    # Rest of your script starts here
    echo "Script execution continues..."
The idea is simple: if the first line get's mangled (#!/bin/bash) the script probably won't execute at all. If the second line gets mangled than obviously the SHA512 comparison won't work (variable name or value).

Finally if the rest of the script gets mangled or truncated it won't SDHA512 the same and it'll cause the function to exit.

For bonus points you can add a check if first line of script is exactly "#!/bin/bash" as well.

1 comments

If the file is truncated after the function's closing brace, it will succeed but do nothing.

If the file is truncated in the middle of the word `check_sha512` it will try to execute a hopefully-not-existing command.

Wrapping in simple { braces } should fix this - if the brace is missing, you get a syntax error, and if present, you can execute the full thing, regardless of whether a trailing newline is available. This is admittedly bash-specific, so won't work for the linked script, but (subshell) doesn't cause too many problems

Using a function and checking the SHA don't really add anything after these fixes.

Checking the shebang is hostile to environments that install bash elsewhere.

An almost-working possibility would be:

  exec some-interpreter -c 'commands' "$0" "$@" ""
which will fail if the second ' is missing. The child interpreter can then check for later truncation by checking that at least 2 arguments were passed and the last one is an empty string. However, this is still prone to truncation before the -c.