-2

I'm using password_verify with two arguments, the hash value that's stored in the Database, and the actual password that the user enters. Here's the code:

$pass = filter_input(INPUT_GET, 'password', FILTER_DEFAULT);
// connecting to the database and executing query, the password is stored in $dpass

  if(password_verify($pass,$dpass))
     echo "Hello User " .  $dname;

else
  echo "Login incomplete";

Now just for clarification:

  • Password column in my database is a varchar(256)
  • The same filtering function that happens during signin is used during signup
  • I tried to password_verify() my password with the same hash value that appeared during signup without using the database returned value (echo hash, copy & paste)
  • I echo both hash value and entered password value, they are both correct
  • I tried both BCRYPT and DEFAULT and they both weren't verified correctly

What could be the issue?

  • 2
    Was the password hash in the DB created with `password_hash`? Just making sure... – Don't Panic Nov 02 '18 at 22:12
  • 1
    If `password_verify($pass, password_hash($pass, PASSWORD_DEFAULT))` "works", then the problem is that $dpass does not contain what is expected - including not being generated correctly (so what *does* it contain, and why is it not as expected?). If it "doesn't work" then *another* line is causing the observed behavior. Both of these outcomes allow focusing on a refined problem set. – user2864740 Nov 02 '18 at 22:13
  • @Don'tPanic yes of course – user2196985 Nov 02 '18 at 22:17
  • @user2864740 Thank you so much! I'm looking for suggestions like this to help me better identify the problem, I'll try it and comment my results – user2196985 Nov 02 '18 at 22:18
  • You shouldn't filter passwords and you may be doing more harm than good. – Funk Forty Niner Nov 02 '18 at 22:19
  • 1
    Yeah, you'd think "of course", but I've seen quite a few questions where that wasn't the case, so I always ask. No offense – Don't Panic Nov 02 '18 at 22:19
  • Is `$pass` plaintext? The first argument should be plain text. Sometimes people hash the first argument. – ArtisticPhoenix Nov 02 '18 at 22:20
  • We also don't know how it is you're querying or the source of the inputs. – Funk Forty Niner Nov 02 '18 at 22:20
  • @FunkFortyNiner I agree, but I think that `FILTER_DEFAULT` means the filter doesn't do anything. It's the same as `$pass = $_GET['password']` – Don't Panic Nov 02 '18 at 22:21
  • @Don'tPanic No Offense taken, thanks for your suggestion! – user2196985 Nov 02 '18 at 22:24
  • @Don'tPanic and I agree with you also, I just looked at the [manual](http://php.net/manual/en/function.filter-input.php). *"If omitted, FILTER_DEFAULT will be used, which is equivalent to FILTER_UNSAFE_RAW. This will result in no filtering taking place by default."*. Yet, just in case they decide to later, it could have adverse effects. – Funk Forty Niner Nov 02 '18 at 22:24
  • All I ever do is `trim()` the passwords, as it's never stored in plaintext (nor displayed) so there is no reason to filter it. The hashing will take care of any surprises. I just trim it because it's common to pick up a space from pasting out of email. – ArtisticPhoenix Nov 02 '18 at 22:27
  • Heh; that filter *is* at fault after all. If you `echo $pass = filter_input(INPUT_GET, 'password', FILTER_DEFAULT);` you will see nothing or `$pw = "password"; echo $pass = filter_input(INPUT_GET, $pw, FILTER_DEFAULT);`. Get rid of that filter, you're trying to verify *nothing*. – Funk Forty Niner Nov 02 '18 at 22:29
  • @FunkFortyNiner the second param should be a string specifying the index in $_GET, so I think that's correct. However, I would _hope_ that we'd be looking at $_POST... – Don't Panic Nov 02 '18 at 22:32
  • @Don'tPanic I tried this `$_GET['xxx'] = "asdfasdf"; echo $pass = filter_input(INPUT_GET, 'xxx', FILTER_DEFAULT);` and I get nothing back. – Funk Forty Niner Nov 02 '18 at 22:34
  • @FunkFortyNiner It won't work that way. It actually has to be passed in the URL. I'm not sure how it does work, but it won't work if you set $_GET in the script. *edit* Yeah, like that note ;-) – Don't Panic Nov 02 '18 at 22:41
  • [See this note](http://php.net/manual/en/function.filter-input.php#99124) *"Note that this function doesn't (or at least doesn't seem to) actually filter based on the current values of $_GET etc. Instead, it seems to filter based off the original values."*. @Don'tPanic OP needs to update their post. – Funk Forty Niner Nov 02 '18 at 22:41
  • @Don'tPanic See their answer and [my comment](https://stackoverflow.com/questions/53126401/password-verify-is-always-returning-false#comment93148152_53126705) under it. – Funk Forty Niner Nov 02 '18 at 22:55

1 Answers1

0

Thank you everyone for your answers, after I run my echo $pass through every line I noticed that at some point in the code it changes from its original value to a different one, I checked it again and apparently the variable $pass is used in dbconnect.php file that is included throughout the code which has my database configurations and setup, it uses the variable $pass to store the database password, that's what altered the value of the password, I fixed $pass to $usrPass and everything worked fine.

So for anyone in the future facing this issue and seeing this, here are the most common mistakes that lead to password_verify() not to work:

  • using double quotes in storing the hash value ($hash = "$2$ds$fdajja..."; using double quotes makes PHP read $2 $ds and $fdajja... as indivisual variables which will probably cause your code to break, USE SINGLE QUOTES INSTEAD.
  • echo both hash and entered values and make sure they match the ones that were inserted and generated during password_hash()
  • if the database value was different (the hash), make sure the type of its column is varchar(256), the hash is usually 60 characters long but the hashing function is frequently improved so that length may expand in the future.
  • if the entered value was different (the user password), make sure the filtering isn't corrupting the password value, also check if another variable has the same name as the one you're storing the password in
  • If password_verify($pass, password_hash($pass, PASSWORD_DEFAULT)) "works", then the problem is that $dpass does not contain what is expected - including not being generated correctly (so what does it contain, and why is it not as expected?). If it "doesn't work" then another line is causing the observed behavior. Both of these outcomes allow focusing on a refined problem set. Thanks to user2864740 for pointing that out.

EDIT: Guys the password filter function did nothing at all because there was nothing to be filtered anyway, for those of you who aren't familiar with it the function basically works Input parameters, it works with both GET and POST inputs, since I'm still doing the backend part I'm using GET for testing purposes.

  • you should have posted that in your question as asked. We/I would have picked up on that right away. Edit: which is why I voted to close as unclear. – Funk Forty Niner Nov 02 '18 at 22:53
  • everything you wrote, already exists in many duplicates. You didn't say anything new, so IMHO; this doesn't add anything special to what's already been asked. – Funk Forty Niner Nov 02 '18 at 22:56
  • Yeah I know it already exist in separate posts, I wanted to deleted the whole question but decided to wrap up all my research and experience with the issue in one answer to help others find their mistakes without all the hassle that I had. – user2196985 Nov 02 '18 at 23:05
  • 1
    This is somewhat beside the point, but if you just changed the variable name and everything worked, it would seem (because you're using `INPUT_GET` in the filter) that the password is being sent in the url query string, which will expose the plain text password. – Don't Panic Nov 02 '18 at 23:06
  • I appreciate what you're saying and did by fixing yourself (\**2 thumbs up\**), but [my comment here](https://stackoverflow.com/questions/53126401/password-verify-is-always-returning-false/53126705?noredirect=1#comment93147651_53126401) was left unheard. In the future and for everybody's sake and their time I might add that a few was actually wasted, please post all relevant code and its source, that way there's no guesswork. Don't take this as an attack, it's just a pro Stack tip :) @user2196985 – Funk Forty Niner Nov 02 '18 at 23:08
  • I agree with @Don'tPanic here on passing (sensitive) data through a URL. There are middle-men out there and at best, use an SSL socket. Using filtering on this is pointless for a few reasons, one of which I mentioned in [this comment](https://stackoverflow.com/questions/53126401/password-verify-is-always-returning-false/53126705?noredirect=1#comment93147632_53126401). So, why the filter to begin with? `password_verify()` takes this into account and your database won't be compromised. Passwords such as `--DELETE;
    blah blah 123'` are considered to be valid. Please remember that.
    – Funk Forty Niner Nov 02 '18 at 23:12
  • @Don'tPanic I'm doing it for testing only, testing different values is much easier and faster like this, I'll surely change it in the final product :) – user2196985 Nov 02 '18 at 23:14
  • @FunkFortyNiner Sorry I missed that one, I didn't include my query part because I already did my testing there and there was no issue in restoring the data, so I just thought the code would be easier to read without all the unnecessary parts, and don't worry I'm not taking it as an attack, I don't ask a lot in the community and from what I saw you seem like an old pro user, so I'll take your word for it, thanks for the tip :) – user2196985 Nov 02 '18 at 23:18
  • @FunkFortyNiner as I told him it's just for testing, and I already had that `--DELETE;
    blah blah 123'` issue covered as I'm using PDO for my Database connection (->prepare and ->execute) But thanks for pointing it out!
    – user2196985 Nov 02 '18 at 23:21
  • 1
    @user2196985 Oh well, *"c'est la vie"* :) I'm glad that you're learning and to keep on going and using good and safe practices. *Cheers* – Funk Forty Niner Nov 02 '18 at 23:33