Using a whitelist on user input - php

I have a a simple form to login using a username and password. I want to apply a whitelist to allow only certain characters. I dont know if anybody requires this but here is the code to retrieve the username and password:
$stmt = $conn2->prepare("SELECT username FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();
$stmt->store_result();
Do I incorporate something like this:
preg_replace( "/[^a-zA-Z0-9_]/", "", $stringToFilter );
If so, where do I include it within my code? And what happens if a user tries to input something other than what is in the whitelist?
ADDED: Ok well what about if it is during registration and it is using INSERT to store username and password?
//insert data
$stmt = $conn2->prepare("INSERT INTO users (username, email, password) VALUES (?, ?, ?)");
//bind the parameters
$stmt->bind_param('sss', $username, $email, $password);

Add the filtering code before your INSERT during registration. Check that the string is not empty after filtering, so that a username of "!!*&%$#()*&#$" does not get inserted as a blank string.
$username_clean = preg_replace( "/[^a-zA-Z0-9_]/", "", $_POST['username'] );
if (!strlen($username_clean)){
die("username is blank!");
}
$stmt = $conn2->prepare("INSERT INTO users (username, email, password) VALUES (?, ?, ?)");
$stmt->bind_param('sss', $username_clean, $email_clean, $password_clean);

Related

Some values do not submit: two different SQL's

In my last question people said that I need to use prepared statements to avoid SQL injection.
I'm changing the previous SQL's now to prepared statements, as y'all wanted.
The thing is, it submits the settings, this part:
$stmt_setsettings = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt_setsettings, $usersettings_sql)) {
array_push($errors, "Safe SQL failed, could not insert settings. Contact the helpdesk.");
} else {
mysqli_stmt_bind_param($stmt_setsettings, "sssss", $email_show, $fname_show, $lname_show, $private_account, $profile_style);
mysqli_stmt_execute($stmt_setsettings);
}
But it submits none of the actual info I need (like the username, firstname, ...)
Also, at the end of the code below it should redirect to the new profile, normally if this feels it should display "Something went wrong, refer to the helpcenter. (SE100)" but it like refreshes the sign up page and throws no error, while there is an error: the not submitting info!
I tried searching up similar questions or fixes but nothing useful found.
Can you check out the following code and let me know what is the deal with the not submitting values? Thanks!
// Finally, register user if there are no errors in the form
if (count($errors) == 0) {
$password = md5($password_1); // Encrypt the password before saving in the database
$user_ip = $_SERVER['REMOTE_ADDR']; // Getting the IP of the user
$bio = $config['default-bio']; // Setting default biography
$profileimg = $config['default-profileimg']; // Setting default profile image
$timestamp = date('d.m.Y'); // Defining the current date
$activity = "on"; // Defining which state the user profile is in, online
$userdata_sql = "INSERT INTO users (username, bio, activity, profileimg, regdate, email, password, firstname, lastname, gender, birthday, country, ip)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$usersettings_sql = "INSERT INTO usersettings (show_email, show_fname, show_lname, private_acc, profile_style)
VALUES (?, ?, ?, ?, ?)";
$stmt_signup = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt_signup, $userdata_sql)) {
array_push($errors, "Safe SQL failed, could not sign up. Contact the helpdesk.");
} else {
mysqli_stmt_bind_param($stmt_signup, "sssssssssssss", $username, $bio, $activity, $profileimg, $regdate, $email, $password, $fname, $lname, $sex, $bday, $country, $user_ip);
mysqli_stmt_execute($stmt_signup);
}
$stmt_setsettings = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt_setsettings, $usersettings_sql)) {
array_push($errors, "Safe SQL failed, could not insert settings. Contact the helpdesk.");
} else {
mysqli_stmt_bind_param($stmt_setsettings, "sssss", $email_show, $fname_show, $lname_show, $private_account, $profile_style);
mysqli_stmt_execute($stmt_setsettings);
}
session_regenerate_id();
$_SESSION['username'] = $username;
$_SESSION['loggedin'] = true;
// Generate user id
$generateid_sql = "SELECT id FROM users WHERE username=? ORDER BY id";
$stmt_generateid = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt_generateid, $generateid_sql)) {
array_push($errors, "Safe SQL failed, could not generate a new ID. Contact the helpdesk.");
} else {
mysqli_stmt_bind_param($stmt_generateid, "s", $username);
mysqli_stmt_execute($stmt_generateid);
$generateid_result = mysqli_stmt_get_result($stmt_generateid);
}
while ($id = mysqli_fetch_assoc($generateid_result)) {
if ($id['username'] <= 0) { // Checking if the user id is a valid id (not below or equal to 0), and if not, displaying a critical error
array_push($errors, "Something went wrong whilst signing up, please refer to the helpcenter. (SE100)");
}
if ($id['username'] > 0) { // Redirecting the user to his or her profile if it is a valid id
header('location: /content/users/profile?id=' . $id['username'] . '');
}
}
}
}
First off, PLEASE don't ever store passwords like this:
$password = md5($password_1); // <-- Totally insecure
Instead use the built-in password_hash() and password_verify() functions. See https://www.php.net/manual/en/faq.passwords.php for a good overview of why md5() is not secure and examples how to handle password storage correctly.
Also, I'd recommend pulling the user out of the database and validating the password, BEFORE setting $_SESSION['loggedin'] = true.
Regarding your question, I'd recommend adding some additional error handling and result checking around your calls to $conn->prepare() and $stmt->bind_param. See mysqli_stmt_execute() does not execute the prepared query for examples of how to check $stmt->errors.
Another general recommendation is checking $stmt->affected_rows to see if your insert statements are actually being executed as you expect. Your inserts should each be affecting 1 row.
Lastly, turning on the MySQL query log can be a great troubleshooting tool: How to show the last queries executed on MySQL? . Are all the SQL queries in your code showing up in the log? Try running the queries manually and see if the results look right.
// Finally, register user if there are no errors in the form
if (count($errors) == 0) {
$password = md5($password_1); // Encrypt the password before saving in the database
$user_ip = $_SERVER['REMOTE_ADDR']; // Getting the IP of the user
$bio = $config['default-bio']; // Setting default biography
$profileimg = $config['default-profileimg']; // Setting default profile image
$timestamp = date('d.m.Y'); // Defining the current date
$activity = "on"; // Defening wich state the user profile is in, online
$userdata_sql = "INSERT INTO users (`username`, `bio`, `activity`, `profileimg`, `regdate`, `email`, `password`, `firstname`, `lastname`, `gender`, `birthday`, `country`, `ip`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$usersettings_sql = "INSERT INTO usersettings (`show_email`, `show_fname`, `show_lname`, `private_acc`, `profile_style`)
VALUES (?, ?, ?, ?, ?)";
$stmt_signup = $conn->prepare($userdata_sql);
$stmt_signup->bind_param("sssssssssssss", $username, $bio, $activity, $profileimg, $timestamp, $email, $password, $fname, $lname, $sex, $bday, $country, $user_ip);
if(!$stmt_signup->execute()){
array_push($errors,mysqli_error($conn));
}
$stmt_setsettings=$conn->prepare($usersettings_sql);
$stmt_setsettings->bind_param("sssss", $email_show, $fname_show, $lname_show, $private_account, $profile_style);
if(!$stmt_setsettings->execute()){
array_push($errors,mysqli_error($conn));
}
session_regenerate_id();
$_SESSION['username'] = $username;
$_SESSION['loggedin'] = true;
// Generate user id
$generateid_sql = "SELECT `id`,`username` FROM `users` WHERE `username`=? ORDER BY `id` limit 1";
$stmt_generateid=$conn->prepare($generateid_sql);
$stmt->generateid->bind_param("s", $username);
if(!$stmt_generateid->execute()){
array_push($errors,mysqli_error($conn));
}else{
$generateid_result = $stmt_generateid->get_result();
}
$username_assoc = mysqli_fetch_assoc($generateid_result);
if ($username_assoc['id'] > 0) {
// Redirecting the user to his or her profile if it is a valid id
header('location: /content/users/profile?id=' . $username_assoc['username'] . '');
}else{
array_push($errors, "Something went wrong whilst signing up, please refer to the helpcenter. (SE100)");
}
}

