Password reset script only fires half the time - php

I had an inefficient piece of code for resetting passwords based on a user entering either their username or their email address. The PHP script branched depending on the identifier used. I collapsed it into one which now works if the user enters their username but not if they enter their email address. Here is the salient code:
$identifier = isset($_POST["username"])?"username":"email";
$ident = isset($_POST["username"])?trim(mysqli_real_escape_string($mysqli,(check_chars_username($_POST["username"])))):trim(mysqli_real_escape_string($mysqli, (check_chars_email($_POST["email"]))));
//create and issue the query
$sql = "SELECT * FROM aromaMaster WHERE $identifier = '$ident'";
$sql_res =mysqli_query($mysqli, $sql) or die(mysqli_error($mysqli));
if(mysqli_num_rows($sql_res) == 0) {
//wrong login info
header("Location: password_reset_form.html/error=$ident");
exit();
}
$info = mysqli_fetch_array($sql_res);
$userid = $info["id"];
$username = stripslashes($info["username"]);
$email = stripslashes($info["email"]);
I have checked and doubled checked that the email form field is called email and it is. It's got me scratching my head. Particularly interesting is the header redirect. When I enter an email address and am redirected, the variable $ident appears empty.

As you've noted in your comment, you have to check for the username variable of the $_POST array to be empty.
It's also a good idea to check if the variable is even there in the first place in addition to and before you test against it being blank.
$identifier =
(isset($_POST["username"]) && !empty($_POST["username"])) ? "username":"email";
When you're sending your form across, all of the text input fields will come through, even if they're blank. Blank is not the same as empty. That's the reason the first part of the ternary operator is always true in your initial code.

Related

How do I double check my PHP signin form

I made a signin form that will look through the database and find a match to the user's credentials, but how do I fix this code so it will relocate the page if there is no match.
<?php
session_start();
include_once 'includes/dbh.php';
$username = $_POST['u_name'];
$password = $_POST['pwd'];
$sql = "SELECT * FROM users;";
$result = mysqli_query($conn, $sql);
while ($row = mysqli_fetch_assoc($result)) {
if ($username == $row['username'] && $password == $row['password']) {
$_SESSION['username'] = $username;
header("Location: second_index.php?signinSuccessful");
}
if ($username != $row['username'] && $password != $row['password']) {
header("Location: index.php?NotSucessful");
}
}
I tried putting the code inside of the loop, but I know that can't work, and if I put it outside of the loop, It redirects even if the credentials are correct. Please help. Thanks
First of all, this is totally wrong, you're looping trough all the users to see if the user exist, instead of that sql statement try $sql = "SELECT * FROM users where user='$user' and password='$password'";
And to avoid any data breach in that sql statemen you have to serialize the user and pass like that before adding it to the statement
$user = mysql_real_escape_string($conn, $user);
$password =mysql_real_escape_string($conn, $password);
Then you only check if the fields aren't empty (which means the user exist)
You are getting all the users from the users table and checking each record manually in php.
The reason why your code doesn't work is because the while loop doesn't check all the users in user table. If the first record in the retrieved table data doesn't match with entered username and password, it will go to 2nd if block and redirect.
You should change your query to filter by user-entered values.
SELECT * FROM USERS WHERE USERNAME = 'username' AND PASSWORD='password'
And later check in php if any record is returned. If any record is returned, it is a valid user, else redirect the user to failed authentication page.
As a good practice, make sure to use parameterized query.
Update Replace the while loop and block with this.
if(mysqli_num_rows($result) > 0){
// valid user
}else{
// invalid user
}
Why do you need while loop in this case when you fetching data from database? Using sql and make the database fetch the only one correct answer, don't make server site do unnecessary work.
I propose just do simple fetch then if check, no need for while loop at all.
Your logic is always redirect to index.php when username password not correct so of course it will always do so when your while loop on server do not hit the correct user.

Updating database info from php, not saving

I have this code and it seems to be working. The values are updating, but when I reload the page the updated values are without any value. For example now I have set the title as "blablabla" and when I reload the page it's changing to "".
This is the code
<?php
$title = $_POST['title'];
$meta = $_POST['meta'];
$email = $_POST['email'];
$analytics = $_POST['analytics'];
$query = "UPDATE websettings SET title = '$title', meta = '$meta', email = '$email', analytics = '$analytics' WHERE id = '1'";
if(mysql_query($query)){
echo "success";
}
else {
echo "fail";
}
?>
Your code applies $_POST variables to the database, but doesn't check if the client actually posted anything. Better to check if $_POST contains array items (if a form was posted), and check if each of those is set (if the user filled in the right fields), and validate the user input before saving (phone numbers, emails etc formatted correctly).
And as was pointed out in the comments you are vulnerable to SQL injection attack - one of the first things you should address.
Try turning on more PHP errors too - these would flag as unset variables for quicker fixing.

