I've been told that this code is old way of connecting and is susceptible to sql injections. How can I make it secure?
This is the code I use to check a database for users and add a new user if they don't have an account. I tried mysqli but I don't think I got it right so I had to go back to this for now until I know how to make it secure.
<?php
// Connect to the database(host, username, password)
$con = mysql_connect('localhost','user1','pass1');
if (!$con)
{
echo "Failed to make connection.";
exit;
}
// Select the database. Enter the name of your database (not the same as the table name)
$db = mysql_select_db('db1');
if (!$db)
{
echo "Failed to select db.";
exit;
}
// $_POST['username'] and $_POST['password'] are the param names we sent in our click event in login.js
$username = $_POST['username'];
$password = $_POST['password'];
// Select eveything from the users table where username field == the username we posted and password field == the password we posted
$sql = "SELECT * FROM users WHERE username = '" . $username . "' AND password = '" . $password . "'";
$query = mysql_query($sql);
// If we find a match, create an array of data, json_encode it and echo it out
if (mysql_num_rows($query) > 0)
{
$row = mysql_fetch_array($query);
$response = array(
'logged' => true,
'name' => $row['name'],
'email' => $row['email']
);
echo json_encode($response);
}
else
{
// Else the username and/or password was invalid! Create an array, json_encode it and echo it out
$response = array(
'logged' => false,
'message' => 'Invalid Username and/or Password'
);
echo json_encode($response);
}
?>
Any data coming from a user should be passed through mysql_real_escape_string(). See the URL below for more information on using that function. It's very important.
http://php.net/manual/en/function.mysql-real-escape-string.php
Here is a little more information on SQL Injections with PHP:
http://php.net/manual/en/security.database.sql-injection.php
MySQLi Information (another technique besides mysql_real_escape_string):
http://php.net/manual/en/mysqli.quickstart.prepared-statements.php
EDIT: OK, I'll admit, I'm kinda old-school. MySQLi definitely seems to be the way to go. I'm more familiar with PHP3 and PHP4 development. If you can, re-implement your data-access code using the last link.
Related
My webpage starts with a login page, like many, and if the user has no account they can sign up. My sign up works and the users password they input is successfully hashed with password_hash and sent to the database. However, when trying to login, password_verify always returns false. Thinking I made a silly error when I originally made the hashed password, I echoed the variable I was using as the second parameter in password_verify. However, it was an exact match to the hash in the database. What could be the issue?? Shortened code is available below for both creating the password during sign up and checking the password while logging in.
CREATING HASHED PASSWORD
<?php
session_start();
require('db_credentials.php');
$inputUsername = $_POST['createUsername'] ? $_POST['createUsername'] : null;
$inputPassword = $_POST['createPassword'] ? $_POST['createPassword'] : null;
$vPassword = $_POST['verifyPassword'] ? $_POST['verifyPassword'] : null;
//protect database from corrupt user input
$inputUsername = $mysqli->real_escape_string($inputUsername);
$inputPassword = $mysqli->real_escape_string($inputPassword);
$vPassword = $mysqli->real_escape_string($vPassword);
//create connection
$mysqli = new mysqli($servername, $username, $password, $dbname);
$protectedPassword = password_hash($inputPassword, PASSWORD_DEFAULT);
//Check if the passwords match
if($inputPassword != $vPassword){
echo '<p style = "text-align: center;">Oops!The passwords you input did not match. Please try again.</p>';
session_write_close();
exit;
}
//Check for duplicate username
$query = "SELECT * FROM user_info WHERE username = ' ".$inputUsername." ' ";
$result = mysqli_query($mysqli, $query);
if(mysqli_num_rows($result) == 1) {
echo '<p style = "text-align: center;">Oops! That Username is already taken. <br>Please try a different one.</p>';
session_write_close();
exit;
}
//Username is not takin and the passwords match
else {
$sql = "INSERT INTO user_info (username, password) VALUES (' ".$inputUsername." ', ' ".$protectedPassword." ')";
echo '<p style = "text-align: center;">Success! You Have Made an Account!</p>';
if($mysqli->query($sql) === TRUE) {
session_write_close();
exit;
}
else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
}
?>
LOGGING IN
<?php
require('db_credentials.php');
$inputUsername = $_POST['username'] ? $_POST['username'] : null;
$inputPassword = $_POST['password'] ? $_POST['password'] : null;
//protect database from corrupt user input
$inputUsername = $mysqli->real_escape_string($inputUsername);
$inputPassword = $mysqli->real_escape_string($inputPassword);
$mysqli = new mysqli($servername, $username, $password, $dbname);
$query = "SELECT * FROM user_info WHERE username = ' ".$inputUsername." ' ";
$result = $mysqli->query($query);
//check if username is in database. If it is, do the passwords match?
if($result->num_rows === 1) {
$row = $result->fetch_array(MYSQLI_ASSOC);
echo $row['password'] . "<br>"; //matches hash in database exactly
echo $inputPassword; //matches the password I type in. Which is same I used to sign up.
if(password_verify($inputPassword, $row['password'])){
header("Location: puzzlerMember.php"); //this never happens
exit;
}
}
echo '<p style = "text-align: center;">Oops! Your Username/Password is incorrect. Sign up if you do not have an account.</p>'; //this always happens
exit;
?>
Note: In the database, I have the password column set to VARCHAR(255).
I've looked at many of these questions which are similar, but they all seemed to have mistaken the length of their password in the database to be too short. If they did not, I tried the top answer of the solutions. I have absolutely no idea what is wrong.
If you can help, I thank you in advance.
You are escaping your password, as a result this changes the password from what it was. Instead of relying on escaping as a security measure (which in itself is a misconception), use prepared statements.
As per the comment below, a clarification is required it seems: You are escaping the password then hashing it, as a result what is stored in the db is not what the user passes therefore it will never find what the user passes, hence, false is always returned.
Related: Should I mysql_real_escape_string the password entered in the registration form?
Update #1
As spotted by #mario, you seem to have spaces in your query when you are passing the values to it as such, it is searching your table for incorrect values.
Reading Material
Prepared Statements
for some reason my login script in php keeps returning invalid results, I'm using PHPMYADMIN to handle the database and mysqli to connect however whenever I submit the data though a HTML form the values always return false even if the correct username and password combo is working.
<?php
$username = $_POST["username"];
$password = $_POST["password"];
$con = mysql_connect("localhost","cnathanielwcol","","login");
if(! $con){die('Connection Failed'.mysql_error());}
$result = mysqli_query("SELECT * FROM login");
$row = mysql_fetch_array($result);
var_dump($row);
if ($row["username"]==$username) {
echo "Correct Username<br>";
} else {
echo "Wrong Username<br>";
}
if ($row["password"]==$password) {
echo "Correct Password<br>";
} else {
echo "Wrong Password<br>";
}
echo "<br><br>Username Submited Via HTML: <b>" . $username . "</b>";
echo "<br>Password Submited Via HTML: <b>" . $password . "</b>";
?>
MySQL is deprecated from new version of PHP use
$con = mysqli_connect("localhost","cnathanielwcol","FKxIHHoWWtd4Q","login");
Firstly, you need to select a single row, not all the rows in your table, you'd do that by specifying a WHERE clause, currently, you are trying to compare an array of values to a string which should be throwing an error if error reporting is enabled.
Secondly, you are mixing to different APIs, mysql_* is not mysqli_*.
Thirdly, it doesn't seems as though you are hashing your passwords, please, do so.
Fourthly, make use of prepared statements, it seems as though you are still learning so it would be best to start using them now.
Reading Material
OWASP's Password Storage Cheat Sheet
OWASP's PHP Security Cheat Sheet
Could you use mysqli_* please? You might be having a problem with your html form maybe
Change
$con = mysql_connect("localhost","cnathanielwcol","FKxIHHoWWtd4Q","login");
With
$con = mysqli_connect("localhost","cnathanielwcol","FKxIHHoWWtd4Q","login");
Your are trying to fetch the data with mysqli and your database connection is established by mysql
your full code:
$username = $_POST["username"];
$password = $_POST["password"];
$con = mysqli_connect("localhost","cnathanielwcol","","login") or die('connection is not establised'.mysqli_error($con));
$result = mysqli_query($con,"SELECT * FROM login WHERE username='$username' AND password='$password'");
$rowCheck=mysqli_num_rows($result);
if ($rowCheck>0) {
// fetch all data
//start session
echo "you are logged in ";
}
else{
echo 'username or password did not match';
}
Use hash password.your code is not safe.
<?php
session_start();
include("connection.php");
if (mysqli_connect_error()) {
die("Could not connect to database");
if ($_POST['submit'] == "Login") {
$query = "SELECT * FROM EmployeeTable WHERE name='"
. mysqli_real_escape_string($link, $_POST['name'])
. "'AND password='"
. md5(md5($_POST['name']) . $_POST['password'])
. "'LIMIT 1";
$result = mysqli_query($link, $query);
$row = mysqli_fetch_array($result);
if ($row) {
$_SESSION['id'] = $row['id'];
header("Location: http://www.ccm.net/forum/");
} else {
$error = "We could not find a user with that email and password. Please try again.";
}
}
?>
I have the above codes just to login an user.I have a table with the username and password already.I dont want to create a signup button,just a login button as the password will be their 'id' itself.I am able to connect to db.
Please help me, as after login I'm taken to a blank page.
First off all: You are vulnerable to sql injections using this code. Please use parametrized queries so you don't forget to escape values you use in your queries.
$mysqli = new Mysqli($host, $username, $password, $database);
$mysqli->prepare('SELECT * FROM EmployeeTable WHERE name = ? AND password = ? LIMIT 1');
$mysqli->bind_param('ss', $name, $password);
$mysqli->execute();
$result = $mysqli->fetch_array();
You should also not use md5 for password hashing. Use the built in password_* functions.
password_hash can be used to hash passwords like so:
$hash = password_hash($password, PASSWORD_DEFAULT);
This also applies what is called a salt to strengthen the hash against dictionary attacks.
When you want to verify passwords use can use password_verify to verify the password against the stored hash like so:
$is_correct = password_verify($password, $hash);
Using these methods you are very unlikely to mess anything up.
A direct answer to your question could be either: if ($_POST['submit'] == "Login") or if($row). I would use count() to check the number of results found like so: if(count($row) > 0).
At a guess without seeing the rest of the HTML, it is probably not satisfying the if $_POST["submit"] statement:
if ($_POST['submit'] == "Login") {
and just ends the script as there is no else option. Perhaps check that your form is POST, Name of button is actually "submit" and its value is "Login"
when I submit this form i have the same error message all the time . even if i put right or wrong password or don't put password or i write the name of the data base wrong . all of this wrongs i have the same error message :
Please enter a username and password .
so what is the problem . and i am sure about my fields on data base .
<?
session_start();
$username = $_POST['username'];
$password = $_POST['password'];
if ($username && $password)
{
$connect = mysql_connect("localhsost","root","adminffpass") or die("Couldent connet to database ");
mysql_select_db("login") or die("No data base found ");
$query = mysql_query("SELECT * FROM users WHERE username='$username'");
$numrows = mysql_num_rows($query);
if ($numrows !=0)
{
while ($row= mysql_fetch_array($query))
{
$dbusername = $row['username'];
$dbpassword = $row['password'];
}
if ($username == $dbusername && $password==$dbpassword)
{
echo "Login successul .<a href='memeberarea.php'>Click to enter member area</a>";
$_SESSION['username'] = $dbusername;
}
else
echo "incorrect password ";
}
else
die ("That user name dosent exist");
}
else
die ("Please enter a username and password");
?>
Even if i put right or wrong password or don't put password or i write the name of the data base wrong . all of this wrongs i have the same error message
Typo: localhsost for one thing. Plus, you may not be able to use mysql_ functions, since they are deprecated and may not be available for you to use.
Plus, your POST arrays may be failing, so make sure your form is a POST method and that your elements bear the name attribute.
I.e.:
<input type="text" name="username">
etc.
if i write wrong name database i don't have any error . why ?"
Because, you're just using or die("Couldent connet to database ") instead of getting the real error mysql_error()
mysql_connect() => http://php.net/manual/en/function.mysql-connect.php
<?php
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
if (!$link) {
die('Could not connect: ' . mysql_error());
}
echo 'Connected successfully';
mysql_close($link);
?>
Your present code is open to SQL injection. Use mysqli with prepared statements, or PDO with prepared statements.
I noticed you may be storing passwords in plain text. If this is the case, it is highly discouraged.
For password storage, use CRYPT_BLOWFISH or PHP 5.5's password_hash() function. For PHP < 5.5 use the password_hash() compatibility pack.
Add error reporting to the top of your file(s) which will help find 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.
Plus, instead of if ($username && $password) you should be using a conditional !empty() for your inputs.
It is also best to use proper and consistent bracing throughout your code.
else{
echo "incorrect password ";
}
etc.
Not doing so, could have adverse effects.
Storing a password hash
Using PDO with prepared statements and password_hash():
Pulled from ircmaxell's answer: https://stackoverflow.com/a/29778421/
Just use a library. Seriously. They exist for a reason.
PHP 5.5+: use password_hash()
PHP 5.3.7+: use password-compat (a compatibility pack for above
All others: use phpass
Don't do it yourself. If you're creating your own salt, YOU'RE DOING IT WRONG. You should be using a library that handles that for you.
$dbh = new PDO(...);
$username = $_POST["username"];
$email = $_POST["email"];
$password = $_POST["password"];
$hash = password_hash($password, PASSWORD_DEFAULT);
$stmt = $dbh->prepare("insert into users set username=?, email=?, password=?");
$stmt->execute([$username, $email, $hash]);
And on login:
$sql = "SELECT * FROM users WHERE username = ?";
$stmt = $dbh->prepare($sql);
$result = $stmt->execute([$_POST['username']]);
$users = $result->fetchAll();
if (isset($users[0]) {
if (password_verify($_POST['password'], $users[0]->password) {
// valid login
} else {
// invalid password
}
} else {
// invalid username
}
You may print some information for yourself, so you could see, what's wrong. Change the following line:
echo "incorrect password ";
to something like this:
echo "incorrect password, u:[$username/$dbusername] p:[$password/$dbpassword]";
If you will see that detailed message, you will know, what's wrong.
EDIT: of course, don't left pwd printing in your final code :)
I'm in the process of adding password hashing and SQL injection defenses into my Login system. Currently, I've ran into an error.
<?php
session_start(); //start the session for user profile page
define('DB_HOST','localhost');
define('DB_NAME','test'); //name of database
define('DB_USER','root'); //mysql user
define('DB_PASSWORD',''); //mysql password
$con = new PDO('mysql:host=localhost;dbname=test','root','');
function SignIn($con){
$user = $_POST['user']; //user input field from html
$pass = $_POST['pass']; //pass input field from html
if(isset($_POST['user'])){ //checking the 'user' name which is from Sign-in.html, is it empty or have some text
$query = $con->prepare("SELECT * FROM UserName where userName = :user") or die(mysqli_connect_error());
$query->bindParam(':user',$user);
$query->execute();
$username = $query->fetchColumn(1);
$pw = $query->fetchColumn(2);//hashed password in database
//check username and password
if($user==$username && password_verify($pass, $pw)) {
// $user and $pass are from POST
// $username and $pw are from the rows
//$_SESSION['userName'] = $row['pass'];
echo "Successfully logged in.";
}
else {
echo "Invalid.";
}
}
else{
echo "INVALID LOGIN";
}
}
if(isset($_POST['submit'])){
SignIn($con);
}
?>
In the above code, when I enter a valid username and password, the system prints out "Invalid". It could be a error in the password_verify() in the if statement(because if I remove it, I login successfully). I'm pretty sure I've done the preparing, binding and execution of the query properly? Does anyone know why it is doing this?
Thanks!
You're doing a SELECT *, and using fetchColumn, so the results are dependent of the returned columns order. You should either select the specific columns you need, or fetch the whole row as an associative array , and access it by column name.
There are other two issues that you should fix:
You shouldn't be using mysqli_connect_error() as you're using PDO. The right function would be $con->errorInfo().
You're defining some constants with the connection settings, yet you don't use them on the PDO() call, repeating the values instead.
Use
// it will be an array('name' => 'John', 'password_hash' => 'abcd')
// or FALSE if user not found
$storedUser = $query->fetch(PDO::FETCH_ASSOC);
instead of
$username = $query->fetchColumn(1);
$pw = $query->fetchColumn(2);
Because fetchColumn moves cursor of result. So first call extracts 1 column of first row, and second call will extract data from SECOND row!