Search code examples
bashopensslcommand-substitution

Openssl return values in bash scripts


Openssl 3.0.2.15 on Ubuntu Server (current)

So, my forensics class was working on a problems I used for bash and we found a kind of strange thing. If you are trying to detect a valid password using a dictionary file, some words (that are not the password) result in an error (e.g. bad decrypt) and subsequently $? has a value of 1. Ok, that works on a test file. Correct password is found and $? == 0. But, when we ran that with a large file of dictionary words, an anomoly occurs: Some words, consistently (but with no pattern I can see) return 0. These are not the password but nevertheless...Now, at the command line, if I run the same exact command, it fails with 'bad decrypt' and $? == 1, but in the script, it returns 0.

It is consistent, the word(s) produce the same result regardless of where they are found in the dictionary file, they can be deleted and retyped into the file, but they always produce a 0 return instead of a 1 like most of the bad words do. This does include the actual password which provides a correct result as well. The correct password correctly decrypts the file but the false positives produce a file which is still encrypted despite them not actually working. So, my question is, any ideas why openssl might not throw the bad decrypt error when the password doesn't actually work?

echo "Current Pword is $pword"
$(openssl enc -aes-256-cbc -pbkdf2 -d -in $2 -out $3 -pass pass:$pword)
if [ "$?" -eq 0 ]
then
    echo "The password was found to be $pword \n"
    echo "$pword\n" >> pwords.out
    echo "The file was decrypted as $3\n"
    exit 0
fi

is the command in the bash script. Like I say, it works fine with the sample file and will find the correct password in the larger dictionary file but curious as to why it doesn't always think a bad password is "bad".

Per the request: The password for the file is "nitrification" words that generate false positives (sample): abies, abkar, bathylimnetic, cairds, dodecatoic, and the list goes on.

Some words that generate negative results: rabies, a, xnitrification, aaa, abalienation, abaton, and so on. I can't see a pattern.

Any comments are appreciated.

BASH script should identify a password for the file if one exists as indicated by openssl. Code works fine but produces many false positives.

Instead, it sometimes seems to think a word is the correct password even when it is not.


Solution

  • (0) This is not a programming or development issue and thus offtopic, but my information won't fit in comments. I will delete if appropriate.

    (1) script differs from command line: this should never happen. If you can isolate a complete example that shows this (encrypted input, password, exact command in script, and same command at commandline) with nonsensitive (i.e. test) data, please post it. (The encrypted data is binary, so to post it either use a protective format like base64 or hex, or a site that handles binary like pastebin.)

    (2) false positives: i.e. openssl enc -d sometimes has status 0, and does NOT say 'bad decrypt', even when password is wrong. THIS IS EXPECTED. enc -d has in general no way of checking or knowing that you use the wrong password, and thus key (and IV/nonce where applicable, which it is here). What it can check for some modes (including CBC) is that the decrypted (PKCS5/7) padding is valid, if padding is used which by default here it is (and in general for CBC it must be).

    When you decrypt with the wrong password and key (and IV/nonce) it produces what is for all practical purposes random binary data. (Effectively the same operation -- iterating a cipher primitive with an arbitrary key -- has actually been used as a Random Number Generator (RNG) or Random Bit Generator (RBG) in some designs, especially for high-volume low-end hardware where additional circuitry may cost significant money.) Approximately 1/250 of the time (to be exact, 1/2^8 + 1/2^16 + 1/2^24 ... 1/2^128) this random data will match the PKCS5/7 spec for valid padding and enc *CBC -d will 'succeed'; otherwise (about 99.6% of the time) enc *CBC -d will flag the error (although if the ciphertext was more than one block it will still write decrypted garbage for all but the last block).