PHP, SQL, User Database - php

I hope I formatted the code properly. I am having trouble making this if statement to work. I've searched and from what it looks like this statement should work. However, when I run it no matter the password if the username starts with kacey then it goes to echo "Logged in as: " . kacey;
Likewise, if I put the input to kaceyfeewaf, it still goes to echo "Logged in as: " . $myuser; This happens regardless of the password I put in. the line $result['username'] should validate to KACEY.
$sql = "SELECT * FROM $dbTable WHERE username = $myuser AND password = $mypass";
$result = mysql_query($sql);
if($result['username'] = $myuser && $result['password'] = $mypass;)
{
echo "Logged in as: " . $myuser;
} else {
echo "Fail ";
}

There are a few issues here.
Firstly, the variables you have in your query are strings, therefore they require to be quoted:
WHERE username = '$myuser' AND password = '$mypass'
Having or die(mysql_error()) to mysql_query() would have signaled the syntax error.
Then you're assigning instead of comparing with
if($result['username'] = $myuser && $result['password'] = $mypass;)
use two equals ==
However, that isn't how you check if those rows exist.
You need to use mysql_num_rows() or use a while loop while using a function to fetch/iterate over results found.
Here is an MySQLi example using mysqli_num_rows():
$conn=mysqli_connect("hostname","username","password","db");
$check_select = mysqli_query($conn, "SELECT * FROM `users`
WHERE email = '$email' AND pw='$pass'");
$numrows=mysqli_num_rows($check_select);
if($numrows > 0){
// do something
}
Now, we don't know where those variables have been assigned, and if from a form that it's using a POST method with matching name attributes.
I.e.:
<form action="" method="post">
<input type="text" name="username">
...
</form>
$username = $_POST['username'];
Another thing which is unknown to us is the MySQL API you're using to connect with. Make sure that you are indeed using the same one as you are using to query with, being mysql_. Different APIs do not intermix, such as mysqli_ or PDO. Use the same one from connection to querying.
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: Displaying errors should only be done in staging, and never production.
I noticed you may be storing passwords in plain text. If this is the case, it is highly discouraged.
I recommend you use CRYPT_BLOWFISH or PHP 5.5's password_hash() function. For PHP < 5.5 use the password_hash() compatibility pack.
Here is a PDO solution pulled from one of ircmaxell's answers:
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 should use == instead of simple = for your if condition

First of all delete that if stmt and make new one where you check for num rows. If there is num rows > 0 you have valid login. And then print needed results from database od current query.
Edit:
You have = insted of == or === so stmt is always true.

Related

Is this php script secure to use in my site?

I want to protect some content in my site with a password and I am thinking in using this php script
Do you think is a good way to go?
Do you know something better for this task or a way to improve ( if needed) thin one ?
The code to load the content from the database is :
<?php
error_reporting(0);
include("config.php");
if (!isset($_REQUEST["p"])) {
echo 'document.write("<div id=\"protected_'.intval($_REQUEST["id"]).'\">");';
echo 'document.write("<form onsubmit=\'return LoadContent(\"'.intval($_REQUEST["id"]).'\",\"protected_'.intval($_REQUEST["id"]).'\",document.getElementById(\"pass_'.intval($_REQUEST["id"]).'\").value); return false;\'\"><input type=\'password\' size=\'30\' placeholder=\'Content is protected! Enter password.\' id=\"pass_'.intval($_REQUEST["id"]).'\"></form>");';
echo 'document.write("</div>");';
} else {
$sql = "SELECT * FROM ".$SETTINGS["data_table"]." WHERE `id`='".intval($_REQUEST["id"])."' AND password='".mysql_real_escape_string($_REQUEST["p"])."'";
$sql_result = mysql_query ($sql, $connection ) or die ('request "Could not execute SQL query" '.$sql);
if (mysql_num_rows($sql_result)==1) {
$row = mysql_fetch_assoc($sql_result);
echo $row["content"];
} else {
echo 'Wrong password';
}
}
?>
As I said in comments, you shouldn't be spending anymore time with what you downloaded since it's old and not safe.
You may be saving passwords in plain text which is definitely not a good idea.
It's time to step into the 21st century.
The mysql_ API is in deprecation and has been deleted from PHP 7.0 entirely.
You are best to use a prepared statement and password_hash() or the compatibility pack.
Here are a few references:
http://php.net/manual/en/book.password.php
http://php.net/manual/en/function.password-hash.php
http://php.net/manual/en/pdo.prepared-statements.php
http://php.net/manual/en/mysqli.quickstart.prepared-statements.php
N.B. The use of mysql_real_escape_string() does not fully guarantee protection against a possible SQL injection.
Consult the following Q&A on the subject:
SQL injection that gets around mysql_real_escape_string()
Here is a piece of code pulled from one or ircmaxell's answers which uses a (PDO) prepared statement and password_hash().
Pulled from: https://stackoverflow.com/a/29778421/1415724
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
}

