Login Server Side Logic - mysql

This question has more to do with how I am setting up my server side code for a simple login script. I'm interested in the best way to achieve my goal, which is of course to verify a users username and password against a database and present them with either a successful login, a registration page, or a username or password found, but the alternative is wrong.
Right now, I have it set up where my sql query scans the database for both the user and pass:
SELECT * FROM test WHERE userName='" + userName + "' AND pass='" + password + "'"
Problem with this approach is it either returns a true or false...I cannot tell if one of the inputs was correct and the other wasn't. It either finds the record, or it doesn't.
So I could query based on the username alone, and if found check the record for the correct password before passing the user onto a successful login. That way I know if the password is wrong, but I have no idea if the password is right and the user simply types the wrong username.
Alternatively, I could extend on that, and if the user isn't found, requery the database based on the password and determine if I can find a record but the username doesn't match. It seems like a lot of back and forth with the database, which is fine. But i'd like to hear from some experts on whether or not this is a proper approach.

I have not much idea wether stored procedure is supported in my sql or not. If it is supported then you can make SP like this way to check all cases. Below is code for MSSQL, you can check it with my sql :
IF EXISTS(SELECT [id] FROM [dbo].[users] WHERE [user_name] = #user_name AND [password] = #password)
BEGIN
SELECT 1 AS RETURNVAL --Valid User
END
ELSE IF NOT EXISTS(SELECT [id] FROM [dbo].[users] WHERE [user_name] = #user_name)
BEGIN
SELECT 0 AS RETURNVAL -- User doesn't exist
END
ELSE
BEGIN
SELECT -1 AS RETURNVAL -- Password Not Correct
END

You don't want to disclose too many information to people with bad intents trying to probe your system for available usernames (or even – god forbid – passwords that are in use).
When a login attempt failed, simply display a message stating:
Username and/or password mismatch.
As an aside, use prepared statements, rather than string concatenation when working with your database; it protects you from SQL injection attacks.
Plus – although it's not entirely clear from your code snippet – don't store plain passwords or plain password hashes. Rely on one of the many available and well tested encryption/hashing libraries e.g. PHP's crypt function (make sure you select a proper hashing function such as SHA512).
Your code in the most simplest form would then look like this:
// coming from your login page
$dbh = new PDO(…);
$sth = $dbh->prepare('SELECT `digest` FROM `users` WHERE `name` = :name LIMIT 1');
$sth->prepare(array( ':name' => $_POST['username'] ));
$result = $sth->fetch();
if($result !== FALSE && crypt($_POST['password'], $result['digest']) === $result['digest']) {
printf('You logged in successfully as %s', htmlspecialchars($_POST['username']));
} else {
echo 'Sorry, username and/or password did not match! Please try again.';
sleep(1);
exit;
}

Related

How do I use SQL statement to get data from a website if all I know is the username?

I am new to MYSQL, and I have a school task that says this:
This is the PhP code that shows how users are authenticated:
$input_uname = $_GET[’username’];
$input_pwd = $_GET[’Password’];
$hashed_pwd = sha1($input_pwd);
...
$sql = "SELECT id, name, eid, salary, birth, ssn, address, email,
nickname, Password
FROM credential
WHERE name= ’$input_uname’ and Password=’$hashed_pwd’";
$result = $conn -> query($sql);
// The following is Pseudo Code
if(id != NULL) {
if(name==’admin’) {
return All employees information;
} else if (name !=NULL){
return employee information;
}
} else {
Authentication Fails;
}
I have tried so many different things like this:
SELECT * FROM credential WHERE name= 'admin';
SELECT * FROM credential WHERE name= 'admin' and Password= 'xyz';
and I put this statement in the username box and xyz in the password box.
I am not sure if I am even approaching this correctly. The SQL statement should in the username box, correct? Is the Password box left empty? My professor hasn't covered this in class. Can someone please clarify how this is done? I have seen examples online and they all look somewhat similar to the above. But, I get the same error every single time:
`There was an error running the query [You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'admin' and password= "xyz"; and Password= da39a3ee5e6b40d3255bfe95601890afd80 at line 3]\n`
Thank you all in advance!
I don't agree that the question is meant to teach people how to hack. It is meant to teach backend developer to sanitize input in order to avoid sql injection or other type of attacks.
To answer your question, you can leave the password field empty and just use the user name.
You can see on the server code that no control is made on the input as the input is taken as is and put on the sql statement. So in order to make the sql statement do what you are looking for, the field can has the following value:
admin'; --
The hyphens are sql comments that allow you to disable the last part of the select statement to not have to provide the password. And the quote and ; will close the statement. Result, you'll login as admin ;-)
Turns out this is what worked for me:
Admin’ or ‘1=1
I’m not completely sure why this also works but it does:
Admin’ or ‘

MySQL SELECT: is it possible to use part of the result in the SELECT?

(Massively edited because the responses were focusing on the wrong thing, which means I didn't formulate the question properly.)
I have a MySQL table with id, username and password fields. The password is encrypted. Part of the encryption uses the id of the record, specifically (in PHP):
md5 (md5('id') . $formPasswordCleaned)
To a validate a login form, I do the following (pseudo-code):
query database for the email address from login form
if num_rows > 0, $row = fetch_array
use $row['id'] to encrypt the password provided in the login form.
compare encrypted password with the one found in $row 4.
But, what I'd really like to do is one single SELECT command, that looks for a match on both email address and the encrypted password. But, since the password was encrypted using the row's id.....
Question: is it possible to write a SELECT statement that uses part of the forthcoming result as some of the arguments? Something like: SELECT * from users where email=$email and password=md5(md5($futureResult['id]).$password)
I realise it's self-referential, but I know just the basics of database usage and so I don't know what to search for (google or here) to find out if it's possible or how to do it, if it is indeed possible.

SQL Injections - Web for Pentester (Pentesterlab)

I am attending a free online course at Pentesterlab and today I am getting comfortable with SQL Injections.
However I don't get the instructions and as it could be a huge (technical) difference I would want to know how it works.
The stuff I am talking about:
https://www.pentesterlab.com/exercises/web_for_pentester/course
Please scroll down more than the half to "SQL Injections" --> "Example 1".
In the example we found out, that the (My)SQL-Table should work like this pattern:
SELECT * FROM users WHERE name='[INPUT]';
As I understand this, all I am providing through the URL is the "INPUT", the quotes (') before and after the input, and the semicolon (;) is added by SQL automatically.
However, the instruction says:
?name=root' and '1'='1: the quote in the initial query will close the
one at the end of our injection.
I don't get it. I thought the quote (') after root ends the first part, but there's still the other part '1'='1 , isn't it?
Maybe it's a misunderstanding of the language, however I am not sure if I understood it .
Imo the SQL should look like this (for example 1, first "code"):
SELECT * FROM users WHERE name=' root' and '1'='1 ';
At the second try at Example 1 it's getting stranger:
?name=root' and '1'='1' # (don't forget to encode #): the quote in the initial query will be commented out.
Wait what? I thought the quote provided by SQL automatically gets commented out.
Imo the SQL should look like this (for example 1, second "code"):
SELECT * FROM users WHERE name=' root' and '1'='1' # ';
Hope someone can clear it out, if I understand it right and it's just to hard for me explained or if I am messing up something.
Thank you guys :)
Mysql does not addanything automatically to your query. If you are not providing a single quote, then it will not be there. Period.
SELECT * FROM users WHERE name='[INPUT]';
The application will contain the above sql statement template in its own code and will substitute the parameter received from the user in place of the [INPUT] placeholder.
If you provide a single name, as you are supposed to, then the query executed will be:
SELECT * FROM users WHERE name='root';
However, if you provide root' and '1'='1 as an input, then the sql code being executed will be
SELECT * FROM users WHERE name='root' and '1'='1';
The single quote before root and after the 2nd 1 are part of the sql statement template within the application.
I haven't read the course, so let's assume the logic will check the user exists in database only.
Original SQL
SELECT * FROM users WHERE name = 'admin'
(1 row affected)
By SQL injection, you can input something after that to make this SQL always return records
by input user name as [root' and '1' = '1]
SELECT * FROM users WHERE name = 'root' and '1' = '1'
(20 rows affected)
However, let's assume this SQL will also check the password
SELECT * FROM users WHERE name = 'admin' and pwd = 'abc'
(1 row affected)
by input user name as [root' and '1' = '1]
SELECT * FROM users WHERE name = 'root' and '1' = '1' and pwd = 'invalid'
(0 row affected)
We need to bypass the password, what need to do is comment out the rest of SQL
by input user name as [root' and '1' = '1'#]
SELECT * FROM users WHERE name = 'root' and '1' = '1'#' and pwd = 'abc'
(20 rows affected)
With this SQL, it will comment out the password checking, and it will grant access even you don't have the correct user name and password

Test whether or not log-in system is protected against sql injection

So for a school project I have to make a site with a log-in system. It has a username and password field, and a submit button. It compares the username and password with those in a MySQL database. If the combination is in the database, the user may proceed, else they are redirected to the log-in page. I use prepared PDO statements for my database connection.
Now my teacher wants me to test the safety by performing sql attacks on the log-in system. Unfortunately I have no idea what to put in these boxes, and what would be the outcome. For example, I have tried putting values in both username and password fields that will return true, like this:
1==1, 1===1, 0 is null
But I do not know whether or not I have succeeded and if attackers may access or truncate my database by these sort of statements.
Html code:
<form method="post" action="includes/login.php">
<input type="text" name="gebruikersnaam" >
<input type="password" name="wachtwoord" >
<input type="submit" value="login">
</form>
Php authentication:
$myusername=$_POST['gebruikersnaam'];
$mypassword=$_POST['wachtwoord'];
$sql="SELECT * FROM leerling WHERE leerlingnummer='$myusername' and wachtwoord='$mypassword'";
$sql2="SELECT * FROM lop WHERE gebruikersnaam='$myusername' and wachtwoord='$mypassword'";
$statement2=$conn->prepare($sql2);
$statement2->execute();
$count2=$statement2->rowcount();
if($count2==1){proceed}
$statement = $conn->prepare($sql);
$statement->execute();
$count= $statement->rowcount();
if($count==1){proceed}
else {deny access}
Imagine this query:
SELECT id FROM users WHERE email=? AND password=? LIMIT 1
Now imagine the values would be foo#bar.hello and an empty string for password:
SELECT id FROM users WHERE email='foo#bar.hello' AND password='' LIMIT 1
This would not be harmful if these credentials are not in your database. Now lets give different input:
For email we fill in an empty string, and for password we insert ' OR 1=1 (Note the first apostrophe)
Your teacher wants you to find out whether this means your SQL server will execute the following query:
SELECT id FROM users WHERE email='' AND password='' OR 1=1 LIMIT 1
SQL is a declarative language with which you declare the expectations you have for your result. If your server would interpret our input as stated above, the first users id would be considered correct, simply because one is equal to one.
As it is, it is susceptible to SQL injection
The thing to look at when trying to inject is can I close the statement I'm in right now and add more to the end.
so if you enter username = 123456' -- the SQL statement becomes SELECT * FROM leerling WHERE leerlingnummer='123456' --' and wachtwoord='unimortant'
the -- starts a comment so all it does is select whatever student number is entered ignoring the password.
PDO has good alternatives to prevent this from happening called Prepared Statements. You declare your SQL queries and only enter where user infromation is going to be entered by using a ? or :lable and then bind user input to those points. The page does a way better job at explaining it. This way all user data is clearly seperated from the rest of the command and will be treated as a litteral string rather than a command. Stopping SQL injection.
$sql="SELECT * FROM users WHERE username = '{$_REQUEST['username']}' AND password = '{$_REQUEST['password']}";
Write query in such format will avoid sql injection.
$sql = 'SELECT * FROM users WHERE username = ? AND password = ?';
$query = $db->prepare($sql);
$query->bindParam(1, $_REQUEST['username']);
$query->bindParam(2, $_REQUEST['password']);
Or pass the parameter to mysql_real_escape_string function and then pass to queries.
$username=mysql_real_escape_string($_REQUEST['username']);
$password=mysql_real_escape_string($_REQUEST['password']);

How to demonstrate SQL Injection in this PHP and MySQL code?

I'd like to note first that this is an education attempt on my own database to better understand MySQL injections to protect my own code.
I need to work out a couple of examples of how a MySQL injection can be constructed against the following code. It's a basic user login system where I'm accepting the username and password without any escaping
$user = (!empty($_POST['user'])) ? $_POST['user'] : '';
$pass = (!empty($_POST['pass'])) ? $_POST['pass'] : '';
The MySQL query then tries to find the entered username and password in my table called users, as follows:
$res = mysql_query("SELECT * from users where user='{$user}' AND pass='{$pass}'");
This is un-escaped input, and I'm trying to come up with MySQL injections to:
bypass the password knowing a legitimate user's username (one user in my users table is tester), and
an injection that would drop the users table in its entirety.
I've tried a couple of MySQL injection examples from Wikipedia, but I'm guessing the {} in my query is preventing the injection, so I would appreciate some help from those who are confident with this, and thank you to all.
Something like this should do:
To log in as user "foo", set the username to "foo' -- "
This will make your query look like
$res = mysql_query("SELECT * from users where user='foo' -- ' AND pass=''");
The "-- " means the rest of the line is commented out
Not sure if this will work but try setting the username to "foo' OR (DROP TABLE users) -- "
This will make your query look like:
$res = mysql_query("SELECT * from users where user='foo' OR (DROP TABLE users) -- ' AND pass=''");
might not accept that though - I think subqueries can only SELECT.
The mysql_query function will only run one query - others would let you do this:
$res = mysql_query("SELECT * from users where user='foo'; DROP TABLE users -- ' AND pass=''");
You will not be able to DROP the table because using mysql_query you can't send multiple queries.
Here's a long list.
http://ha.ckers.org/sqlinjection/
Your code will obviously fail almost all the test as it is totally unprotected.
$user = (!empty($_POST['user'])) ? $_POST['user'] : '';
$pass = (!empty($_POST['pass'])) ? $_POST['pass'] : '';
$user = mysql_real_escape_string($user);
$pass = msyql_real_escape_string($pass);
$res = mysql_query("SELECT * from users where user='{$user}' AND pass='{$pass}'");
That will protect code for you.
Anyone will not be able to DROP the table.
{} are not the reason. It might be that php's Magic Quotes (now deprecated) protect you from rather simplistic attacks.
However, you can switch them off and then test again.
Try this one out and see if it dumps the entire table:
For both username and password, I enter:
' OR 1=1 AND '}' '=
This of course assumes that I know you are using the curly brace to wrap the data values.
I'm really not sure how MySQL handles mixed logic like that, since it's not enclosed in parenthesis, so let me know if it works!