Sign up script security check - php

Hey guys, I have this sign up script and I'm using mysql_real_escape_string .I know prepared statements are safer but I'm just not experienced enough to use them, I just can't figure out how. Anyway here's the script:
<?php
$username=mysql_real_escape_string($_POST['username']);
$password=sha1($_POST['password']);
$password2=sha1($_POST['password_confirmation']);
$passcheck=$_POST['password'];
$todo=mysql_real_escape_string($_POST['todo']);
$email=mysql_real_escape_string($_POST['email']);
$fname=mysql_real_escape_string($_POST['fname']);
$lname=mysql_real_escape_string($_POST['lname']);
$gender=$_POST['gender'];
$class=$_POST['class'];
$section=$_POST['section'];
if(isset($todo) and $todo=="post"){
$status = "OK";
$msg="";
}
if(!isset($username) OR strlen($username) <3){
$msg=$msg."Username should be equal to or more than 3 characters long.<BR/>";
$status= "NOTOK";
}
if(mysql_num_rows(mysql_query("SELECT username FROM users WHERE username = '$username'"))){
$msg=$msg."Username already exists. Please try another one.<BR/>";
$status= "NOTOK";
}
if(mysql_num_rows(mysql_query("SELECT email FROM users WHERE email = '$email'"))){
$msg=$msg."E-mail is already in use. Please try again.<BR/>";
$status= "NOTOK";
}
if ( strlen($passcheck) < 3 ){
$msg=$msg."Password must be more than 3 charactors long.<BR/>";
$status= "NOTOK";
}
if ( $password <> $password2 ){
$msg=$msg."Passwords are not identical.<BR/>";
$status= "NOTOK";
}
if(!eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", $email)){
$msg=$msg."The email is not a valid email.<br/>";
$status="NOTOK";
}
if($status=="NOTOK"){
echo '<div class="statusmsg">'.$msg.'<br/><input class="submitButton" type="button" value="Retry" onClick="location.href='."'signup.php'\"></div>";
}
else {
$hash = md5( rand(0,1000) );
$hash = mysql_real_escape_string($hash);
if(mysql_query("insert into users(username,password,email,fname,lname,hash,gender,class,section) values('$username','$password','$email','$fname','$lname','$hash','$gender','$class','$section')")or die (mysql_error ())){
echo '<div class="statusmsg">Welcome, You have successfully signed up. Please check the verification e-mail sent to you.</div>';
$to = $email;
$subject = 'Signup | Verification';
$message = '
Thanks for signing up!
Your account has been created, you can login with the following credentials after you have activated your account by pressing the url below.
------------------------
Username: '.$username.'
------------------------
Please click this link to activate your account:
<div id="header">
<h3>JMToday > Sign up</h3>
</div>
http://www.JMtoday.com/verification.php?email='.$email.'&hash='.$hash.'
';
$headers = 'From:noreply#JMtoday.com' . "\r\n";
mail($to, $subject, $message, $headers);
}
else {
echo "Database problem, please contact site admin";
}
}
?>

The user will never see the "database problem" message, as the script will die() out if the query fails. As well, you're embedding HTML into the message, but are not building a proper HTML-format email. Some mail clients may be smart enough to figure out there's HTML and render it as such, but that's just luck.
The hash you generate is limited to generating only 1001 hashes. Given the birthday paradox, after 38 people sign up, the odds of a collision are 50%. After 100 people, the odds are 99.29%. Instead of hashing a random number, do something like:
$hash = md5(serialize($_POST) . $some_other_stuff_in_case_POST_is_empty);

Related

MySQL replaces my PHP input data