prevent sql injection in mysqli [duplicate]

This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Can I mix MySQL APIs in PHP?
(4 answers)
Closed 3 years ago.
I am very new to mysqli earlier i am writing queries in mysql but mysqli is more advanced so, i am first time using it.
Below is my php code.
function clean($str) {
$str = #trim($str);
if(get_magic_quotes_gpc()) {
$str = stripslashes($str);
}
return mysql_real_escape_string($str);
}
$email = clean($_POST['email']);
$password = clean($_POST['password']);
//$password =md5($password);
if(empty($res['errors'])) {
$result = $mysqli->query("SELECT uid FROM users where email='$email' and password = '$password'");
if($result->num_rows == 1){
$res['success'] = true;
}
else{
array_push($res['errors'], 'Invalid login details');
$res['success'] = false;
}
}else{
$res['success'] = false;
}
echo json_encode($res);
}
clean function is not working as expected because sql queries return false if i enter username and password correct.
So, it seems like this is not valid in mysqli case.
I checked this link PHP MySQLI Prevent SQL Injection and got to know that we have to prepare query.
I can see there is an example but i am not able to understand how to prepare/bind if i have to use two or more form data.
Thanks for your time.
Updated code
$result = $mysqli->prepare("SELECT uid FROM users where email=:email and password = :password");
$result->execute([
':email' => $email,
':password' => $password]);
//$result->execute();
if($result->num_rows == 1){
//if(mysqli_num_rows($result) === 1) {
$res['success'] = true;
}
else{
array_push($res['errors'], 'Invalid login details');
$res['success'] = false;
}
As already stated in comments, you need to be consistent with your API choice. You can't mix APIs in PHP.
You started out with mysqli_*, so I'll continue with that. You had some mysql_* and PDO in there, and it might not be a bad idea to use PDO over mysqli_* - but if your server supports mysqli_*, there is nothing wrong with using that. See Choosing an API and decide for yourself (just stay away from mysql_*, it's outdated).
Using mysqli_*, you connect to the database like this (you didn't show your connection).
$mysqli = new mysqli("host", "username", "password", "database");
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: (".$mysqli->connect_errno.") ".$mysqli->connect_error;
}
$mysqli->set_charset("utf8");
As for preventing SQL injection in it self, all you need is to use prepared statements. You can still clean or sanitize your data if there are some kind of values you don't want sitting in your tables - but that's kind of another discussion.
You also need to know if your passwords are hashed in the database. They really should be, and you should be using password_hash($password, $algorithm) and password_verify($password, $hash) if you're on PHP5.5 and above (if not, look into something like password_compat).
You need to be consistent with your hashes too, you can't insert it with md5 and selecting it with no hash. It all needs to be the same. Because if you are selecting an md5 hash, and comparing it to an unhashed string, they will be different, and the query fails.
I'm showing you an example of using password_verify(), so that means that the password stored in the database will also need to be stored with password_hash() (or your query fails).
if ($stmt = $mysqli->prepare("SELECT uid, password FROM users where email=?")) {
$stmt->bind_param("s", $_POST['email']); // Bind variable to the placeholder
$stmt->execute(); // Execute query
$stmt->bind_result($userID, $password); // Set the selected columns into the variables
$stmt->fetch(); // ...and fetch it
if ($stmt->num_rows) {
if (password_verify($_POST['password'], $password)) {
// Password was correct and matched the email!
} else {
// Password was incorrect...
}
} else {
// Accountname not found
}
}
This is just a basic example, but it will get you started. Never trust user input, use prepared statements.
You can bind more variables like so:
$stmt = $mysqli->prepare("SELECT uid FROM users where email= ? and password = ?");
$stmt->bind_param('ss', $email, $password);
/* execute prepared statement */
$stmt->execute();
As you can see, you can expand on the bind_param() function. You can also add different type of variables:
i corresponding variable has type integer
d corresponding variable has type double
s corresponding variable has type string
b corresponding variable is a blob and will be sent in packets
From: http://php.net/manual/en/mysqli-stmt.bind-param.php
First of all, I suggest you learn PDO instead of MySQLi, just because it supports more drivers.
Second, you use mysql_real_escape_string, as you might see, that is a MySQL function, not a MySQLi function.
So where you have:
$result = $mysqli->query("SELECT uid FROM users where email='$email' and password = '$password'");
You should do something like:
<?php
$stmt = $dbConnection->prepare("SELECT uid FROM users where email = :email AND password = :password");
try{
$stmt->execute([
':email' => $email,
':password' => $password
]);
}
catch(Exception $e){
echo $e->getMessage(); //Remove when putting online
}
if($stmt->num_rows){
$res['success'] = true;
}
?>
You're presently mixing MySQL APIs/functions with mysql_real_escape_string(), then num_rows and then a PDO binding method where email=:email and password = :password which seems to have been taken from another answer given for your question.
Those different functions do NOT intermix.
You must use the same one from connection to querying.
Consult: Can I mix MySQL APIs in PHP?
It looks like you're wanting to setup a login script. I suggest you use the following and pulled from one of ircmaxell's answers:
Pulled from 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
}
It's safer and uses a safe password hashing method, rather than what you seem to want to use is MD5 $password =md5($password); and is no longer considered safe to use now.
References:
PDO connection http://php.net/manual/en/pdo.connections.php
PDO error handling http://php.net/manual/en/pdo.error-handling.php
To check if a user exists, you can see one of my answers https://stackoverflow.com/a/22253579/1415724
http://php.net/manual/en/mysqli.error.php
http://php.net/manual/en/function.error-reporting.php
Sidenote: If you do go that route, remember to read the manuals and that your password column is long enough to hold the hash. Minimum length is 60, but they recommend 255.
It is also unclear if your HTML form does have name attributes for the POST arrays, so make sure the form is using a POST method.
http://php.net/manual/en/tutorial.forms.php
I believe I have given you enough information to get started.
What you must NOT do, is to use the above with your present code and simply patching it. You need to start over.
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: Displaying errors should only be done in staging, and never production.