MySQL multiple queries not working

Problem has been solved
I have created a form that processes the changing of user information from the admin side e.g. the admin changes a user's username and/or email. I am having trouble processing multiple queries.
For example, if the admin changes the username, the query works. If the admin changes the email address, the query works. But if the admin changes the username and email at the same time through the form then only the username changes.
Any ideas? I will submit my code but I will change variables for security reasons etc. Also, anything in capitals has been changed for security reasons. The code is all correct for each individual function because as I said, if I ONLY change the email, it works and actually changes. But if I change the username AND email, only the username will change despite the fact the email query runs and it echo's the email has been changed!
Also, it is worth noting that all of the fields e.g. username field and email field are part of one form that submits to one page.
if (isset($_POST['SUBMIT_BUTTON_PRESSED'])) {
//Gather all inputs from the form and sanitise it.
//REMOVED FOR SECURITY REASONS.
if($USERNAME_NEW != "") {
if($USERNAME_NEW == $CURRENT_USERNAME) {
echo "You have entered the username you are already using. Please enter a different username.";
} else {
$CHECK_USERNAME = "SELECT USERNAME_ROW FROM USERS_TABLE WHERE username='$USERNAME_NEW'";
$RUN_QUERY = mysqli_query($CONNECTION INFO, $CHECK_USERNAME);
$RESULT = mysqli_num_rows($RUN_QUERY);
if($RESULT > 0) {
echo "That username already exists. You cannot use that username again. Please enter another username.";
} else {
$editing_username = true;
$USERNAME = $NEW_USERNAME; //NOT NEEDED BUT IT STILL WORKS
$THE_SQL_QUERY = "UPDATE USER_TABLE SET username='$USERNAME' WHERE username='$ORIGINAL USERNAME'";
$RUN_THIS_QUERY= mysqli_query($CONNECTION INFO, $THE_SQL_QUERY);
echo "The user's username has been changed to: ". $USERNAME;
}
}
}
if($EMAIL != "") {
if($EMAIL == $CURRENT_EMAIL) {
echo "You have entered the same email address to the one you are already using. Please enter a different email address.";
} else {
$CHECK_EMAIL = "SELECT USERS_EMAIL FROM USER_TABLE WHERE username='$USER'";
$CHECK_EMAIL_QUERY = mysqli_query($CONNECTION_INFO, $CHECK_EMAIL);
$RESULT = mysqli_num_rows($CHECK_EMAIL_QUERY);
if($RESULT > 0) {
echo "That email already exists. You cannot use that username again. Please enter another username.";
} else {
$editing_email = true;
$THE_NEW_EMAIL = $FINAL_EMAIL_THING; // AGAIN NOT NEEDED BUT STILL WORKS
$THE_SQL= "UPDATE USER_TABLE SET USER_EMAIL='$EMAIL' WHERE username='$USER' LIMIT 1"; // REMOVED THE LIMIT 1, STILL DOESN'T WORK
$RUN_THIS_QUERY = mysqli_query($CONNECTION, $THE_SQL);
if($RUN_THIS_QUERY) {
echo "The user's email has been changed."; // EVEN WHEN BOTH FIELDS ARE SUBMITTED THIS WORKS SO THE QUERY IS RUNNING BUT THE EMAIL DOESN'T CHANGE
}
}
}
}
Thanks for the help! Also, no un-witty remarks about how my question is structured etc. because I don't care to be honest. I just want this code working to be honest because I've been working on it for a while. This may be something simple or I might be using the wrong approach for this type of form submission.
Remember: THIS CODE DOES WORK WHEN I SUBMIT EACH FIELD SEPARATELY!
Its very hard to figure out as you are not producing the real code.
I think you have missed something here.
As you are using USER_NAME as key in the SQL's, make sure that you are using the updated username in the second sets of SQL (to update the email) as they are already replaced by the first SQL.
And there is no security risk while showing your codes snippets to someone else. Hide only the username/passwords or Identities. :)

mysql_affected_rows() work-around?