So, I've been trying to create a Signup/Login process using PHP and MySQL. I created a Signup form, and a handling page. Then I tred it out, set the email as a#a.com and password as MyPassword.
I then checked the database and got surprised. The email was correctly inputted, alright, but the password wasn't! It was one of the passwords that I used to test before, and it is a pretty personal one.
Every time I tried it again, the same thing happened. The password was always changed to my personal one whenever I signed up.
The problem is that, in my code, I don't have that personal password, anywhere. I only used it to test my signup flow once, and now it's stuck to my database!
Here, I registered using test credentials. The password is asd and it's obviously 3 letters long.
But when I check the database, I see the following. Even though I edited the password so you can't see it, it's still obvious it's more than 3 letters long.
Is this some kind of MySQL over-writing thing, that I just don't know about yet?
Here is the full code of the SignUp Page (Might be a little long, bear with me):
<?php
session_start();
$firstName = $_POST['firstName'];
$lastName = $_POST['lastName'];
$email = $_POST['signUpemail'];
$password = $_POST['signUppassword'];
include("mysql_base.php");
echo "Preparing MYSQL Statement...<br>";
echo "<script>";
echo "firstPart()";
echo "function firstPart() {";
echo "document.write('Starting to process MYSQL Statement...')";
echo "window.setTimeout(secondPart(),2000)";
echo "}";
echo "function secondPart() {";
echo "document.write('Starting to stop processing MSYQL Statement...')";
echo "}";
echo "</script>";
echo "Started to proccess...<br>";
$sql = "INSERT INTO pages_accounts (email, pass, firstname, lastname, confirm) VALUES ('".$email."','".$password."','".$firstName."','".$lastName."','0')";
if ($conn->query($sql) === true){
echo "<b>SIGNUP SUCCESS</b><br>";
echo "SUCH HAPPINESS. WOW. MMM.<br><br>";
echo "--Check your mail for a confirmation email. Check SPAM too!--";
$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";
$headers .= 'From: FoxInFlame Pages<pages#foxinflame.tk>' . "\r\n";
$message = "
<html>
<body>
<center>
<div style='background-color:orange'><h1>Confirm your Account</h1><br><h3>At FoxInFlame Pages</h3></div>
You seem to have registered for an account at FoxInFlame Pages. Now please click on the following link to complete your registration, and start creating amazing websites!<br><a href='http://www.foxinflame.tk/pages/confirm.php?id=".$conn->insert_id."'>Click Here</a>
</center>
</body>
</html>
";
mail($email, "[CONFIRM] Account on FoxInFlame Pages", $message);
} else {
echo "MUCH SADNESS. SUCH DEPRESSION. FAIL ERROR. NO RETURN.";
echo "Error: ".$sql."<br>".$conn->error;
};
?>
Your problem will be in include("mysql_base.php");. That file will be setting $password for it's own internal use, which is overwriting the $password variable that you get from $_POST;
2 options to get around this:
1 - Open the database connection first.
<?php
session_start();
include("mysql_base.php");
$firstName = $_POST['firstName'];
$lastName = $_POST['lastName'];
$email = $_POST['signUpemail'];
$password = $_POST['signUppassword'];
2 - Use different variable names:
<?php
session_start();
include("mysql_base.php");
$signup_firstName = $_POST['firstName'];
$signup_lastName = $_POST['lastName'];
$signup_email = $_POST['signUpemail'];
$signup_password = $_POST['signUppassword'];
Aside from this, the password field on the sign up page doesn't have name="signUppassword", and you have no SQL Injection protection.
On your page I see:
<input style="color:white" type="password" name="password" required="" autocomplete="off">
So your input name is password
But in your code you are trying to get signUppassword:
$password = $_POST['signUppassword'];
Do you have some transformation somewhere ? javascript?

Trouble matching login password with stored hashed password in database

