1

I am trying to implement this flow:

  1. User signs up with email address
  2. User receives email with validation link
  3. User follows link to a page asking to set a password
  4. User sets password

Here's the code I have so far:

$email = $_GET['email'];
$verification_code = $_GET['verification_code'];
$validation_message = "";
$self = htmlspecialchars($_SERVER["PHP_SELF"]);

if(isset($_POST['submit'])) {
    if ($_POST['password'] == "") {
        $validation_message = "Please enter a password";
        echo "<form id='verify-email-form' action='$self' method='post'><h1 id='set-password-input' class='h1-splash h1-password'>Choose a password</h1><input type='hidden' name='email' value='$email'><input type='hidden' name='verification_code' value='$verification_code'><input type='password' name='password' class='text-input' placeholder='Password'><button type='submit' name='submit' id='submit-input-splash'>Go!</button></form><p id='validation-message'>$validation_message</p>";
    }
    else {
        echo $_POST['email'];
        echo $_POST['password'];
    }
}
else {
    require 'connect.php';
    $sql = "SELECT * FROM users WHERE email='$email' AND verification_code='$verification_code' AND active='0'";
    $result = $con->query($sql);
    if ($result->num_rows > 0) {
        echo "<form id='verify-email-form' action='$self' method='post'><h1 id='set-password-input' class='h1-splash h1-password'>Choose a password</h1><input type='hidden' name='email' value='$email'><input type='password' name='password' class='text-input' placeholder='Password'><button type='submit' name='submit' id='submit-input-splash'>Go!</button></form><p id='validation-message'>$validation_message</p>";
    }
    else {
        echo "Invalid activation code.";

    }
}
?>

The URL is in this format: www.example.com/activate.php?email=name@example.com+verification_code=1234567890

I'm tripping up at the eventuality that a user presses submit without typing anything in the password field. It reloads the page to activate.php but without the variables in the URL, so the email address can't be submitted if the user then does type a password.

Is there a workaround for this, or a better way of structuring it?

Sebastian
  • 3,548
  • 18
  • 60
  • 95
  • Put the URL including the URL variables into the form's `action` attribute…!? – deceze Jan 24 '18 at 16:15
  • @deceze I've changed `action` to `$self?email=$email&verification_code=$verification_code`, but now the URL fails to load like that if I press submit without anything in the password field for a second time. Do I need to restate the variables again somewhere? – Sebastian Jan 24 '18 at 16:19
  • Be more specific. What does the URL you're cobbling together look like? Is it the same as your initial URL? – deceze Jan 24 '18 at 16:21
  • Yes, the URL is exactly the same. If I click submit without entering a password it loads the URL with my two variables. But if I click it again, it loads `www.example.com/activate.php`. – Sebastian Jan 24 '18 at 16:22
  • `+verification_code` that + sign should be an ampersand, unless that was changed now. – Funk Forty Niner Jan 24 '18 at 16:23
  • @FunkFortyNiner apologies, I fixed that in my own code but not on here. The problem outlined above persists – Sebastian Jan 24 '18 at 16:24
  • *"I'm tripping up at the eventuality that a user presses submit without typing anything in the password field."* - check for `empty()` then. – Funk Forty Niner Jan 24 '18 at 16:24
  • 1
    So eventually when it is live: `?email=' OR 1=1 LIMIT 1;--` will allow you to change the first users password (most likely an admin) - Read before going any further: [How can I prevent SQL injection in PHP?](https://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php) – Lawrence Cherone Jan 24 '18 at 16:24
  • "action='$self'" - don't do that. Even if you've escaped the data with htmlspecialchars, its not safe for injection here. Just omit the action altogether to set the URL for the form to the current URL. – symcbean Jan 24 '18 at 16:25
  • Odd that you tried to protect against tag injection via PHP_SELF but didn't worry about the SQL injection vulns. – symcbean Jan 24 '18 at 16:26
  • @symcbean thank you, this solved the problem – Sebastian Jan 24 '18 at 16:29

1 Answers1

0

You are sending those variables as POST and trying to read them as GET: $_GET['verification_code'];

Just change the form method to GET or read the variables as POST.

tomcontr
  • 98
  • 9