I'm using this code as part of an email confirmation script. It works great, except I can't figure out a way to distinguish between when somebody has provided an invalid email address vs when they have simply refreshed the page (ie. already confirmed their account). The only think I can think of is putting a time stamp field in the users table that always gets updated, but I'm hoping there is a better way. I thought REPLACE would do the trick, but, while email is unique, it is not the primary key.
if (isset ($email, $token, $correctToken)){
$success = FALSE; //Set the $success variable so that we don't get an error when testing for it later
if ($token == $correctToken) {
$confirm = mysql_query("UPDATE users
SET conf = 'TRUE'
WHERE email = '$email'");
if (mysql_affected_rows() == 1) {
echo "Thank you! Your email address is confirmed and your account is actived.";
$success = TRUE;
}
}
if (!$success) {
echo "There was a problem with the confirmation. Try the link in your email again or contact us at Support#WiseRenters.com";
// Send email to admin to notify of error
exit;
}
}
Thanks in advance for the advice!
Billy
EDIT: The $email and $token variables are provided through $_GET or $_POST, in case that wasn't obvious.
A redirection would stop them from refreshing - but what if they click the link in their email again?
You should check if the current user is activated or not.
$sql = "SELECT id, conf FROM users WHERE email = '{$email}'";
$exec = mysql_query($sql) or die(mysql_error());
list( $id, $conf ) = mysql_fetch_row($exec);
if( $conf ) {
// Redirect them to their profile with a message saying "your account has already been activated"
header("Location: /profile?already_activated");
exit;
}
// your code
$confirm = mysql_query("UPDATE users
SET conf = 'TRUE'
WHERE id = '{$id}'");
In response to your comment:
Keep in mind this will only add an additional query for a user who has not activated yet. If they have activated then the redirect occurs and the page is still running only 1 query.
To optimize this a bit, you can select the user ID and confirmation status based on the email address. Then, if they do need to be activated, you can activate them based on user ID instead of email. Since an integer key is much faster, the combined time of the 2 queries will be about the same as the 1 query where you are updating based on a string column. I updated the code to reflect this.
Also, this page will probably not be accessed very frequently. Any optimizations from here would really be micro- and not really that helpful.
By the way I hope you are using mysql_real_escape_string on the email, and that conf is a boolean true/false not a string 'true'/'false'.

One php file not working in membership script

My membership script is working except this one file. When I type username and password in the login form the check.php gives me this message "Please enter all information". The only information on the login form is username and password. The action of the login form is posted on check.php
I need this script to check the username and md5 encrypted password in my database and redirect to member area. I'm using random passwords. This is the only problem. Here is the check.php script. Please let me know what I need to do for this to work. I got this script from someone else and they don't know how to fix it either. I don't know php. Just want to copy and paste. Thanks
============================
<?
/* Check Username Script */
session_start(); // Start Session
include 'database.php';
// Conver to simple variables
$username = $_POST['username'];
$password = $_POST['password'];
if((!$username) || (!$password)){
echo "Please enter ALL of the information! <br />";
include 'login_form.html';
exit();
}
// Convert password to md5 hash
$password = md5($password);
// check if the user info validates the db
$sql = mysql_query("SELECT * FROM users WHERE username='$username' AND password='$password' AND activated='1'");
$login_check = mysql_num_rows($sql);
if($login_check > 0){
while($row = mysql_fetch_array($sql)){
foreach( $row AS $key => $val ){
$$key = stripslashes( $val );
}
// Register some session variables!
session_register('first_name');
$_SESSION['first_name'] = $first_name;
session_register('last_name');
$_SESSION['last_name'] = $last_name;
session_register('email_address');
$_SESSION['email_address'] = $email_address;
session_register('special_user');
$_SESSION['user_level'] = $user_level;
mysql_query("UPDATE users SET last_login=now() WHERE userid='$userid'");
header("Location: members.php");
}
} else {
echo "You could not be logged in! Either the username and password do not match or you have not validated your membership!<br />
Please try again!<br />";
include 'login_form.html';
}
?>
This is the only part of the script that I could copy here. I'm using sessions. Action is POST.
It sounds like a typo, either when you set the $username $password variables, or in your form. Check that name is correct on the form inputs :)
also, it is better to use isset($username) instead of !$username. Doesn't give a warning :)
In your form, make sure the input fields that ask for the username and password have the correct name associated with it.
For example:
<input type='text' name='username'>
<input type='password' name='password'>
The value after name= is what gets passed as the variable name. To demonstrate that, the input field:
<input type='text' name='thisIsMyName'>
will show up in the PHP script as:
$_POST['thisIsMyName'];
If you post the HTML of the form that is being submitted, we can give you further details on it.
please post the content of login_form.html. I guess that this form is either using GET instead of POST or the input fields are not named "username" and "password".
Something else: This code contains a very serious security issue:
$username = $_POST['username']
mysql_query("SELECT * FROM users WHERE username='$username' AND password='$password' AND activated='1'");
This means that an attacker can manipulate the sql statement. For example the username:
admin'--
will result in this sql query:
SELECT * FROM users WHERE username='admin'--' AND password='egal' AND activated='1'
which means:
SELECT * FROM users WHERE username='admin'
And will grant access if a user named "admin" exists, ignoring the password.
Note: Filtering for -- will not help as there are number of other ways to have fun with this. You need to mysql_real_escape_string($username) to escape special characters in the input. More information is available at http://php.net/manual/en/function.mysql-real-escape-string.php

Categories