I am new to PHP and MYSQL and am working on a registration/login form project to build up my knowledge but I am a bit stuck, so hope you can help.
I have a database on PHPMyAdmin and my registration form searches to see if the email address already exists if not to insert all the information into the database. This works fine. I also have a login form which searched for the email address and password to see if they matched any in the database, if so to log in. This worked fine.
My issue came when I started to learn about password salts/hashing. I can still register okay but when I try to login with details already in the database it doesn't seem to match the passwords up to allow me to log in.
register.php
<?php
error_reporting(E_ALL);
require 'db_connect.php';
// Stores the information submitted from the form via the $_POST variable
// if the request method in the form is POST then execute the following code (read the submitted information - send the email and redirect to the header location
// if it is NOT POST then it will skip this code block and show blank contact form
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$fname = trim($_POST["fname"]);
$lname = trim($_POST["lname"]);
$cname = trim($_POST["cname"]);
$email = trim($_POST["email"]);
$pass1 = trim($_POST["pass1"]);
$pass2 = trim($_POST["pass2"]);
// VALIDATIONS
// All required fields must be entered
if ($fname == "" OR $lname == "" OR $email == "" OR $pass1 == "" OR $pass2 == "") {
$error_message = "You must fill in all the required fields.";
}
// password must contain 6 characters min
if (strlen($pass1) < 6) {
$error_message = "Password must be at least 6 characters long";
}
//passwords must match each other
if ($pass1 != $pass2) {
$error_message = "Passwords do not match";
}
// hash and salt password - PASSWORD_DEFAULT uses the php default hashing algorithm -
// cost is the expense used to generate the hash (higher the number the more secure but slower the page load)
$password_save = password_hash($pass1 . SALT , PASSWORD_DEFAULT, array('cost' => 10 ));
// if there's not a previous error message run a database query to look if the email address entered matches any already in the database.
if (!isset ($error_message)){
$query = "SELECT * FROM registration_tbl WHERE email = '".$email."'";
$query_run = mysqli_query($dbc, $query);
// if the query locates more than 0 (i.e 1+) records with matching email addresses then echo out the error
// else insert all new form data in to the database and echo a success message
if (mysqli_num_rows($query_run)>0) {
$error_message = "Email Address ".$email." is already registered";
} else {
$sql = "INSERT INTO registration_tbl (first_name,last_name,company_name,email,password,reg_datetime) VALUES ('".$fname."','".$lname."','".$cname."','".$email."','".$password_save."', NOW())";
$query_run = mysqli_query($dbc, $sql);
echo "Registration Successful";
}
}
login.php
<?php
error_reporting(E_ALL);
require 'db_connect.php';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$email = trim($_POST["email"]);
$pass = trim($_POST["pass"]);
// VALIDATIONS
// both fields must be entered to log in
if($email == "" OR $pass == "") {
$error_message = "Both fields must be completed ";
}
$hashandsalt = password_hash($pass . SALT, PASSWORD_DEFAULT, array('cost' => 10 ));
// if no error message is set - send a query to the database for all records in the registration_tbl where the email matches one in the database
// if the query returns less than 1 record (i.e no matches in the database) show error message
// else if found in the database save the login details to session variables and then
// redirect to the logged-in.php page
if (!isset ($error_message)) {
$query = "SELECT * FROM registration_tbl WHERE email ='".$email."'";
$query_run = mysqli_query($dbc, $query);
if (mysqli_num_rows($query_run)<1 ){
$error_message = "Your login details do not match, please double check and try again1";
} else {
while($row = mysqli_fetch_array($query_run)) {
echo ($row['password']) ."<br>";
echo $pass ."<br>";
echo $hashandsalt;
if (password_verify($pass, $hashandsalt)){
$_SESSION['firstname'] = $row['first_name'];
$_SESSION['lastname'] = $row['last_name'];
$_SESSION['email'] = $row['email'];
$_SESSION['password'] = $row['password'];
$_SESSION['id'] = $row['ID'];
header("location: logged-in.php");
} else {
$error_message = "Your login details do not match, please double check and try again";
}
}
}
}
}
?>
<div class="wrapper">
<?php
if(!isset ($error_message)) {
echo '<p>Please complete the log in details </p>';
} else {
echo $error_message;
}
?>
<form method="post" action="login.php">
<table>
<tr>
<th>
<label for="email"> Email Address </label>
</th>
<td>
<input type="email" name="email" id="email" value="<?php if(isset($email)) { echo htmlspecialchars($email); } ?>">
</td>
</tr>
<tr>
<th>
<label for="pass"> Password </label>
</th>
<td>
<input type="password" name="pass" id="pass">
</td>
</tr>
</table>
<input type="submit" value="Log in">
</form>
The results of the 3 echos I have in the login.php
echo ($row['password']) ."<br>";
This one will show the hashed password from the database
echo $pass ."<br>";
This one will show whatever password is entered
echo $hashandsalt;
This one shows a new hashed password which differs each time the page is refreshed
This is where my query is I am obviously missing something which is not allowing the password entered to match up to the already stored hashed password.
I have scoured the internet including number of stack overflow posts but I can't quite seem to figure out what I have done wrong. This is my first post so I hope I am posting enough information for you.
Any ideas guys?
p.s I know I need to add the mysqli_real_escape_string - this was my next job after figuring this one out :ve
To verify the password you need to check with the stored password-hash from the database. There is no need to call password_hash() in login.php.
login.php
if (password_verify($pass, $row['password']))
Also there is no need to add a salt before hashing, the function password_hash() will add it automatically.
register.php
$password_save = password_hash($pass1, PASSWORD_DEFAULT, array('cost' => 10 ));

