PDO password_verify, do I need to sanitize? - php

I have a login.php file using pdo for my website. For all my other queries up to this point based on user input, I've been using prepared statements, to protect against sql injection. However, for the login section, I'm comparing the inputted password against the hashed value in my database using password_verify(). I can't really use a prepared statement for this as my code looks like this:
if($res->fetchColumn() == 1){
$stmt2 = $conn->prepare("SELECT `password` FROM members WHERE :email = `email`");
$stmt2->bindParam(':email', $email);
$res2 = $stmt2->execute();
$passhash = $res2->fetchColumn();
$password_verify($_POST[password], $passhash);
//^^ do i need to sanitize that?
}else{
//login failed
}
This seems like it will be a simple answer, but I just want to make sure I'm doing it right.

you don't need to sanitize it as you are going to compare it with the hashed password from the database
plus on register.php you don't need to sanitize the password as you going to hash it using password_hash()
then save it to the database which won't cause any harm because it's already hashed
any sanitize to the password on register may spoil it
for example if the user used password like mypassword'1'2'3 after sanitize it will be
mypassword\'1\'2\'3 which is not the same
hope it helps

Related

password hash and verify not work properly

Password hash not work properly in my script.
Here my integration:
register.php
$password = password_hash(md5(sha1($_POST['password']) . $salt), PASSWORD_DEFAULT);
And here how i verify it:
Login.php
$password = md5(sha1($_POST['password']) . $salt);
$check = $mysqli->query("SELECT password FROM accounts WHERE email = '$email'");
$passw_hash = $check->fetch_assoc();
if (password_verify($password, $passw_hash["password"])) {
// LOGIN SUCCESSFULLY
}
My PHP version: 5.5
Or if you have any other method to encrypt password let me know.
UPDATE
1- Modified password's column size to VARCHAR (250) from VARCHAR (60)
2- Removed all other encryptions like md5, sha1, and cleaning the code to protect password against sql injections.
Example of hashed password:
Pure TEXT: google
Hashed: $2y$10$0Bd5Uv09Jg50QZZ4Iz7F2.WGV3MpYkScg9vuTONWmUCMYPJ3qDukC
I insert a new member to my database with prepared statements using mysqli:
$st = $mysqli->prepare("
INSERT INTO
accounts(
username,
password,
date
) VALUES (
?,
?,
?
)");
$st->bind_param('sss', $username, $password, $date);
$st->execute();
Since you're using password_hash() you do not want to use any additional hashing, so remove the md5() and sha1() functions.
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
Furthermore, remove the functions from your login:
$password = $_POST['password'];
By adding the other functions you're destroying the elements password_hash() and password_verify() need to do their jobs. Adding the two additional hashing mechanisms also don't make the hash any more secure.
Make sure you don't escape passwords or use any other cleansing mechanism on them before hashing. Doing so changes the password and causes unnecessary additional coding.
In addition Little Bobby says your script is at risk for SQL Injection Attacks. Learn about prepared statements for MySQLi. Even escaping the string is not safe! Don't believe it?

php crypt password and postgresql database

I'm new in PHP. I'm doing authentication, where I'm checking password with password stored in database PostgreSQL. On db site i used this function to crypt my password:
update ucty set psswd = crypt('some_pswd',gen_salt('md5')) where uid='1';
In my PHP srcipt I'm using this code:
$query = "SELECT meno, priezvisko, nickname, psswd, uid
FROM ucty
where nickname='$nickname' and psswd=crypt('$password', psswd)";
Everything works fine, but I'm not sure , that this is correct way to secure my password.
Any advice?
You're correct; this isn't the correct way to secure your password.
You're encrypting the password as part of the query. This can be logged (in plaintext), so it's very possible for intruders (or anyone listening to your traffic) to see users' passwords in plaintext.
"How can I prevent this?" Do your hashing on the server-side, within your PHP code. You can read up on this in the PHP manual.
Essentially, you want to have your query to set a password be something like this:
UPDATE ucty SET psswd=$hashed WHERE uid=1;
You're putting variables directly into the SQL statement. You didn't mention what method you're using to query the database, but you'll want to use prepared statements. This is a safe way to slide in user-supplied data (which $nickname and $password are).
This would be an example of a good way to use prepared statements:
$query = "SELECT meno, priezvisko, nickname, psswd, uid"
. " FROM ucty"
. " WHERE nickname=? and psswd=?";
$stmt = $dbh->prepare($query);
$stmt->execute(array($nickname, $hashedPassword));

Is this login system secure

Is this login system secure ?
if ($_POST[$submit]){
$user = $_POST[$user];
$pass = $_POST[$pass];
if ($user && $pass){ //if user and pass is enterered
require("vars.php"); //require MySQL conection settings
mysql_connect($auth_mysql_server, $auth_mysql_user, $auth_mysql_pass); //connect to MySQL
mysql_select_db($auth_mysql_db); // select MySQL database
$pass = md5($pass); // hash password
$query = mysql_query("SELECT * FROM $auth_mysql_table WHERE user='$user'"); // run query
$numrows = mysql_num_rows($query);
if ($numrows == 1){ //check if user exists
$row = mysql_fetch_assoc ($query);
$dbid = $row[$auth_mysql_id_row];
$dbuser = $row[$auth_mysql_user_row];
$dbpass = $row[$auth_mysql_pass_row];
if ($pass == $dbpass){ // if password is equal to the one in the database start session
session_start();
//set session information
$_SESSION['user'] = $dbuser;
header("Location:$auth_loggedin"); // goto logged in page
}
else return (3);
}
else return (2);
mysql_close(); // close MySql connection
}
else return (1);}
If not how could i make it secure ?
I hashed the password but i know md5 can be decrypted however sha1 can be too.Also is themysql_close() needed ?
Add salt to your hashes. This can be a random string, a user's name, timestamp of account creation or pretty much whatever you like, as long as it's the same every time a given user logs in. The purpose is to first, break rainbow tables (long lists of common passwords that have been md5 encrypted) and second, add entropy to normally short passwords.
$pass = $_POST['pass'];
$salt = "7y9fhu8a"
$secure_pass = md5( $pass . $salt );
Secondly, you're not sanitizing your username input. You could add a mysql_real_escape_string to your username to prevent sql injection attacks.
$query = "SELECT * ".
"FROM $auth_mysql_table ".
"WHERE user='" . mysql_real_escape_string($user) . "'";
$result = mysql_query($query);
There are other ways to sanitize user input, but that's the quick and dirty. As far as the mysql_close goes, i wouldn't bother. If you need to run any other queries you'd need to reopen the connection.
no it is not secure. you are opening yourself to sql-injection attacks. imagine what would happen, if somebody entered this into your user-input-field (which goes into the $_POST[$user])
a'; drop table user; select '1'='1
this would result in an sql statement like this:
SELECT * FROM $auth_mysql_table WHERE user='a'; drop table user; select '1'='1'
which you would execute against your database. that's bad!
you need to sanitize your input. read this: http://php.net/manual/en/security.database.sql-injection.php
edit: relevant
No it's not secure.
You need to sanitize your user inputs or (even better) use bind variables. For PHP you can use PDO: PHP PDO prepared statements
Also, an unsalted md5 is a terrible choice for hashing passwords and provides no real security. A salted md5 is only marginally better (but still in the terrible category).
You should either:
Not store any passwords- use federated login (OpenID, OAuth, etc)
If you are going to handle passwords yourself then use a much stronger hash function such as scrypt, bcrypt, or PBKDF2.
mysql_close is not needed but is good practice. PHP will automatically close the connection at the end of the script.
MD5 is not the best encryption method, you can use some other PHP encryption library like AES
See this link for more information about PHP encryption:
http://php.net/manual/en/ref.mcrypt.php
keep in mind that you also have to ALWAYS sanitize the code !!
MySQL injection can be a bad beast!!

How to use the md5 hash?

Okay, so I'm learning php, html, and mysql to learn website development (for fun). One thing I still don't get is how to use md5 or sha1 hashes. I know how to hash the plain text, but say I want to make a login page. Since the password is hashed and can't be reversed, how would mysql know that the user-inserted password matches the hashed password in the database? Here is what I mean:
$password = md5($_POST['password']);
$query = ("INSERT INTO `users`.`data` (`password`) VALUES ('$password')");
I know that this snippet of script hashes the password, but how would I use this piece of code and make a login page? Any working examples would be great.
Here is my script:
<?php
session_start();
include("mainmenu.php");
$usrname = mysql_real_escape_string($_POST['usrname']);
$password = md5($_POST['password']);
$con = mysql_connect("localhost", "root", "g00dfor#boy");
if (!$con) {
die(mysql_error()); }
mysql_select_db("users", $con) or die(mysql_error());
$login = "SELECT * FROM `data` WHERE (`usrname` = '$usrname' AND `password` = '$password')";
$result = mysql_query($login);
if (mysql_num_rows($result) == 1) {
$_SESSION['logged_in'] = true;
header('Location: indexlogin.php');
exit;
}
else {
echo "Wrong username or password.";
}
?>
But I still get the else statement, "Wrong username or password. Someone help plz!"
The answer is quite simple: You have a hash in the database, so you need to hash the user-provided password to compare them.
So when the user attempts to log in, you take the $_POST['password'] or whatever, and create a hash of it. Then, you simply query the database for the hash, SELECT * FROM users WHERE password = 'hashgoeshere'
I would also recommend you read more about secure storage of passwords. For example this is a good start: You're probably storing passwords incorrectly - Coding Horror
Please use SHA1/256. MD5 is not cryptographically secure anymore and it's discouraged to use it for cryptography (it's fine for file hashes ETC).
I'm not posting code, but explaining the technique:
First, on the registration, take the SHA1/256 hash of the password and store it in the database. The next time the user logs in you take the SHA1/256 hash of the password he/she entered again and match it against the hash stored in your database. This works because the SHA1 hash for the password is semi-unique (the chances for duplicates are small) for that password.
well instead of inserting into the SQL database, assign some query into a variable and check it against the md5 given by the user
When the user tries to login using their password, you take the md5 of what they enter and compare it with what you've already stored in the database. If it matches, you know they entered the right password.
It hashes the password so it is not save in clear text
e.g mylongpassword becomes 9a995d3f6a3d69c1a9b4344bed4f2c87
Select the hashed password using the db First
$password_from_db = Select * from user where username='".$_POST['username']."'
Then password from the ($_POST['password']) should be hashed first in PHP then compared to the valued stored in the DB
<?
if (md5($_POST['password'])==$password_from_db){
return true;
}else{
return false;
}
?>
Edited
Your code seems okay.
Check if your password field in the database is at least 32 characters.
And try to execute this query (changing variables to real string) in phpMyAdmin if you use one.
You have a major crypto problem, too.
$password = md5($_POST['password']);
The problem there is that all the people with identical passwords will have identical hashes, so if (when?) someone breaks into your site, they run one dictionary attack, and then compare the hashes from the attack to the hashes from your DB. As a result, they break every single account on your site for essentially the same cost as breaking one.
At a very minimum, you should salt it, something like this:
$password = md5($_POST['user'] + $_POST['password']);
But even that has surprising weaknesses, so it's better to hash it twice, maybe like this:
$password = md5($_POST['password'] + md5($_POST['password'] + $_POST['user']));
Of course, the best way of all is to use something written by someone who knows far more about doing crypto properly than I do :)
(And remember that bad perf in your authentication system is a feature.)