PHP create user in mysql table [duplicate]

This question already has an answer here:
What to do with mysqli problems? Errors like mysqli_fetch_array(): Argument #1 must be of type mysqli_result and such
(1 answer)
Closed 1 year ago.
if ($stmt = $connection->prepare('INSERT INTO users (name, id, password, email, city, avatar, about, activation_code) VALUES (?, ?, ?, ?, ?, ?, ?, ?)')) {
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
$uniqid = uniqid();
$stmt->bind_param('ssssssss', $_POST['name'], $_POST['id'], $password, $email, $_POST['city'], $_POST['avatar'], $_POST['about'], $uniqid);
$stmt->execute();
$stmt->store_result();
echo 'Account's created';
} else {
echo 'Error';
}
This part of code doesn't create user in myqsl db. But if I
This code:
$stmt->bind_param('ssssssss', $_POST['name'], $_POST['id'], $password, $email, $_POST['city'], $_POST['avatar'], $_POST['about'], $uniqid);
Replace with:
$stmt->bind_param('ssssssss', $_POST['name'], $_POST['id'], $email, $password, $_POST['city'], $_POST['avatar'], $_POST['about'], $uniqid);
It create user but in table in email there is password and in password - email.
How I can fix it???
You need to check out what the error reported by MySQL says.
Not having seen your table definition (you really should post that too), I can only guess that the password you use - the hash - being as it is a PK2DBF hash, is too long for the password field.
You probably reserved something like 64 chars for the email and, what do I know, 16 characters for the password. But the password hash is longer. So if you insert the password in the email column it fits, the other way it doesn't.
You should use something like VARCHAR(200) for the password column definition field.
check the sql datatypes of the email and password columns and their respective lengths, the hash generated is probably too long or the email column does not allow certain inputs.

