Why a MYSQL string that contains ' is not secure? - mysql

guys,I am new to mysql security,and when I search this issue on google,lots of people are warning that we should check the mysql string to see if it contains ' or not,otherwise you are at the risk of getting mysql database injected,but they didn't tell why?can you please tell me the reason? thank you very much.

Imagine you have a user table and a login form. Usually when a user logs in you want to determine whether he has an account:
THIS IS VERY BAD PHP:
"SELECT * FROM users WHERE username = '$username' AND password = MD5('$password');"
Now you have a user with the username
1';DROP TABLE users;#
What would happen?

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 ‘

Look up my current userID with mySql

This scripts selects an account form my MySQL database with the userID 1:
$_SESSION['user_id'] = 1;
If my MySQL account has id 1 then it will change that account.
I wonder how you can change the = 1; so it automatically looks up which account you are on at the moment? Right now it only works with the account with userID 1.
MySQL database name for my userid is "userID".
Usually you would say something like
SELECT * FROM user_profiles WHERE user_id=1 in MySQL.
Also, I would recommend that you use PDO and properly escape the user input using
htmlspecialchars($_SESSION['user_id'])
in your PHP file since the user_id input most likely can be manipulated by the user.
You are using Session so it can not change the userID unless you destroy that session by using this PHP function:
session_destroy();
And if you want to know your current userID:
echo $_SESSION['user_id'];

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']);

Login Server Side Logic

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;
}

Error: select command denied to user '<userid>'#'<ip-address>' for table '<table-name>'

