1

I am generating a password hash that I would like to base on user input for use later in the script. I have tried variations on the syntax for the bash variable in the following:

#!/bin/bash

printf "Enter password:"
read pw

php -r 'echo password_hash("$pw", PASSWORD_DEFAULT, [ "cost" => 11 ]) . "\n";'

I get the correct hash but only after I get an undefined variable warning.

When I put the variable in single quotes '$pw' and then input the password as "password" or 'password' I do not receive the error.

How can I pass a bash variable to a php command or otherwise assign it to a php variable within a bash script without the undefined variable error message?

2 Answers 2

2

Passing variables via the environment is the way to go (because the password will never be accessible to more processes or users than necessary, in contrast to passing it via php's command line).

This should be done with the export builtin for POSIX compliance. Alternatively, the Bash-only declare -x can be used as well.

printf "Enter password:"
read pw

# export pw to the environment:
export pw

# the process executing your php program reads pw from the
# environment that it inherited from its parent process:
php -r 'echo password_hash($_SERVER["pw"], PASSWORD_DEFAULT, [ "cost" => 11 ]) . "\n";'

Note that the population of superglobal arrays depends on the value of variables_order in your PHP configuration (The S character must be in this setting's value to populate $_SERVER).

Sign up to request clarification or add additional context in comments.

Comments

1
php -r 'echo password_hash("$pw", PASSWORD_DEFAULT, [ "cost" => 11 ]) . "\n";'

A single-quoted string in Bash does not do variable expansions, so you're literally passing the string $pw to PHP to parse, and since it doesn't exist you get a warning from PHP. The hash you get back is likely of the empty string, not the string you want. Try replacing php -r with echo in your script to see exactly what's being passed to php.

The suggestion to export the variable is a good option for security reasons (though you should use $_ENV, not $_SERVER), however in the general case (i.e. not a password) it's not necessary. Properly quoting the string so that the variable is evaluated in Bash is easy to do once you understand Bash's quoting semantics (which admittedly can be confusing).

For this case it should be sufficient to simply invert the single and double quotes in your string:

php -r "echo password_hash('$pw', PASSWORD_DEFAULT, [ 'cost' => 11 ]) . '\n';"

5 Comments

this is more along the lines of what I was looking for/confused about. Thank you for the explanation. I appreciate Michael Jaros' answer as well though!
@DonPeat: $_ENV is not populated in many environments by default (this depends on the value of variables_order). And passing the password via string substitution makes it visible to other users on that machine via the command line, which is not the case when passing it via the enviornment, so this could be a security issue in some environments.
@MichaelJaros This is an internally run script, so not necessarily worried about that per se but certainly good to know. So is it better practice, generally speaking, to export to environment?
@DonPeat: Secrets on command lines can be a problem (e.g. /proc/cmdline, shell history). Passing the secret via environment is better, but this was a real problem especially on older Unixes and should still be considered potentially dangerous as at least all child processes have access to the secret. Resetting the variable after starting a child does not solve this problem, as the child with the secret can have children as well. Secrets should be stored in files secured via permissions instead or passed via IPC (pipes, sockets, ...) between processes.
@MichaelJaros for passwords specifically, I agree with you, though the problem underlying the question is simply mis-quoting in Bash.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.