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));
Related
I'm attempting to get my code to pull up a username based on the password a user inputs. It works successfully when I bake the actual password into the code, but I haven't found any way to get the variable in successfully.
The troublesome line is:
$result=$dbh->prepare('SELECT * from account WHERE password = (' & $formpassword & ')');
The variable is $formpassword.
I have variables successfully working on an INSERT statement elsewhere in my code, using this system:
$_query = "INSERT INTO account (username, password) ";
$_query = $_query."VALUES ('".$formusername."', '".$formpassword."')";
^^^ I have tried using the above system for my SELECT statement, but it doesn't appear to work either.
Sorry if my post is unclear or anything, I'm not remotely experienced with programming...
Thanks for the help!
Never store plain text passwords! Please use PHP's built-in functions to handle password security. If you're using a PHP version less than 5.5 you can use the password_hash() compatibility pack. It is not necessary to escape passwords or use any other cleansing mechanism on them before hashing. Doing so changes the password and causes unnecessary additional coding.
When using prepared statements you put placeholders in the sql.
$stmt=$dbh->prepare('SELECT * from account WHERE password = :formPassword');
$stmt->execute([':formPassword'=>$formpassword]);
$row = $stmt->fetch();
$stmt = $pdo->prepare('INSERT INTO account (username, password) VALUES (:username, :formPassword)');
$stmt->execute([':username'=>$formusername,':formPassword'=>$formpassword]);
You should be able to use " (Double quotes) instead of ' (Single quotes). Then you can just use the variable without concatenation.
$result=$dbh->prepare("SELECT * from account WHERE( password = $formpassword )");
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
I'm trying to make a register/login system. To check if usernames and email addresses aren't used, I use this :
$username = $_POST['uLogin'];
$usernameLC = strtolower($username);
$query1 = $db0->query("SELECT userLogin FROM tbuser WHERE userLogin=':login';");
$query1->bindValue(":login", $usernameLC, PDO::PARAM_STR);
But it doesn't work. I can create as much users with the same username as I want. By extension, it also won't let me connect onto the website as it doesn't bind values or anything, so it can't compare my username to the one in the DB.
Verifying if a username is not taken worked when I used it like this
$username = $_POST['uLogin'];
$usernameLC = strtolower($username);
$query1 = $db0->query("SELECT userLogin FROM tbuser WHERE userLogin='$usernameLC';");
But it isn't the proper way to go :/
Can anybody help ? :)
They're not working because your binded values contain quotes; remove them.
userLogin=':login'
as
userLogin=:login
"Verifying if a username is not taken worked when I used it like this"
WHERE userLogin='$usernameLC'
You need to remove the quotes in the bind as already stated on top, and make sure you're using PDO to connect with, as stated below; if that is the case.
Using setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) would have signaled the syntax errors.
Read up on how to use prepared statements in PDO, to prepare and execute:
http://php.net/pdo.prepared-statements
An insight:
Make sure you are indeed using a PDO connection rather than a mysqli-based (it's unknown). I see these types of questions often, where OP's use mysqli_ to connect with and querying with PDO.
Those different MySQL APIs do not intermix with each other.
Connecting through PDO on PHP.net
If you're using mysqli_ to connect with:
See mysqli prepared statements and how to use them.
Add error reporting to the top of your file(s) which will help find errors, if any in regards to your POST arrays, or other possible errors.
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
// rest of your code
Sidenote: Error reporting should only be done in staging, and never production.
Edit:
"Thanks, it works great. When logging in though, comparing submitted password to the password in DB returns false. I try stocking the received password in $_SESSION['test'] to see what it gets and print_r($_SESSION); returns me this : Array ( [test] => Array ( [userPwd] => test12 [0] => test12 ) ) (test12 is my password, userPwd is the password Field in the db) Any idea ? ^^"
In regards to a comment you left about using passwords.
It seems you are storing passwords in plain text, rather than a hash. This is highly discouraged, as well as being stored in sessions; a very bad idea.
Read up on sessions hijacking.
See this Q&A on Stack on hashed passwords:
Q: Php 5.5 And Pdo Login
A: https://stackoverflow.com/a/27023211/
Using PHP's password_hash() function and password_verify() function.
For PHP < 5.5 use the password_hash() compatibility pack.
A note about the column type and length when storing a hashed password.
The password column should be VARCHAR.
It should also be long enough to store the hash.
Using VARCHAR(255) is best.
First off, if you're going to prepare, use ->prepare(), and remove quotes in your named placeholders, they don't need to have that:
$query1 = $db0->prepare("SELECT userLogin FROM tbuser WHERE userLogin= :login");
Then $query1->execute(), the prepared statement after the binding, so all in all:
$username = $_POST['uLogin'];
$usernameLC = strtolower($username);
$query1 = $db0->prepare('SELECT userLogin FROM tbuser WHERE userLogin = :login'); // prepare
$query1->bindValue(':login', $usernameLC, PDO::PARAM_STR); // bind
$query1->execute(); // execute
I am about to launch my website and security is important so i wanted to outline what I have done to secure the site. Please correct me if I am wrong and if I need something else:
To connect to our server, I have a two-factor authenitcation enabled via VPN.
The site uses SSL
Data is encrypted at rest.
I have a log monitoring tool
WHen users enter data into the database i use mysql_real_escape_string(); and when i display user data i use htmlspecialchars();
Passwords are stored using md5 encryption.
Sample insert query:
// I use these on every page
$username = removeBadChars($_SESSION["username"]);
$password = removeBadChars($_SESSION["password"]);
//Sanitized data
$_SESSION["username"] = $username;
$_SESSION["password"] = $password;
//Query to display
$sql = "select `User_name`, `User_id`, `User_kind` from `clientele`
where `username` = '$username' AND `password`='$password'";
$query = mysql_query($sql) or die ("Error: ".mysql_error());
while ($row = mysql_fetch_array($query)){
$name = htmlspecialchars($row['User_name']);
$uid = htmlspecialchars($row['User_id']);
$uis = htmlspecialchars($row['User_kind']);
}
mysql_free_result($query);
//Insert Query
$title = mysql_real_escape_string($_POST['title']);
$comment = mysql_real_escape_string($_POST['comment']);
$insert = "INSERT INTO table (Title, Comment)
VALUES ('".$title."', '".$comment."')";
$query = mysql_query($insert) or die ("Error: ".mysql_error());
Use a stronger hash function (e.g. sha256)
Append a salt (random value for every user) to the password before hashing it
Use prepared statements (MySQLi) instead, to avoid the possibility of forgetting to escape data before entering it into the database
Do not store user information in $_SESSION. Instead, store a session variable that means nothing to the outside world, changes every time someone logs in, and links to the user account. - This only applies to cookies. drinks some caffeine
Be careful putting data from user in attribute values (e.g. <span title="FULLNAME">), as additional escaping is needed (quotes, spaces if not using quotes, etc)
Note: This list is not exhaustive. It only lists things I noticed that were wrong with the short snippets you provided.
For safety you should probably use a PDO or mysqli_ functions and skip that old-school mysql_ junk, it's no longer being developed. Here's how to use the PDO:
$pdo = new PDO('mysql:host=localhost;dbname=whatever', $username, $password);
$statement = $pdo->prepare('select `User_name`, `User_id`, `User_kind` from `users`
where `username` = :user AND `password`= AES_ENCRYPT(:pass,:user)');
$statement->bindParam(':user', $_GET['user']);
$statement->bindParam(':pass', $_GET['pass']);
$results = $statement->execute();
var_dump($results->fetchAll());
the parameters are much safer because when you bindParam it automagically validates. Others have mentioned using md5 hashing, but there are plenty of databases for "decoding" them and also rainbow table attacks, so they're not very secure. Here I'm using mysql's AES_ENCRYPT for the password, and using the username as the key for demonstration purposes, you'd probably want to generate your own key and store it somewhere, because you can AES_DECRYPT with that... There are libraries for better encryption you should check out, like scrypt.
Whatever you do, do not use addslashes() it's insecure
On top of that you should look into securing your server's OS and Apache in other ways, like making not advertise version numbers and running apache as it's own users etc. Check out the Open Web Security Project website for tons of security info.
I have two problems.
problem one:
I am trying to create a registeration form where users can register with my website.
when I run this mysql statement a get dublicate entry found error:
$sql "insert into users(username, password) values('$username, sha('$password'))";
Duplicate entry 'da39a3ee5e6b4b0d3255bfef95601890afd80709' for key 'password'
despite the fact that I changed the the string sha('$password') several times.
please help.
else{
include("databaseconnection.php");
$databaseconnect = connect($host,$user,$password,$database)
or die("couldnot connect to database serever.\n");
$database_select = mysql_select_db($database,$databaseconnect)
or die("could not select dabases.\n " .mysql_error());
$query2 = "insert into company(username,password)
values('$username',sha1('$password'))";
$result2 = mysql_query($query2,$databaseconnect);
echo "you have been registered as '$companyloginName' <br/>";
header("Location:/index.php");
my login php script is as follow:
$result ="select username, password form users where username ='$username' and password = sha('$password');
if(mysql_num_rows($reuslt)==1){
echo"welcome '$username";
}
First, I would STRONGLY advice against using MySQL's sha() or PHP's sha1() alone for password hashing purposes. This is a huge security risk for your users if your database gets compromised.
Please take the time to read my previous answer on the subject of password hashing to properly secure your data.
Second, your code is vulnerable to an SQL Injection attack. Use mysql_real_escape_string() to escape the variables you are going to put in your query before-hand.
$query2 = "insert into company(username,password)
values('" . mysql_real_escape_string($username) .
"', sha1('" . mysql_real_escape_string($password) . "'))";
Third, your $password variable is being overwritten by your databaseconnection.php file.
include("databaseconnection.php");
$databaseconnect = connect($host,$user, $password ,$database);
To put emphasis...
$databaseconnect = connect($host,$user,$password,$database);
Therefore, the $password used later on in your query still contains the password for the database connection, not your user's password.
Change the name of your variable in databaseconnection.php or even better still, use an array to hold all the configuration.
$dbConnectParams = array('host' => 'localhost'
'user' => 'myUser',
'pass' => 'myPassword',
'db' => 'myDB');
Then, change your code as follows:
include("databaseconnection.php");
$databaseconnect = mysql_connect($dbConnectParams['host'],
$dbConnectParams['user'],
$dbConnectParams['pass'],
$dbConnectParams['db']);
Since you are already passing the database when calling mysql_connect(), you do no need to call mysql_select_db().
da39a3ee5e6b4b0d3255bfef95601890afd80709 is the sha1 hash of the empty string. Make sure that you actually insert the password into your SQL query, for example by echoing the query instead of sending it to the SQL server.
Edit With the new information added to your question, check out these two lines:
include("databaseconnection.php");
$databaseconnect = connect($host,$user,$password,$database)
Here, $password is the password used to connect to the database. The inclusion of databaseconnection.php probably overwrites what was previously in the $password variable.
Try to echo $query2 and you'll probably see it for yourself, that the SQL query doesn't include any password at all or that the password therein is not the same as the one entered by the user.
Guessing from the commented line, it may be possible you accidentally use the connection password that is set in 'databaseconnection.php' rather than the user password - you don't show how you initialize the $password string.
Also note the comma in your sql that shouldn't be there:
insert into company(username,password,)
^
I have not tested if that is the cause, but you should probably get rid of it and test it again.
Also, seriously consider pdo / prepared statements to prevent sql-injections, even more so if you want to insert the password from user input.