I am trying to send three mysql prepared statements in the same section [duplicate]

This question already has answers here:
PHP parse/syntax errors; and how to solve them
(20 answers)
Closed 3 years ago.
The problem I am facing is that I am not able to take the users id and send it through.
Here is the code.
if ($stmt = $con->prepare('INSERT INTO tblusers (user, password, token) VALUES (?, ?, ?)')) {
// We do not want to expose passwords in our database, so hash the password and use password_verify when a user logs in.
$token = password_hash($_POST['token'], CRYPT_BLOWFISH);
$password = password_hash($_POST['password'], CRYPT_BLOWFISH);
$stmt->bind_param('sss', $_POST['username'], $password, $token);
$stmt->execute();
$stmt = $con->('SELECT id from tblusers where user=?');
$user=$_POST['username'];
$stmt->bind_param('s' $user);
$stmt->execute();
$stmt -> bind_result($id);
$stmt = $con->prepare('INSERT INTO tblbtc (id) VALUES (?)');
$stmt->bind_param('i', $id);
$stmt->execute();
header('location: ../../home/index.php');
} else {
// Something is wrong with the sql statement, check to make sure accounts table exists with all 3 fields.
echo ('Could not prepare statement!');
}
}
$stmt->close();
}
Here is also a error message I get
Parse error: syntax error, unexpected '(', expecting identifier (T_STRING) or variable (T_VARIABLE)
This code down below works without the two extra added mysql statements.
if ($stmt = $con->prepare('INSERT INTO tblusers (user, password, token) VALUES (?, ?, ?)')) {
// We do not want to expose passwords in our database, so hash the password and use password_verify when a user logs in.
$token = password_hash($_POST['token'], CRYPT_BLOWFISH);
$password = password_hash($_POST['password'], CRYPT_BLOWFISH);
$stmt->bind_param('sss', $_POST['username'], $password, $token);
$stmt->execute();
header('location: ../../home/index.php');
} else {
// Something is wrong with the sql statement, check to make sure accounts table exists with all 3 fields.
echo ('Could not prepare statement!');
}
}
$stmt->close();
}
The expected results of this code it to create the user which works and then to take the users id and also create columns on the tblbtc with the userid/.
You can get the inserted user id using mysqli::inserted_id
see the code below
<?php
if ($stmt = $con->prepare('INSERT INTO tblusers (user, password, token) VALUES (?, ?, ?)')) {
// We do not want to expose passwords in our database, so hash the password and use password_verify when a user logs in.
$token = password_hash($_POST['token'], CRYPT_BLOWFISH);
$password = password_hash($_POST['password'], CRYPT_BLOWFISH);
$stmt->bind_param('sss', $_POST['username'], $password, $token);
$stmt->execute();
$user_id = $stmt->insert_id;
if($user_id)
{
$stmt = $con->prepare('INSERT INTO tblbtc (id) VALUES (?)');
$stmt->bind_param('i', $user_id);
$stmt->execute();
header('location: ../../home/index.php');
}
else{
echo ('Could not prepare statement!');
}
} else {
// Something is wrong with the sql statement, check to make sure accounts table exists with all 3 fields.
echo ('Could not prepare statement!');
}
$stmt->close();

