Domanda

I have created a login and registration system using php. I intend to use nonces to prevent the replay attack. So far what I have is, generating a random number using (uniqid(mt_rand(),true)); and then store this on the database, and pass the same data in a hidden field to the client end, and then send it back to the server side, when the login button is clicked. if it matches the on in the database, the user is redirected to the private page, and then a new nonce is generated and updated in the database.

This is how i intend to implement it. But I'm some how not totally sure of the implementation.

È stato utile?

Soluzione

<?php
session_start();
//Check nonce against session
if(isset($_POST) && $_POST["nonce"] === $_SESSION["csrf"]){
    //save data
    //redirect
}
//generate new nonce for form
$_SESSION["csrf"] = uniqid(mt_rand(),true);
?>
<form method="post" action="<?php echo $_SERVER['REQUEST_URI'] ?>">
    <input type="hidden" name="nonce" value="<?php echo $_SESSION['csrf']; ?>"/>
    <!-- other form fields -->
    <!-- submit button -->
</form>

Altri suggerimenti

you can use php sessions for this purpose. Session is a more conventional and useful approach for login purposes. After recieving form data validate that data and then storing that data in session will work.

uniqid(mt_rand(),true) is not appropriate for a nonce value:

http://php.net/manual/en/function.mt-rand.php

It uses a random number generator with known characteristics using the » Mersenne Twister, which will produce random numbers four times faster than what the average libc rand() provides.

http://php.net/manual/en/function.uniqid.php

his function does not generate cryptographically secure values, and should not be used for cryptographic purposes. If you need a cryptographically secure value, consider using random_int(), random_bytes(), or openssl_random_pseudo_bytes() instead.

random_bytes and openssl_random_pseudo_bytes return characters that are not printable, but you can convert them to hexadecimal representations:

bin2hex(random_bytes($length))

Make sure the nonces cache storage is not available to other users. For instance, PHP sessions are usually saved as files inside the /tmp folder. If you're using SESSIONS, override their default behaviour:

http://php.net/manual/en/class.sessionhandlerinterface.php

Anyway, I developed and released a nonces library:

This is how you could create a form with a nonce using the library:

<?php
require __DIR__ . '/../vendor/autoload.php';

$form = new \pedroac\nonce\Form\NonceForm(
    'token',
    new \pedroac\nonce\NoncesManager(
      new \Symfony\Component\Cache\Simple\PdoAdapter($pdo)
    )
);
if ($form->isSubmittedInvalid()) {
  /**
   * handle failure
   */
}
if ($form->isSubmittedValid()) {
  /**
   * handle the success
   */
}
?>
<form method="POST">
    <?= new HtmlNonceField($form) ?>
    <input type="submit" name="myform" value="Submit" />
</form>

You could also do it like this:

<?php
require __DIR__ . '/../vendor/autoload.php';

$manager = new \pedroac\nonce\NoncesManager(
    new \Symfony\Component\Cache\Simple\PdoAdapter($pdo)
);
$lastNonceName = $_SESSION['nonce_name'];
if(isset($_POST[$lastNonceName]) && $manager->verifyAndExpire($lastNonceName, $_POST[$lastNonceName])) {
    // handle success
}

$nonce = $manager->create();
session_start();
$_SESSION['nonce_name'] = $nonce->getName();
?>
<form method="post">
    <input type="hidden"
           name="<?= htmlspecialchars($nonce->getName()) ?>"
           value="<?= htmlspecialchars($nonce->getValue()) ?>" />
    <input type="submit" name="myform" value="Submit" />
</form>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top