HTML & PHP - HTML code simply not read

Asked

Viewed 399 times

2

I have following code on the part of PHP does not present any error, the page appears blank and does not show the HTML code.

<?php
include("config.php");
if($_GET['key'] && $_GET['reset'])
{
  $email=password_hash($_GET['key'],PASSWORD_DEFAULT);
  $pass=password_hash($_GET['reset'],PASSWORD_DEFAULT);
  $sql=mysqli_query($conn,"SELECT email, password FROM registo where email='$email' and password='$pass'");
  if(mysqli_num_rows($sql)==1)
  {
    ?>
<html>
    <form method="post" action="update_newpassword.php">
    <input type="hidden" name="email" value="<?php echo $email;?>">
    <p>Enter New password</p>
    <input type="password" name='password'>
    <input type="submit" name="submit_password">
    </form>
    </html>
    <?php

  }
}
?>
  • Place these two lines at the beginning of the script: ini_set('dispaly_errors', true);error_reporting(E_ALL); see if there are any errors.

  • There is no error. What exists is a mistaken use of cryptography. The password_hash until version 7.1 is only Bcrypt. It generates a different (and theoretically unique) salt for each time. So when you use it to give the INSERT he will save $(algo)$(dificuldate)$(salt [primerios 16 caracteres, salvo engano])(hash da senha). Hence the verify_password works, because it generates the input password again with the same salt and then compares. However do what you are doing, using a SELECT is impossible because the new $email will be different from $email that is there

  • but PHP does not present any error, the HTML code simply does not appear!

  • the page appears blank

  • Appears blank because it does not find SELECT less (or more) than a line. Create a else in the if(mysqli_num_rows($sql)==1) and you’ll see this. Of a var_dump(mysqli_num_rows($sql));

  • Is passing key and reset to url?

  • Inkeliz did what you said and appeared the following: int(0)

  • Maurivan this is my link: $link="<a href='http://unn-w17015779.newnumyspace.co.uk/reset.php?key=". $email." &reset=". $pass." '>Click To Reset password</a>";

  • @Dianamadeira Precisely, he does not find because Bcrypt always generates a different hash, if it always generates something different as you want to think what is equal to it?! I’ll post an answer explaining that.

  • ok hold on Inkeliz

Show 5 more comments

1 answer

5

The problem is logical and predictable by the behavior of Bcrypt. I will try to pass a basic of the behavior of Bcrypt.

But, see that do this:

<?php

$senha = "a-mesma-senha";

echo password_hash($senha,PASSWORD_DEFAULT);

Will return:

$2y$10$l1Ka5O0C9oYxyY./MvA5YOH1JBTjcY9qTefOLUrZMZ8R4H8kR3UmO

But the same code will return:

$2y$10$J.eVvzGeh4FQh9uHb8Exz.U9jfn8hJhXs58bvdBYITkLfjLAJp0aK

And without changing anything also returns:

$2y$10$VFXgZFjjRLqeQvGIdeAtiuQR8jt1x.6wiz/L4dSBWC5w8fUbWwgDu

See for yourself, click on "Execute Code" several times and always the result will be different


This is self-explanatory. When you do the INSERT you insert for example:

$2y$10$l1Ka5O0C9oYxyY./MvA5YOH1JBTjcY9qTefOLUrZMZ8R4H8kR3UmO

But when you do it again you try to search for, in the SELECT:

$2y$10$VFXgZFjjRLqeQvGIdeAtiuQR8jt1x.6wiz/L4dSBWC5w8fUbWwgDu

Who are obviously different and you won’t find them.

This set of codes with $ in between represent:

$<algo>$<dificuldade>$<sal (22 caracteres)><senha (31 caracteres)>

Only the title of curiosity and so that you knew how this works note that if you do this:

// Não utilize isto em produção!

// Gera o BCrypt
$hashUm = password_hash('senha', PASSWORD_DEFAULT);

// Obtem o salt da hash gerada (primeiros 22 caracteres após o último $):
$salt = substr(substr($hashUm, strrpos($hashUm, '$')), 1, 22);

// Gera um nova senha COM O MESMO SALT:
$hashDois = password_hash('senha', PASSWORD_DEFAULT, ['salt' => $salt]);


if($hashDois === $hashUm){
echo 'Funcionou';
}

Do not use the above code for obvious security reasons.

Why does the above code work even generating twice? Because it is the same salt (the same difficulty and the same algorithm), so the same hash will result, this is like the verify_password works.

This is "exactly" what happens when using the password_verify(), it gets salt from the hash and then encrypts the input with the same salt and checks, but logically with side-Channel protections and the like.


The difference between Bcrypt/PBKDF2/Argon2i/Scrypt (...) against SHA256, MD5, SHA-1 (...) is precisely that they all have difficulty adjustment and also a salt, the salt in specific makes that identical passwords are not equal, see this publication also, as you can easily see above.


How to solve the problem:

Simple, first a value should be fixed for both sides, it should be "plain text", unencrypted.

For example:

$tokenPlanoComum = unpack('H*', random_bytes(128))[1];

$tokenSecretoCliente = unpack('H*', random_bytes(32))[1];
$tokenSecretoBanco = password_hash($tokenSecretoCliente,PASSWORD_DEFAULT);

You will save in the database the following information:

$tokenSecretoBanco 
$tokenPlanoComum

You will send the customer the information:

$tokenPlanoComum
$tokenSecretoCliente

Then to give the SELECT you will get via the $tokenPlanoComum, in this way, for example:

SELECT * FROM tabela WHERE tokenPlanoComum = "$tokenPlanoComum"

Then after SELECT compare the information that the client sent (from the URL) to the database:

if(password_verify($_GET['tokenSecretoCliente'], $tabela['tokenSecretoBanco'])){
// Tudo certo!
}

Remember, if applicable, to set an expiration time to prevent you from using the same token after long time.

Because this is efficient?

If there is a fault in your system that allows you to get the information from the table (example a Read-Only SQL Injection), one of them is encrypted and only the client has the possession, so it will still be safe since it will need both correct. ;)

Because this works?

Because there is a common ground where it is immutable and will always be the same for both sides.

  • Inkeliz See if you can be right, but that’s certainly not what makes my HTML code appear or not, because my doubt here was this, it was the fact that the HTML code did not appear. eeu believe that the problem is in the if before

  • @Dianamadeira, this is obvious. The mysqli_num_rows returns the number of rows that the mysql query got. If Mysql cannot find the information it will result in a num_rows worthwhile 0, after all it found 0 lines. Mysql will not find for the reason I said above. If it returns 0 he will be different from 1 and as a consequence HTML will not appear. I assumed I would know the usefulness of mysqli_num_rows, which is to inform the number of lines obtained by the previous query. The reason for being 0, that’s what I said above.

  • 1

    Perfect answer. I would ask more in the future when I deploy my recovery system and, luckily, I found your answer. Fully functional in my tests. Thank you!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.