PHP/MySQL - Checking results

I'm trying to create a login system with PHP, but the SQL query is not returning the result I'm expecting.
I have a typical username and password page, and I'm using what the user types in there to check for an account. I know for a fact that the database contains real usernames and passwords but the call to mysqli_num_rows is always returning 0.
Is there something I'm doing wrong?
$username = $_POST['username'];
$password = $_POST['password'];
$result = mysqli_query($con, "SELECT * FROM StaffTable WHERE staffNo='$username' AND password='$password'");
echo mysqli_num_rows($result); //This always prints out 0.
if(mysqli_num_rows($result) == 1)
{
echo "OK";
}
Ignoring the plain-text-password thing which you claim to be aware of, something like this perhaps...
$username = isset($_POST['username']) ? $_POST['username'] : null;
$password = isset($_POST['password']) ? $_POST['password'] : null;
$stmt = $con->prepare('SELECT 1 FROM StaffTable WHERE staffNo = ? AND password = ?');
if (!$stmt) {
throw new Exception($con->error, $con->errno);
}
$stmt->bind_param('ss', $username, $password);
if (!$stmt->execute()) {
throw new Exception($stmt->error, $stmt->errno);
}
if ($stmt->fetch()) {
echo 'OK';
}
To summarise...
I've checked that the input variables are set and assigned defaults if they're not that shouldn't produce any false positives
I've used a prepared statement with bound parameters to avoid SQL injection vulnerabilities
I throw exceptions when errors occur. These are great because they halt execution and give you all the information you need to debug the problem.
This is my main problem with mysqli over PDO. mysqli is simply not noisy enough when errors occur. You shouldn't have to manually check for error conditions all the time.
I've changed the query to a simple boolean check as that's all you were using it for. The row either exists, or it doesn't.
Try something more along the lines of
$username=$_POST['username'];
$password=md5($_POST['password']);
$query="SELECT * FROM StaffTable WHERE staffNo='".$username."' AND password='".$password."'";
$result=mysqli_query($con,$query);
if (mysqli_num_rows($result)==0)
{
echo "Incorrect Password Or Username Combo";
}
else {
while($row=mysqli_fetch_object($result)) {
$_SESSION['id']=$row['id'];
}
I would say to start with at least running the passwords in encryption for now and look into SQL injection and upgrade as you learn more about what you're looking at.
The biggest flaw in yours aside from what's already been pointed out is
($con, "SELECT * FROM StaffTable WHERE staffNo='$username' AND password='$password'");
With the variables you cannot put them within the query that way; you would want to do something more along the lines of
($con, "SELECT * FROM StaffTable WHERE staffNo='".$username."' AND password='".$password."'");
If you'll notice I escaped from the plain text so that the variables would be set. The reason you're returning 0 results everytime is because you are actually searching for username $username with $password as their password.
Good luck!

PHP MySQLI (OOP?) - The code doesn't work at all

I'm kinda new to the OOP(? If this IS OOP, I don't know) language, and I'm trying to make a simple login-proccess, with MySQLi. The problem are, that the code doesn't work. I can't login (and It's not showing me any errors) and I can't register an new account (same problem) - It's like the code are dead or something.
I'm not sure I've done it right, but this is my best, so far. 'cause I'm new to OOP(?).
Index.php:
<?php
if(isset($_POST['submit'])) {
$username = mysql_real_escape_string($_POST['username']);
$password = mysql_real_escape_string(md5($_POST['password']));
$userControl = "SELECT * FROM users WHERE username='".$username."' AND password='".$password."'";
$userControlResult = $mysqli->query($userControl);
if($mysqli->num_rows($userControlResult) > 1) {
$userRow = $mysqli->fetch_assoc($userControlResult);
$dbid = $userRow['id'];
$dbuser = $userRow['username'];
$_SESSION['id'] = $dbid;
$_SESSION['username'] = $dbuser;
header("location: me.php");
die();
} else {
echo "<div class='errorField'>Användarnamnet eller lösenordet är fel!</div>";
}
}
?>
I suppose that if I can solve the first error, I can solve the second too.
Thanks!
Many things I would recommend changing about your code:
Don't use mysql_real_escape_string() if you're using mysqli. You can't mix these APIs.
No need to escape a string returned by md5(), because it's guaranteed to contain only hexadecimal digits.
Don't use mysqli_real_escape_string() anyway -- use parameters instead.
Always check if prepare() or execute() return false; if they do, then report the errors and exit.
You can get a mysqli result from a prepared statement using mysqli_stmt_store_result().
Don't SELECT * if you don't need all the columns. In this case, you already have $username so all you really need to fetch is the id column.
No need to check the number of rows returned, just start a loop fetching the rows (if any). Since you exit inside the loop, your "else" error clause will be output only if the loop fetches zero rows.
Consider using a stronger password hashing function than MD5. Also, add a salt to the password before hashing. Read You're Probably Storing Passwords Incorrectly.
Example:
<?php
if(isset($_POST['submit'])) {
$username = $_POST['username'];
$password = md5($_POST['password']);
$userControl = "SELECT id FROM users WHERE username=? AND password=?";
if (($userControlStmt = $mysqli->prepare($userControl)) === false) {
trigger_error($mysqli->error, E_USER_ERROR);
die();
}
$userControlStmt->bind_param("ss", $username, $password);
if ($userControlStmt->execute() === false) {
trigger_error($userControlStmt->error, E_USER_ERROR);
die();
}
$userControlResult = $userControlStmt->store_result();
while($userRow = $userControlResult->fetch_assoc()) {
$_SESSION['userid'] = $userRow["id"];
$_SESSION['username'] = $username;
header("location: me.php");
die();
}
// this line will be reached only if the while loops over zero rows
echo "<div class='errorField'>Användarnamnet eller lösenordet är fel!</div>";
}
?>
A good command to enter at the top of the script (under the
ini_set('display_errors', 1);
This will display any errors on your script without needing to update the php.ini (in many cases). If you try this, and need more help, please post the error message here and I'll be able to help more.
Also, if you are using $_SESSION, you should have
session_start();
at the top of the script under the
Make sure your php is set to show errors in the php.ini file. You'll need to do some research on this on your own, but it's fairly easy to do. That way, you'll be able to see what the error is and go from there.

Updating MySQL database with MD5 value

Having searched thoroughly through my code, the only reason that I could determine for this error is that the technique I am using for converting the string to MD5 is invalid. However I cannot find another way to do so.
$username = $_POST['username'];
$password = $_POST['password'];
$repassword = $_POST['repassword'];
if( $password=$repassword ) {
$con=mysql_connect("localhost", "root", "");
if( $con == true ) {
mysql_select_db("movedb", $con);
//$newpassword = mysql_real_escape_string(md5($_POST['password']));
$query = "UPDATE user SET password=MD5('$password') WHERE username='$username'";
// $query = "UPDATE user SET password='$newpassword' WHERE username='$username'";
$result = mysql_query($query, $con);
if( $result == true ) {
echo "Successfully saved your message";
} else {
echo mysql_error();
}
mysql_close($con);
} else {
echo "Cannot connect to the database";
}
} else {
echo "Passwords do not match!";
}
Any ideas on how to update this MD5 value from PHP
$password = md5($password);
$query = "UPDATE user SET password='".$password."' WHERE username='".$username."'";
Use PHP supported md5 hash.
An issue that can cause problems is that MySQL and PHP use different default salts when they encrypt. This means that the resulting strings will be different. So you have to use either PHP or MySQL to encrypt and not a mixture of the 2.
Secondly, MD5 has been superceded by other better encryption algorithms. You might consider using one of those for improved security. Check out PHP's crypt() function.
To check the password:
SELECT * FROM 'user' WHERE username='bob.jhonny' AND pass=MD5('oldPassword');
To update:
UPDATE 'dlp_contatcs'.'user' SET 'Pass'=MD5('NewPassword') WHERE 'Username'='bob.jhonny';
Warning:
Please, don't use mysql_* functions to write new code. They are no longer maintained and the community has begun the deprecation process. See the red box?
Instead, you should learn about prepared statements and use either PDO or MySQLi. This article should give some details about deciding which API to use. For PDO, here is a good tutorial.
You can calculate the md5() hash with PHP and store it into a variable, then put that variable into the database. Just make sure you do the same conversion (md5 in the PHP code body) when checking against the database.
You should fix the line if( $password=$repassword ). You need either two or three = signs to make the if check against something. The proper line would be if( $password === $repassword ).
// ...
$newpassword = md5($_POST['password']);
$result = mysql_query('UPDATE user SET password="' .mysql_real_escape_string($newpassword). '" WHERE username = "' .mysql_real_escape_string($username). '"', $con);
if ( $result === TRUE )
{
echo "Successfully saved your message.";
// ...

Categories