what to do with this error?

I have had my script running on a localhost WampServer 1st which where it worked and then exported it to my online live domain.
After some adjustments i got the script partically working again but i am still getting below error
Call to undefined function filter_var()
The purpose of this script is when an user wants to registrate it will validate the email address and add the user to the database and send an validation link to the users emailaddress.
Here is the script:
<?PHP
error_reporting(E_ALL);
ini_set('display_errors', 1);
// connection towards database with a include function
include ('connection.php');
if (isset($_REQUEST['send']))
{
if(isset($_REQUEST['NAAM']))
{
$naam = $_REQUEST['NAAM'];
}
function spamcheck($field)
{
//filter_var() sanitizes the e-mail
//address using FILTER_SANITIZE_EMAIL
$field = filter_var($field, FILTER_SANITIZE_EMAIL);
//filter_var() validates the e-mail
//address using FILTER_VALIDATE_EMAIL
if(filter_var($field, FILTER_VALIDATE_EMAIL))
{
return TRUE;
}else
{
return FALSE;
}
}
//if "email" is filled out, proceed
if (isset($_REQUEST['mail']))
{
//check if the email address is invalid
$mailCheck = spamcheck($_REQUEST['mail']);
if ($mailCheck == TRUE)
{
$email = $_REQUEST['mail'];
}else
{
$mailCheck = FALSE;
echo "Invalid input email";
}
}
if(isset($_REQUEST['question']))
{
$quest = $_REQUEST['question'];
// checks if the filled in Question is de same as the answer novice or Novice
if ($quest =="novice" or $quest =="Novice")
{
$questCheck = TRUE;
}else
{
$questCheck = FALSE;
echo "Your answer to the question was incorrect!<br>";
}
}
if(isset($_REQUEST['wachtwoord'] , $_REQUEST['c_wachtwoord']))
{
$WW = $_REQUEST['wachtwoord'];
$c_WW = $_REQUEST['c_wachtwoord'];
// checks if the filled in password is de same as the confirmation password
if ($WW == $c_WW)
{
$pwCheck = TRUE;
}else
{
$pwCheck = FALSE;
echo "Your filled in passwords are not the same try again!<BR>";
}
}
// checks if both password confirmation and question are TRUE continue else retrieve fault
if ($pwCheck && $questCheck && $mailCheck == TRUE)
{
$hash = md5( rand(0,1000) );
// insert all filled in values into the database
$opdracht1 = "INSERT INTO users (ID , name , password , mail , staffLevel , hash , active) VALUES ('','$naam','$WW','$email','0','$hash','0')";
// run query
if (mysql_query ($opdracht1))
{
header( "refresh:5;url=http://www.debeerislos.nl/inlog_user.php" );
echo "Your account has succesfully been created! Please check your email to validate your account!<BR>";
$to = $email; //Send email to our user
$subject = 'Signup | Verification'; //// Give the email a subject
$message = '
Thanks for signing up!
Your account has been created!
You can login with the following credentials:
------------------------
Username: '.$naam.'
Password: '.$WW.'
------------------------
After you have activated your account you will have the rights so you can fully use it.
Please click this link to activate your account:
http://www.debeerislos.nl/verify_user.php?email='.$email.'&hash='.$hash.'&name='.$naam.'
'; // Our message above including the link
$headers = 'From:info#debeerislos.nl' . "\r\n"; // Set from headers
mail($to, $subject, $message, $headers); // Send the email
}else
{
echo "Woops something went wrong please contact the Administrator of the website or fill in the form again!<br> <A href='http://www.debeerislos.nl/form_register_user.html'>CLICK HERE!</A> to fill in the forum again";
}
}elseif ($pwCheck && $questCheck == FALSE)
{
echo "you filled both the password confirmation and the answer to the question incorrect!<br>";
}
}else
{
echo "Either you haven't send anything! or you haven't filled in the form<br>";
}
?>
In advance thank you.
Kind Regards,
StaleDevil
where have you defined filter_var() function? It is not defined in your given code. If you are defining it in the same page then how are you defining? provide example. otherwise if you are definfing it in another page then include the page.

