encrypted password in mysql tables, VBA as a front-end - mysql

I am trying to add some security at MS ACCESS 2013 applications (using a Mysql BE in the backend).
The first application form will ask for user and password, compare it against a mysql custom table ("USUARIOS", for instance) and grant access if they match or don't elsewhere
But I would like passwords to be stored "encrypted", using AES_ENCRYPT or other convenient algorithm
I have input the user/password directly from mysql-workbench
INSERT INTO USUARIOS COLUMN (ALIAS, PWD)
VALUES ('luis', AES_ENCRYPT('miguel','yucg39dy(9&%$^?bcGSFD'))
but I am failing to retrieve the password to compare (from code, using VBA, loading ADO recordsets).
rs.open "SELECT AES_DECRYPT(PWD, 'yucg39dy(9&%$^?bcGSFD' FROM USUARIOS WHERE ..'
this rs doesn't return the word 'miguel' as intended
I would appreciate any hint on that. Maybe I can use password() or MD5() functions, don't need any key

I have input the user/password directly from mysql-workbench
INSERT INTO USUARIOS COLUMN (ALIAS, PWD) VALUES ('luis',
AES_ENCRYPT('miguel','yucg39dy(9&%$^?bcGSFD'))
rs.open "SELECT AES_DECRYPT(PWD, 'yucg39dy(9&%$^?bcGSFD' FROM USUARIOS WHERE ..'
It's long time ago but maybe try this:
SELECT AES_DECRYPT(PWD, 'yucg39dy(9&%$^?bcGSFD') AS PWD FROM USUARIOS WHERE ..' ('User' = 'miguel';)
All the best

You don't need to retrieve the password.
You should be doing
SELECT COUNT(*) FROM USUARIOS WHERE USER = ? AND PWD = AES_ENCRYPT(...)
and seeing whether the count was 1 or 0.
It will then become clear to you that you don't need to decrypt the passwords at all, so you can stop that insecure plan and hash them instead.

Related

How to use password() in sql?

I am trying to verify user login my matching the input password to the password input by user
My insert query:
insert into login (Emp_id, Emp_Fname, Emp_Lname, Username, Password) values (5, 'TestFName', 'TestLName', 'Test', password('april'));
it stores the password as this value :
*72B46CDA233C759A88BEF81F59F66D78B26B2848
select * from login where password = '*72B46CDA233C759A88BEF81F59F66D78B26B2848'; -- this line shows me the result
select password('april'); -- this returns *72B46CDA233C759A88BEF81F59F66D78B26B2848
select * from login where password = 'password(april)'; -- this returns an empty set
Is there any alternative to this line of code?
I think you need to use:
select * from login where password = password('april');
So, don't quote the whole password function, just the argument to the function.
One cannot safely store passwords with pure SQL commands, instead a dedicated password-hash function of the development language should be used. In PHP this would be the functions password_hash() and password_verify() for the verification of the password.
Even more, MySql's password() function was never intended to be used with user passwords and is deprecated (will be removed in future versions). Have a look at the second note box in the documentation.
The reason why you cannot left the hashing to the SQL command is, that salted password hashes cannot be searched for in the database. The searching has to be done by user name only and afterwards one can verify the found password hash with the user input. A more in-depth explanation you can find in this answer.
https://dev.mysql.com/doc/refman/5.7/en/encryption-functions.html#function_password says:
This function is deprecated as of MySQL 5.7.6 and will be removed in a future MySQL release.
PASSWORD() is used by the authentication system in MySQL Server; you should not use it in your own applications.
That wasn't an idle warning. https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_password says:
This function was removed in MySQL 8.0.11.
So don't use PASSWORD() — unless you plan to never upgrade to MySQL 8.0.
Besides that, you have some problems in your code.
insert into login (Emp_id, Emp_Fname, Emp_Lname, Username, Password)
values (5, 'TestFName', 'TestLName', 'Test', password('april'));
I wouldn't use password (or any other hashing function) in this way, because you still have the plaintext password in your SQL statement. This ends up getting logged in query logs and statement-based binary logs, so it's a security weakness. That is, anyone who can get access to your logs can inspect the passwords.
Instead, hash the password in your app, and then put the result of that hash into your SQL statement.
Which hashing function you use depends on the language you use to write your application code. #martinstoeckli mentions a couple of functions that are used by PHP developers, but those won't be the same for other programming languages. You don't mention which language you use.
Likewise, when you search for a login that has that password, it works if you search for a specific hash string, but this doesn't work:
select * from login where password = 'password(april)'; -- this returns an empty set
The reason is that you're searching for the string 'password(april)'. Putting an expression in quotes means to use that literal string — it won't execute the function and use the result of it.
Again, you don't want to calculate the hash using SQL anyway. That puts the plaintext password into query logs and is not good for security.
You want to produce the hash string in your app, and then use the hash string in searches, like your first example. But not using the PASSWORD() function — using some application code function.
select * from login where password = '*72B46CDA233C759A88BEF81F59F66D78B26B2848';
(The hash string above is based on your example. It's a hash produced by MySQL's PASSWORD() function, only as strong as a SHA1 hash, which is known to be unsuitable for passwords.)
Actually, my preferred method is not to search for a password at all. Search for the login, and return the password hash string that is stored in the database.
select password from login where user = 'billkarwin'
Then in the application code, compare the hash string you fetched from the database against the re-calculation of the hash string based on the user's input when they're trying to log in.