PHP AJAX login, is this method secure?

I have just started PHP and mySQL and need to know if this is "safe". The login information is passed into the following PHP file through AJAX (jQuery).
jQuery AJAX
$("#login_form").submit(function(){
$.post("login.php",{user:$('#username').val(),pass:$('#password').val()} ,function(data)
PHP
ob_start();
mysql_connect("-", "-", "-") or die("ERROR. Could not connect to Database.");
mysql_select_db("-")or die("ERROR. Could not select Database.");
//Get Username and Password, md5 the password then protect from injection.
$pass = md5($pass);
$user = stripslashes($user);
$pass = stripslashes($pass);
$user = mysql_real_escape_string($user);
$pass = mysql_real_escape_string($pass);
//See if the Username exists.
$user_result=mysql_query("SELECT * FROM users WHERE username='$user'");
$user_count=mysql_num_rows($user_result);
if($user_count==1){
if($pass_length==0){ echo "userVALID"; }
else{
$pass_result=mysql_query("SELECT * FROM users WHERE username='$user' and password='$pass'");
$pass_count=mysql_num_rows($pass_result);
if($pass_count==1){
session_register("user");
session_register("pass");
echo "passVALID";
}
else { echo "passERROR"; }
}
}
else { echo "userERROR"; }
ob_end_flush();
I know this may not be the best way to do things but, it is the way I know! I just want to know if it has any major security flaws. It is more of a concept for me and therefore I am not incorporating SSL.
You should make this change just in case people have a backslash in their password:
if(get_magic_quotes_gpc()){
$user = stripslashes($user);
$pass = stripslashes($pass);
}
$user = mysql_real_escape_string($user);
$pass = sha256($salt.$pass);
First and foremost md5 is very bad. Also md5() and mysql_real_escape_string() is redundant. Collisions have been generated in the wild. sha1() although weakened is still much more secure and no collisions have been generated (yet). The best choice would be sha256 in php, or using the mhash library.
$pass = md5($pass);
You also need to salt the password.
It suffers from
Sending the password over an unencrypted connection (use HTTPS at least to send the username and password; this protects the password against passive attackers but not against active ones. To be secure against active attackers, you must encrypt all the communications).
Storing the password in the database (you should store a salted hash instead).
Also never tell user things like "user doesn't exist" or "incorrect password". It's much better if you just print out "Incorrect username or password" so everyone cannot check for existing usernames and then try to guess password for these.
session_register() is deprecated, you should be using $_SESSION[].
You're also performing your string escapes on a hashed password string $pass; it will always have a hex value and so doesn't need to be escaped. You can perform escapes on the password string before the hash, but that's only marginally useful (e.g., if you allowed passphrases to be saved by users that included characters that needed to be escaped. Generally I disallow this on the registration side of the code). You should also use a salt.
Base on my research:
using jquery ajax to login is as safe as plain old form. data is always sent through http request. reference: ajax safe for login?
use SSL (https) in login form gives extra security.
instead of using mysql_connect, you should use prepared statements
reference: why prepared statement? and prepared statement usage example
you should use one-way password hashing algorithm, such as Bcrypt. one-way hashing algorithm means you cannot convert hashed password back to plain text. but you can verify the keyed in password against the hashed password stored in database. reference: don't encrypt password, hash it instead. and the Bcrypt and how to use it

Categories