In my website, I am using MySQL database. I am using a webservice where in I do all my database related manipulations.
Now In one of the methods of that webservice, I get the following Error.
select command denied to user '<userid>'#'<ip-address>' for table '<table-name>'
What could be wrong?
Below is the code where I get that error. I tried debugging and found that it fails at the line
MySqlDataReader result1 = command1.ExecuteReader();
Here is my code:
String addSQL = "Select Max(`TradeID`) from `jsontest`.`tbl_Positions";
MySqlConnection objMyCon = new MySqlConnection(strProvider);
objMyCon.Open();
MySqlCommand command = objMyCon.CreateCommand();
command.CommandText = addSQL;
MySqlDataReader result = command.ExecuteReader();
//int j = command.ExecuteNonQuery();
while (result.Read())
{
MaxTradeID = Convert.ToInt32(result[0]);
}
objMyCon.Close();
for (i = 1; i <= MaxTradeID; i++)
{
String newSQL = "Select `Strike`,`LongShort`,`Current`,`TPLevel`,`SLLevel` from `json`.`tbl_Position` where `TradeID` = '" + i + "'";
MySqlConnection objMyCon1 = new MySqlConnection(strProvider);
objMyCon1.Open();
MySqlCommand command1 = objMyCon1.CreateCommand();
command1.CommandText = newSQL;
MySqlDataReader result1 = command1.ExecuteReader();
objMyCon2.Close();
I'm sure the original poster's issue has long since been resolved. However, I had this same issue, so I thought I'd explain what was causing this problem for me.
I was doing a union query with two tables -- 'foo' and 'foo_bar'. However, in my SQL statement, I had a typo: 'foo.bar'
So, instead of telling me that the 'foo.bar' table doesn't exist, the error message indicates that the command was denied -- as though I don't have permissions.
database user does not have the permission to do select query.
you can grant the permission to the user if you have root access to mysql
http://dev.mysql.com/doc/refman/5.1/en/grant.html
Your second query is on different database on different table.
String newSQL = "Select `Strike`,`LongShort`,`Current`,`TPLevel`,`SLLevel` from `json`.`tbl_Position` where `TradeID` = '" + i + "'";
And the user you are connecting with does not have permission to access data from this database or this particular table.
Have you consider this thing?
This problem happened to me because I had the hibernate.default_schema set to a different database than the one in the DataSource.
Being strict on my mysql user permissions, when hibernate tried to query a table it queried the one in the hibernate.default_schema database for which the user had no permissions.
Its unfortunate that mysql does not correctly specify the database in this error message, as that would've cleared things up straight away.
select command denied to user ''#'' for table ''
This problem is a basically generated after join condition are wrong database name in your join query. So please check the your select query in join table name after database.
Then solve it for example its correct ans ware
string g = " SELECT `emptable`.`image` , `applyleave`.`id` , `applyleave`.`empid` , `applyleave`.`empname` , `applyleave`.`dateapply` , `applyleave`.`leavename` , `applyleave`.`fromdate` , `applyleave`.`todate` , `applyleave`.`resion` , `applyleave`.`contact` , `applyleave`.`leavestatus` , `applyleave`.`username` , `applyleave`.`noday` FROM `DataEMP_ems`.`applyleave` INNER JOIN `DataEMP_ems`.`emptable` ON ( `applyleave`.`empid` = `emptable`.`empid` ) WHERE ( `applyleave`.`leavestatus` = 'panding' ) ";
The join table is imputable and applyleave on the same database but online database name is diffrent then given error on this problem.
You need to grant SELECT permissions to the MySQL user who is connecting to MySQL. See:
http://dev.mysql.com/doc/refman/5.0/en/privilege-system.html
http://dev.mysql.com/doc/refman/5.0/en/user-account-management.html
I had the exact same error message doing a database export via Sequel Pro on a mac. I was the root user so i knew it wasn't permissions. Then i tried it with mysqldump and got a different error message:
Got error: 1449: The user specified as a definer ('joey'#'127.0.0.1') does not exist when using LOCK TABLES
Ahh, I had restored this database from a backup on the dev site and I hadn't created that user on this machine. "grant all on . to 'joey'#'127.0.0.1' identified by 'joeypass'; " did the trick.
hth
If you are working from a windows forms application this worked for me
"server=localhost; user id=dbuser; password=password; database=dbname; Use Procedure Bodies=false;"
Just add the "Use Procedure Bodies=false" at the end of your connection string.
For me, I accidentally included my local database name inside the SQL query, hence the access denied issue came up when I deployed.
I removed the database name from the SQL query and it got fixed.
try grant privileges again.
GRANT ALL PRIVILEGES ON the_database.* TO 'the_user'#'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
Disclaimer
Backup first.
Check your query sentence before executing.
Make sure you've added a WHERE (filter) clause before updating.
In case you have root access or enough privileges, you can do the following directly:
Log into your MySQL as root,
$ mysql -u root -p
Show databases;
mysql>SHOW DATABASES;
Select MySQL database, which is where all privileges info is located
mysql>USE mysql;
Show tables.
mysql>SHOW TABLES;
The table concerning privileges for your case is 'db', so let's see what columns it has:
mysql>DESC db;
In order to list the users' privileges, type the following command, for example:
mysql>SELECT user, host, db, Select_priv, Insert_priv, Update_priv, Delete_priv FROM db ORDER BY user, db;
If you can't find that user or if you see that that user has a 'N' in the Select_priv column, then you have to either INSERT or UPDATE accordingly:
INSERT:
INSERT INTO db (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv) VALUES ('localhost','DBname','UserName','Y' ,'N','N','N');
UPDATE:
UPDATE db SET Select_priv = 'Y' WHERE User = 'UserName' AND Db = 'DBname' AND Host='localhost';
Finally, type the following command:
mysql>FLUSH PRIVILEGES;
Ciao.
The problem is most probably between a . and a _. Say in my query I put
SELECT ..... FROM LOCATION.PT
instead of
SELECT ..... FROM LOCATION_PT
So I think MySQL would think LOCATION as a database name and was giving access privilege error.
I had the same problem. This is related to hibernate. I changed the database from dev to production in hibernate.cfg.xml but there were catalog attribute in other hbm.xml files with the old database name and it was causing the issue.
Instead of telling incorrect database name, it showed Permission denied error.
So make sure to change the database name everywhere or just remove the catalog attribute
my issues got fixed after upgrading to MySQL workbench latest version 8.0.18
I had the same problem. I was very frustrating with it. Maybe this is not answering the question, but I just want to share my error experience, and there may be others who suffered like me. Evidently it was just my low accuracy.
I had this:
SELECT t_comment.username,a.email FROM t_comment
LEFT JOIN (
SELECT username,email FROM t_un
) a
ON t_comment.username,a.email
which is supposed to be like this:
SELECT t_comment.username,a.email FROM t_comment
LEFT JOIN (
SELECT username,email FROM t_un
) a
ON t_comment.username=a.username
Then my problem was resolved on that day, I'd been struggled in two hours, just for this issue.
I am sure this has been resolved, just want to point out I had a typo in the database name and it was still throwing this error on the table name. So you might want to check for typos in this case.
Similar to other answers I had miss typed the query.
I had -
SELECT t.id FROM t.table LEFT JOIN table2 AS t2 ON t.id = t2.table_id
Should have been
SELECT t.id FROM table AS t LEFT JOIN table2 AS t2 ON t.id = t2.table_id
Mysql was trying to find a database called t which the user didn't have permission for.