hash() function in mysql version 8.0

I am trying to store passwords in my user table. Of course I want to salt and hash them before.
But there's no hash() method in mysql anymore. How can I do it in version 8.0? Are there alternatives?
Thanks in advance for your help.
You should hash passwords in your app, before sending them to SQL.
Why do I say this? After all you could do this:
INSERT INTO Accounts (user, salt, password)
VALUES ('myuser', '1234', SHA2(CONCAT('xyzzy', '1234'), 256))
But now you the password 'xyzzy' appears in plain-text in your query logs and binary logs, even if it is stored in hashed form in the table itself. If you don't secure your logs adequately, a hacker could get a hold of them and find everyone's password.
Instead, perform the hash operation in your application code. Get the result of that, and save the hash string verbatim in the database.
INSERT INTO Accounts (user, salt, password)
VALUES ('myuser', '1234', 'd3822b5f03ad0c1a363d874238f6b48fd68a131cc35d5e55c77a81db1d266b84')
That way the plain-text password does not get logged.
Likewise, when you do password checks for users as they log in, read the salt, then use it to hash the password they input, then compare that to the hash string stored in the database.
SELECT salt FROM Accounts WHERE user = ?
...calculate hash string using user input + salt...
SELECT password = ? AS password_matches FROM Accounts WHERE user = ?

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

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.

I need helping creating a query to salt and md5 a password then confirm the login on a MySQL Table

I've created a view of a table on a MySQL database to enable another application to use our existing (centralized) clients table.
Our passwords are stored as
md5(password + salt) + ":" + salt
Normally I decode this via a programming language of the given app we're connecting to it but...
This time it's a third party app and I only have SQL and one query to authorize a user.
Can you help me create a valid SQL query to authenticate?
The logic is straight forward:
Get salt for the given user, (everything after the colon)
combine the password and the salt
MD5 the password and salt
then compare the resulted md5 hash
the default sql query for this app is
select * from users
where userName=? and userPass=?
Thanks in advance.
I tried this and it works:
SELECT * FROM users
WHERE userPass = CONCAT(
MD5(CONCAT('xyzzy', (#salt := SUBSTRING_INDEX(userPass, ':', -1)))),
':', #salt)
AND userName = 'bkarwin';
I know you probably don't have the freedom to change anything, but FWIW, MD5() is not considered strong enough encryption for passwords. It's recommended to use SHA-256, which is available through the SHA2() function in MySQL 6.0.5.
select * from users where userName='MyUser' and userPass=concat(md5('MyPass'), ':', salt)
where salt=(
select substring(userPass FROM (instr(userPass, ':')+1)) from users
where userName='MyUser'
)