OK I have this code to send an email account verification link
$verifyemail = $clean['email'];
$to = $verifyemail;
$subject = 'Virtual Pierz Close | Verify Your Account';
$message = "Thanks for registering with VPC, on clicking the verification link below, your account will be confirmed, you can then go ahead buy Virtual Properties, donating £5 each time to the worthwhile charity.
http://www.cambrianvacation.co.uk/vpc/registered.php?
email='$verifyemail'&hash='$hash1' ";
$headers = 'From:noreply@cambrianvacation.co.uk'; // Set from headers
mail($to, $subject, $message, $headers);
And then I have this code, that is trying to activate the account by setting active = 1 in the database, which will then be part of the access control logic at login, without active = 1, there is no login, amongst other protection
if(isset($_GET['email']) && !empty($_GET['email']) AND isset($_GET['hash']) && !empty($_GET['hash'])){
// Verify data
$accountemail = $_GET['email'];
$accounthash = $_GET['hash'];
}
$accountActive = 1;
$notactive = 0;
$username = '';
$password2 = '';
$username = 'xxxxxxx';
$password2 = 'xxxxxxx';
$db1 = new PDO('mysql:host=localhost;dbname=xxxxxxxxxxxxx', $username, $password2, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
$db1->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$db1->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try{
$search = $db1->prepare("SELECT email, hash, active FROM users WHERE email = :email AND hash= :hash AND active = :active");
$search->bindParam(':email', $accountemail);
$search->bindParam(':hash', $accounthash);
$search->bindParam(':active', $notactive);
$search->execute();
$colcount = $search->columnCount();
}catch(PDOException $e) {
$e->getMessage();
}
print_r($colcount);
if($colcount === 3){
//try{
$update = $db1->prepare("UPDATE users SET active=:active WHERE email=:email AND hash=:hash AND active = :active");
$update->bindParam(':active', $accountActive);
$update->bindParam(':email', $accountemail);
$update->bindParam(':hash', $accounthash);
$update->bindParam(':active', $notactive);
$update->execute();
//}catch(PDOException $e) {
// $e->getMessage();
//}
However I cannot get the active column to update.
I’ve also thought about using the GET[’email’] could be subject to semantic url attacks, however the logic won’t activate the account without the matching hash, which is randomly generated with crypt()………
If anyone can see any security holes in the code, please tell me………
There really is no reason to make two separate queries here. Why not just have one query to update the record based on hash and email and active = 0? If the count of modified rows = 1, then you had a success, else you had a failure. You probably don’t care why it failed, as it would be bad from a security perspective to indicate back to the user why update failed (i.e. bad email, bad hash, already active user, etc.).
That being said, your problem actually lies in the fact that your update uses
?style bindings, while you are usingbindParam()with:paramstyle bindings. This won’t work since those values are not present in the prepared statement.So just use this one single query:
Obviously if you think you are going to change the value for active/non-active then feel free to use a parameter for those as well, but my guess is you would want to treat that as a boolean-style tinyint field with only allowable values of 0 and 1, so there is really no point in having the parametrization there.