bind_param doesn't replace ?s in my prepared statement

It registers the user successfully. But when I check it on my database, all of the values are 0s. What's the problem?
here's the function code:
public function insertUser($email, $firstName, $lastName, $encryptedPassword, $salt)
{
//SQL language - command to insert data
$sql = "INSERT INTO users (email, firstName, lastName, password, salt) VALUES (email=?, firstName=?, lastName=?, password=?, salt=?)";
//preparing SQL for execution by checking the validity
$statement = $this->conn->prepare($sql);
//if error
if (!$statement)
{
throw new Exception(($statement->error));
}
//assigning variables instead of '?', after checking the preparation and validity of the SQL command
$statement->bind_param('sssss', $email, $firstName, $lastName, $encryptedPassword, $salt);
//result will store the status/result of the execution of SQL command
$result = $statement->execute();
return $result;
}
The parameters for the function get set with the correct values when called, I tested it
I'm pretty new to PHP. If i correct my function, it doesn't create a new user. It doesn't even print out anything in the browser window. Here's the piece of code that calls this one (maybe it helps you with finding the solution):
$result = $access->insertUser($email, $firstName, $lastName, $encryptedPassword, $salt);
//result is positive
if ($result)
{
//throw back the user details
$return['status'] = '200';
$return['message'] = 'Successfully registered';
$return['email'] = $email;
$return['firstName'] = $firstName;
$return['lastName'] = $lastName;
echo json_encode($return);
$access->disconnect();
}
Your query is wrong.
//columns are declared here
$sql = "INSERT INTO users (email, firstName, lastName, password, salt) VALUES (email=?, firstName=?, lastName=?, password=?, salt=?)";
//you do not need to declare your columns again
Simple change your query to
$sql = "INSERT INTO users (email, firstName, lastName, password, salt) VALUES (?, ?, ?, ?, ?)";
Also, it appears as though you are storing your password and the salt separately, that tells me you are rolling your own hashing algorithm, there isn't really a need for this. I would remove your salt column, and use password_hash() for your password column.
remove the column=?
$sql = "INSERT INTO users (email, firstName, lastName, password, salt) VALUES (?, ?, ?, ?, ?)";
the code
column=?
in your value assignment is evalued as boolean condition that return false (0)

Register/Login Notworking android/PHP

Hi guys I set up a table on 000webhost. I set it up with a column for id, name, username, age and password. For some reason the username does not show up in the table when I run the code for the register and Im not sure what the error is. Here is the code for Register.php:
<?php
$con = mysqli_connect("*****", "****", "*****", "****");
$name = $_POST["name"];
$age = $_POST["age"];
$username = $_POST["username"];
$password = $_POST["password"];
$statement = mysqli_prepare($con, "INSERT INTO user (name, username, age, password) VALUES (?, ?, ?, ?)");
mysqli_stmt_bind_param($statement, "siss", $name, $username, $age, $password);
mysqli_stmt_execute($statement);
$response = array();
$response["success"] = true;
echo json_encode($response);
?>
As I originally stated in comments:
You're trying to insert a string using the i parameter being an integer.
The order matters when binding.
You need to change your present parameters to ssis while making sure the age column is indeed an integer type.
Checking for errors on the query would have told you about it.
http://php.net/manual/en/mysqli.error.php
I also hope you're not storing plain text passwords. Use password_hash() if you plan on going live with this.
http://php.net/manual/en/function.password-hash.php
Sorry to be the bearer of bad news, but you will be hacked should this be the case.
Using a prepared statement without using a safe password hashing function won't guarantee your site from being compromised.
Your bind statement has incorrect format specifiers. Change this line
mysqli_stmt_bind_param($statement, "siss", $name, $username, $age, $password);
To
mysqli_stmt_bind_param($statement, "ssis", $name, $username, $age, $password);
Those specifiers need to match the column and variable type. S for string and i for Int

Categories