I am working on page with register and login possibilities.
It always says that the password is incorrect. What am I doing wrong?
I also tried with iterator_to_array, it doesn't work either.
$db = get_db();
$mojlogin = $_POST['login'];
$mojehaslo = $_POST['haslo'];
empty($mors);
$mors = $db->morsy->findOne(array('login' => $mojlogin, "haslo1" => $mojehaslo));
if(password_verify($mojehaslo, $mors['haslo1'])){
echo "Zalogowany!\n";
$powitanie = "Witaj ponownie, ".$mojlogin."!";
echo "<h1 class='tytul'>$powitanie</h1>";
$_SESSION["user"] = $mojlogin;
} else {
echo "Niepoprawny login lub hasło!\n";
}
As far as I can tell from your code, you request the user password and use it as a search criteria to get his account from the database, which implies that instead of storing the hash of the password, you store the password itself.
The proper way to do this is to generate hash first, store it in haslo1 field, and then use it as a second argument in the password_verify function along with the actual password in $mojehaslo as the first one. Furthermore, you only use $mojlogin in the findOne() query, because the idea is to get the hash from the database corresponding to user login and compare it to the password that was entered.
You normally want to generate your hash using password_hash function:
$hash = password_hash($password, PASSWORD_DEFAULT);
Then, after you place it in haslo1 document field, you use almost the same code as you did before:
$mors = $db->morsy->findOne([ 'login' => $mojlogin ]);
if (password_verify($mojehaslo, $mors['haslo1'])) {
// here goes your entrance code
}
Check var_dump, always.
After not getting my login, my friends told me to use:
var_dump(iterator_to_array($db->morsy->find()))
I had white space before login, because of mistakes in form.
Related
I'm trying to store an encrypted password in MySQL and as for the register part it works as it should how ever when i try to do the login things go south.
I can not verify $_POST['password'] against the hash stored in MySQL.
I have no idea what I'm doing wrong.
Here is my register.php which works as it should:
register.php (working)
$post_password = mysqli_real_escape_string($_POST['password']);
$password_hash = password_hash($post_password, PASSWORD_BCRYPT);
mysqli_query goes here...
login.php (not working)
$con = mysqli_connect("XXX","XXX","XXX","XXX");
$post_username = mysqli_real_escape_string($con,$_POST['username']);
$post_password = mysqli_real_escape_string($con,$_POST['password']);
// Getting the stored Hash Password from MySQL
$getHash = mysqli_fetch_assoc(mysqli_query($con, "SELECT * FROM anvandare WHERE username = '$post_username'"));
$got_Hash = $getHash['password'];
// Checking if what the user typed in matches the Hash stored in MySQL
// **This is where it all goes wrong**
if (password_verify($post_password, $got_Hash)) {
echo "The posted password matches the hashed one";
}
else {
echo "The posted password does not match the hashed one";
}
When I run the code above I get the "Correct password" message by just entering the username and leaving the password field out.
What am I missing?
Actually you need to make sure that you are allowing more than 100 characters in your password column so that all the hashed password can be saved in the field. This was also happening with me, the script was correct and everything was working fine but the only mistake I was doing was that I didn't allow more than 40 characters in the password field which was the biggest error. After incrementing the maximum limit from 40 to 100, everything is working fine:)
I've asked a few questions about this piece of code on this site.
Basically, my database is not updating when I use - $id = $GET_['id']; (at the top of the code below). The id gets passed to this page from the previous page - the url of the page is 'http:// www.21orange.com/CCC/changepassword.php?id=1'. There is an 'id' field in my database.
When I change the above line of code to - $id = '1' - the code runs perfectly and the database is updated. It only stops working when I use the $GET_['id']. Why is this?
// First we execute our common code to connection to the database and start the session
require("common.php");
$id = $_GET['id'];
// This if statement checks to determine whether the registration form has been submitted
// If it has, then the registration code is run, otherwise the form is displayed
if(!empty($_POST))
{
// Ensure that the user has entered a non-empty password
if(empty($_POST['password']))
{
die("Please enter a password.");
}
// Ensure that the user has entered a non-empty username
if(empty($_POST['confirmpassword']))
{
// Note that die() is generally a terrible way of handling user errors
// like this. It is much better to display the error with the form
// and allow the user to correct their mistake. However, that is an
// exercise for you to implement yourself.
die("Please confirm your password.");
}
if ($_POST['password'] == $_POST['confirmpassword']) {
// An INSERT query is used to add new rows to a database table.
// Again, we are using special tokens (technically called parameters) to
// protect against SQL injection attacks.
$query = "UPDATE Staff SET password=:password, salt=:salt WHERE id=:id";
// A salt is randomly generated here to protect again brute force attacks
// and rainbow table attacks. The following statement generates a hex
// representation of an 8 byte salt. Representing this in hex provides
// no additional security, but makes it easier for humans to read.
$salt = dechex(mt_rand(0, 2147483647)) . dechex(mt_rand(0, 2147483647));
// This hashes the password with the salt so that it can be stored securely
// in your database. The output of this next statement is a 64 byte hex
// string representing the 32 byte sha256 hash of the password. The original
// password cannot be recovered from the hash.
$password = hash('sha256', $_POST['password'] . $salt);
// Next we hash the hash value 65536 more times. The purpose of this is to
// protect against brute force attacks. Now an attacker must compute the hash 65537
// times for each guess they make against a password, whereas if the password
// were hashed only once the attacker would have been able to make 65537 different
// guesses in the same amount of time instead of only one.
for($round = 0; $round < 65536; $round++)
{
$password = hash('sha256', $password . $salt);
}
try
{
// Execute the query to create the user
$stmt = $db->prepare($query);
$stmt->execute(array(
'password' => $password,
'salt' => $salt,
'id' => $id));
}
catch(PDOException $ex)
{
// Note: On a production website, you should not output $ex->getMessage().
// It may provide an attacker with helpful information about your code.
die("Failed to run query: " . $ex->getMessage());
}
// This redirects the user back to the login page after they register
header("Location: stafflist.php");
// Calling die or exit after performing a redirect using the header function
// is critical. The rest of your PHP script will continue to execute and
// will be sent to the user if you do not die or exit.
die("Redirecting to stafflist.php");
}
die("Passwords do not match.");
}
I'm new to php, so forgive my naivety. P.s. I know the method I'm using is fairly old school, but it's only a test.
Thanks,
Joe
You can't do both GET and POST in a single HTTP Request.
However, you can use an hidden input field to get around this limitation:
In your HTML markup, you can add the following:
<input type="hidden" name="id"
value="<?php echo htmlspecialchars($_GET['id'], ENT_QUOTES); ?>" />
And your $_GET['id'] should work just fine.
To avoide this error
Undefined index: id in /home/content/47/11368447/html/CCC/changepassword.php on line 6
first test if the index exists :
if(isset($_GET['id'])) {
$id = $_GET['id'];
} else {
// here you can set a value for the id
}
Otherwise, you can add your $id var in your if test :
if(!empty($_POST) && $id)
{
//...
}
It looks like you are passing the 'id' to the action URL but for some reason the $_GET variable is not having it. Please double check:
Are you really passing the 'id' to the URL ? Please make sure.
Please check the code in common.php to see if the $_GET variable is modified in it.
Is that script behind a rewrite settings (e.g in .htaccess) ? if yes, $_GET parameters could be gone due to inappropriate rewrite settings. You can further test it out by putting print_r($_GET); in the beginning and visit that script directly ( GET instead of POST )
$id = $_GET['id'];
first check there is any value in $id to print the $id through echo
I've cribbed this code almost verbatim from a bunch of very helpful answers here on SO, so I can't get my head around what's wrong.
First, here's my function for creating a user account:
function BFcrypt($password,$cost)
{
$chars='./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$salt=sprintf('$2a$%02d$',$cost);
for($i=0;$i<22;$i++) $salt.=$chars[rand(0,63)];
return array(
'salt'=>$salt,
'hash'=>crypt($password,$salt)
);
}
Then, when a user goes to login:
case 'login':
$login =$_POST['login'];
$pwd =$_POST['pwd'];
$sql ="SELECT * FROM `users` WHERE `users`.`login`='$login' LIMIT 1;";
if($query = mysql_query($sql)){
$row=mysql_fetch_assoc($query);
print_r($_POST);
print_r($row);
$hash = $row['password'];
if(crypt($pwd,$hash)==$hash){
echo"SUCCESS";
}else{
echo"FAILURE";
}
}
The login function appears to always be failing. I've set it to show me $pwd, $hash and crypt($pwd,$hash), and for some reason, crypt($pwd,$hash) never seems to == $hash.
Here's a row in the database for a sample user (I'm logging the salt now, though I know it's supposed to be included in the hash:
'id'=>'680',
'login'=>'argh',
'password'=>'$2a$10$BWZAX7wrwQp5iyK4kh6VLunqy82eiXg7GaDs6mJLqdgT5s2qiUqYW',
'salt'=>'$2a$10$BWZAX7wrwQp5iyK4kh6VL5',
'first'=>'argh',
'last'=>'argh',
'zip'=>'00000',
'email'=>'argh',
'date updated'=>'2012-12-12 16:05:29'
I believe that when I call crypt($pwd,$hash),it truncates $hash, leaving only the original 22-character salt (plus prefix), thus the output will be the same as $hash as long as $pwd is the same. I'm seeing clearly there's an issue here in that the salt I'm recording is one character longer than the one that ends up appended to the hash, but it's the appropriate length for blowfish, and anyway, making it one character shorter doesn't seem to help.
I can't figure out what I'm doing wrong here. Any help would be appreciated.
Based on your own salt value and password of 'argh' I ran a small test script:
$hash = crypt('argh', '$2a$10$BWZAX7wrwQp5iyK4kh6VL5');
// $2a$10$BWZAX7wrwQp5iyK4kh6VLuIzJHihvZTdfpRXNkTPVKkTiGfLDl1RO
var_dump(crypt('argh', $hash) == $hash);
// bool(true)
The problem doesn't seem to be in the code you've shown.
You could check your database field width to store the password hash, which should be at least 60 wide. And while you're at it, fix your SQL injection vulnerability (by using prepared statements most preferably).
Hopefully this is simple. I am trying to grant administrative power to the user if they are able to provide the 'root' password. Is there a way to compare this newly entered password with the root password? this is what my code looks like so far:
<form action='index.php?login=yes' method=POST>
Password: <input type=password name='pwd'><br />
<input type=submit value='Login' />
</form>
<?php
$pass=$_POST['pwd'];
$login=$_GET['Login'];
if($login=='yes') {
$con=mysql_connect('localhost','root','');
mysql_select_db('Login');
$get=mysql_query("SELECT count(id) FROM Login WHERE pwd = '$pass'");
$result=mysql_result($get, 0);
mysql_close($con);
if($result!=1)
echo"Login Failure!";
else {
echo"Login Success";
};
};
?>
</p>
Please be gentle because PHP is a lot different than i'm used to (i prefer java).
Thanks!
You should definitely consider hashing the password, with a salt. The md5() algorithm isn't really recommended for secure environments but it does at least make the job harder.
When saving your password in the database, you should do something like
$salt = 'dhg1d9h12h1029he01h2e1'; // Just have something random and long here
$hashedpassword = md5($salt.md5($password, true)); // Or any other combination you like here
Then, you can save $hashedpassword into the database like so:
mysql_query(sprintf("UPDATE Login SET pwd = '%s' WHERE username = '%s'",
mysql_real_escape_string($hashedpassword),
mysql_real_escape_string($username)
));
Then when you want to check if a password matches, do the exact same step as above to calculate the $hashedpassword value but pass in their test password and then compare that with what's in the DB, eg:
$result = mysql_query(sprintf("SELECT (pwd = '%s') AS authenticated FROM Login WHERE username = '%s'",
mysql_real_escape_string($hashedpassword),
mysql_real_escape_string($username)
));
$row = mysql_fetch_assoc($result);
if ($row['authenticated']) {
echo "Success!";
}
Aaaanyway, you look like you're just starting out, so I'd be very careful how you go with actual password verification. From what I understand bcrypt2 is what you want to use instead of md5, but I'll leave you to read up on how to do that in PHP; you should definitely read up on this stuff.
I'd also check the structure of your login table. You probably want more than a single user in it, otherwise why not just store the hash in the code itself, rather than the DB?
Also, you can determine if someone is submitting a form or getting the form by checking if $_SERVER['REQUEST_METHOD'] == 'POST', which is cleaner than using a get URL parameter (though I guess there's nothing wrong with the other approach...)
Alright, I'm trying to make a login page. It seems that all of the pages worked pretty good- until I added salts. I don't really understand them, but doing something as basic as I am shouldn't be to hard to figure out. Here's "loginusr.php":
<html>
<body>
<?php
//form action = index.php
session_start();
include("mainmenu.php");
$usrname = mysql_real_escape_string($_POST['usrname']);
$pass = $_POST['password'];
$salt = $pass;
$password = sha1($salt.$pass);
$con = mysql_connect("localhost", "root", "g00dfor#boy");
if(!$con)
{
die("Unable to establish connection with host. We apologize for any inconvienience.");
}
mysql_select_db("users", $con) or die("Can't connect to database.");
$select = "SELECT * FROM data WHERE usrname='$usrname' and password='$password'";
$query = mysql_query($select);
$verify = mysql_num_rows($query);
if($verify==1)
{
$_SESSION["valid_user"] = $usrname;
header("location:index.php");
}
else
{
echo "Wrong username or password. Please check that CAPS LOCK is off.";
echo "<br/>";
echo "Back to login";
}
mysql_close($con);
?>
</body>
</html>
I used the command echo $password; to show me if the password in the database matched with the script. They did. What am I doing wrong?
It seems like you've misunderstood salts, since you're setting $salt to be the password.
A salt should be a completely random string that's stored in a user record along with the password hash. A new unique salt should be generated for every user. So you need to add a new column to your database, called "password_salt" or similar.
Rather than trying to use the password in the SELECT query and see if you get any records, you actually need to just SELECT using the username/user_id in order to get the password hash and salt so that you can then use those to determine if the user entered the correct password.
When you sign up new users you should add the fields with values like this,
<?php
// This is registeruser.php
$salt = substr(sha1(uniqid(rand(), true)), 0, 20);
$pass = $_POST['password'];
$pass_to_store = hash("sha256", $salt.$pass);
// Then issue a DB query to store the $salt and $pass_to_store in the user record.
// Do not store $pass, you don't need it.
// e.g. INSERT INTO users ('username', 'password_salt', 'password_hash') VALUES (:username, :salt, :pass_to_store);
?>
Then to check the password is the same when logging in, you do something like this,
<?php
// This is loginuser.php
$user = // result from SQL query to retrieve user record
// e.g. SELECT password_hash, password_salt FROM users WHERE username='from_user'
$salt_from_db = $user['password_salt'];
$pass_from_db = $user['password_hash'];
if ($pass_from_db == hash("sha256", $salt_from_db.$_POST['password'])
{
// Password matches!
}
?>
Don't forget to sanitize user inputs and anything you're putting into your database. You might want to look into using prepared statements instead of having to remember to use mysql_real_escape_string all the time.
It looks like you're salting with the same password? Normally a salt would be a random key that is specific to your site that you prepend to the password input, which it looks like you're doing fine. Just make sure you're using that same salt for checking that you use when the password is created.
Also, to use sessions properly you need to have session_start before anything is output to the page:
<?php
session_start();
?>
<html>
<body>
...
A salt is a random value to prevent an attacker from just looking up the source of a hash in table generated based on common passwords. (Using the username as salt is obviously not a good idea as it only adds very little entropy).
So you need to store the salt in the database and read it from the database in order to calculate the salted password hash for comparison with the stored value.
You misspelled username a couple of times, is it misspelled in the database, too?