Verification link not activating account

So I've sent a link after registration to Verify an account, the link contains the users email address and a 32 character code for example:
$to = $email;
$subject = 'Signup | Verification';
$message = '
Thanks for signing up!
Your account has been created, you can login with the following credentials after you have activated your account by pressing the url below.
------------------------
Username: '.$username.'
Password: '.$password.'
------------------------
Please click this link to activate your account:
localhost:8888/website/verify.php?email='.$email.'&hash='.$hash.'
';
$headers = 'From:myemail#email.com' . "\r\n";
mail($to, $subject, $message, $headers);
That all seems to work fine I'm receiving the email with a link like this:
http://localhost:8888/website/verify.php?email=myemail#email.com&hash=fe646d38bc2145ca6c3cf77d52820cd0
The problem comes when I follow the link and try to activate the account. It takes me to Verify.php fine but I keep getting Invalid Approach and I'm unable to set Validation to 1.
<?php include "includes/base.php"; ?>
<?php
if(isset($_GET['Email']) && !empty($_GET['Email']) AND isset($_GET['Hash']) && !empty($_GET['Hash'])){
$email = mysql_escape_string($_GET['Email']);
$hash = mysql_escape_string($_GET['Hash']);
$search = mysql_query("SELECT Email, Hash, Validation FROM users WHERE Email = '".$email."' AND Hash = '".$hash."' AND Validation = 0") or die(mysql_error());
$match = mysql_num_rows($search);
if($match > 0){
mysql_query("UPDATE users SET Validation = 1 WHERE Email = '".$email."' AND Hash = '".$hash."' AND Validation = 0") or die(mysql_error());
echo "Your account has been activated, you can now login";
}else{
echo "The url is either invalid or you already have activated your account.";
}
}else{
echo "Invalid approach, please use the link that has been sent to your email.";
}
?>
1) this code is unsecure as it has SQL injection problem. Use prepared statements
Please keep in mind that mysql_* functions are no longer supported and they are depriated
2) Regarding your code I found that your GET request has 'email' and 'hash' all lowercase, but in PHP code you use $_GET['Email'] and $_GET['Hash'].
You need to change this:
if(isset($_GET['Email']) && !empty($_GET['Email']) AND isset($_GET['Hash']) && !empty($_GET['Hash'])){
$email = mysql_escape_string($_GET['Email']);
$hash = mysql_escape_string($_GET['Hash']);
To this
if(isset($_GET['email']) && !empty($_GET['email']) AND isset($_GET['eash']) && !empty($_GET['eash'])){
$email = mysql_escape_string($_GET['email']);
$hash = mysql_escape_string($_GET['eash']);
or change your GET request to the next one:
http://localhost:8888/website/verify.php?Email=myemail#email.com&Hash=fe646d38bc2145ca6c3cf77d52820cd0
Change Hash to hash & Email to email. (Capitalized, but not in link that you send)
Also, your code is prone to sql injection attack as you are directly using the values in the url to query your database. Please use mysql_real_escape_string and perform some sanity checks before making the query.
there's capitals in the PHP whereas there are none in the link
$_GET['Email']
verify.php?email=myemail#email.com

Creating a mechanism to validate emails

I already have an advanced user login/register system on my website (colemansystems.psm2.co.uk). However, I would like to have a email sent to new users for verification of their email address. If they have not clicked the link they will not be able to access their account. I am semi-experienced with PHP and MySQL, so please explain in depth.
The code I'm using for the verify.php file (the link the user click on with a GET (for example, verify.php?d=51773199320))
$secret = $_GET['d'];
$result = mysql_query("SELECT valid FROM users WHERE secret=$secret");
while ($row = mysql_fetch_array($result))
{
$valid = $row['valid'];
}
if ($valid == "") {
echo"There seems to be a problem with the verification code.<br><br><br><br><br>";
}
elseif ($valid == "1")
{
echo"Your account is already verified.<br><br><br><br><br>";
}
else
{
mysql_query("UPDATE users SET valid = '1' WHERE secret=$secret");
echo "Thank you, your account is now verified and you are free to use the exclusive features!<br><br><br><br><br><br>";
}
Is this secure?
The easiest way is not to register unverified users at all.
Ask them for an email address and send email with a link that contains this address sealed with a hash. Upon receiving this link you can start the registration process.
Something like this
$secret = "35onoi2=-7#%g03kl";
$email = urlencode($_POST['email']);
$hash = MD5($_POST['email'].$secret);
$link = "http://example.com/register.php?email=$email&hash=$hash";
And in your register.php add 2 hidden fields to the registration form - email and hash, storing their received values from GET.
Finally, process registration and check,
if (md5($_POST['email'].$secret) == $_POST['hash']) {
//Continue registration.
}
Easiest for whom - user, coder, computer?
What are you optimizing - the quantity of keypresses, the size of the code, the user experience?
The easiest to code is probably unsafe.
You should check the email address for correctness before sending a letter to it.
after registration create a hashed string and save it to the temporary user table send that hashed string to the user email address using this code
if(isset($_POST['register']))
{
$email_id=$_POST['email'];
$pass=$_POST['password'];
$code=substr(md5(mt_rand()),0,15);
mysql_connect('localhost','root','');
mysql_select_db('sample');
$insert=mysql_query("insert into verify values('','$email','$pass','$code')");
$db_id=mysql_insert_id();
$message = "Your Activation Code is ".$code."";
$to=$email;
$subject="Activation Code For Talkerscode.com";
$from = 'your email';
$body='Your Activation Code is '.$code.' Please Click On This link Verify.php?id='.$db_id.'&code='.$code.'to activate your account.';
$headers = "From:".$from;
mail($to,$subject,$body,$headers);
echo "An Activation Code Is Sent To You Check You Emails";
}
and after that create a verify page and then
if(isset($_GET['id']) && isset($_GET['code']))
{
$id=$_GET['id'];
$code=$_GET['id'];
mysql_connect('localhost','root','');
mysql_select_db('sample');
$select=mysql_query("select email,password from verify where id='$id' and code='$code'");
if(mysql_num_rows($select)==1)
{
while($row=mysql_fetch_array($select))
{
$email=$row['email'];
$password=$row['password'];
}
$insert_user=mysql_query("insert into verified_user values('','$email','$password')");
$delete=mysql_query("delete from verify where id='$id' and code='$code'");
}
}
if you have any problem here is a complete tutorial http://talkerscode.com/webtricks/account-verification-system-through-email-using-php.php

Categories