I have a simple SQL query in MYSQL.
The data type of the password column is varchar(250)
Here is my query which is meant to select the row regarding the user using their hashed password in the database:
SELECT * FROM employeeDetails
WHERE password = 'b''\xb4\xb7\xfbbA\x16\xa0\x97\xd5\x05\xd8\xb7\xfc\xeb\x06+
\x0f\x9b3)\xa3\x8d\xf6\x81\xc8\xccJ\xd6\x99\xbf\xf0\xc8'''
When I copy the password cell from the table here is the password I am trying to query in the query above:
'b'\xb4\xb7\xfbbA\x16\xa0\x97\xd5\x05\xd8\xb7\xfc\xeb\x06+
\x0f\x9b3)\xa3\x8d\xf6\x81\xc8\xccJ\xd6\x99\xbf\xf0\xc8'''
The problem is, It doesn't return any rows!
I don't know why looking for a hashed password. I would think you query the WHO is attempting login, then once that record is returned (if one so exists), THEN you have the hashed column returned and you can compare locally. What happens if for whatever strange reason you get a duplicate coincidental hash (depending on how you build your underlying stored hash). Do you let person "A" login as person "X"? Now you wont have to worry about the query of the hashed password value. If you never get the person, who cares, the hash is irrelevant.
In your request you must precede the quotes and the antislashes characters by an escape character (\)
select row with the request :
SELECT * FROM employeeDetails WHERE PASSWORD =
"\'b\'\\\xb4\\\xb7\\\xfbbA\\\x16\\\xa0\\\x97\\\xd5\\\x05\\\xd8\\\xb7\\\xfc\\\xeb\\\x06
+
\\\x0f\\\x9b3)\\\xa3\\\x8d\\\xf6\\\x81\\\xc8\\\xccJ\\\xd6\\\x99\\\xbf\\\xf0\\\xc8\'\'\'"
Is your hash string correct? It looks as though it may have been mangled by a converter of some type. Look: \xfbbA, capital A? That shouldn't be there. This b''\xb4, the b'' seems quite out of place, etc..
Look at this command:
SELECT UNHEX('4d7953514c');
The result is:
+---------------------+
| UNHEX('4d7953514c') |
+---------------------+
| MySQL |
+---------------------+
"MySQL" is just an arbitrary string I chose, it could have been any text value. But it certainly will error out on some of your chars.
mysql> SELECT UNHEX("'b''");
+-----------------------+
| SELECT UNHEX("'b''"); |
+-----------------------+
| NULL |
+-----------------------+
If you wanted to actually compare the values, you'll notice your DB-field probably looks like: Ll▒▒$o4|l▒▒Ődn▒▒, when doing a straight SELECT passwordfield FROM YourTable.
But you can get a decipherable value with....
mysql> SELECT HEX(passwordfield) FROM YourTable;
And this returns something like...
mysql> select HEX(Password) from User;
+------------------------------------------------------------------+
| HEX(Password) |
+------------------------------------------------------------------+
| 294C6CADBE246F3
+------------------------------------------------------------------+
Now that you can look at the raw, hexadecimal in the database and in the hashed password, you should be able to definitely tell if they match, and if not, what's different between the two and track it down.
You may need to fix the hashing, fix password cleansing, fix MySQL field-escaping, or use HEX() or UNHEX() in your insert/select queries, it's really hard to tell without knowing any more. The above should hopefully provide sufficient knowledge to debug further.
Related
SELECT * FROM plugin_referral_code WHERE code=0;
Returns this record
What!? Why?
MySQL does not return an incorrect result for that query. Please, note that most important web sites use MySQL or its forks, so it is illogical to assume that a query like that doesn't work correctly.
You are comparing potatoes with tomatoes. 'butts' is a string, 0 is a number. MySQL (or any program ever existed) cannot compare strings to numbers. So, it internally converts 'butts' to a number. Any string, if converted to a number, is 0.
Also note that your client is ignoring a MySQL warning that explains the problem:
MariaDB [test]> SHOW WARNINGS;
+---------+------+-------------------------------------------+
| Level | Code | Message |
+---------+------+-------------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: 'butts' |
+---------+------+-------------------------------------------+
1 row in set (0.00 sec)
I suggest to immediately uninstall any client that hides MySQL warnings... but this is a personal opinion :)
Are you definitely executing the entire query in your query editor? I know some editors let you execute (highlighted) parts of queries. It's possible that if you're actually only executing SELECT * FROM plugin_referral_code WHERE code it would return any rows with non-NULL code values.
This is because the where clause needs to evaluate to true, and WHERE code would evaluate to true for any non-NULL code value.
That's all I can guess on this. If this is not the case, please provide more detail, e.g. what type column code is, and execute your query with DESC before it to get any query plan details.
I've noticed that, in Laravel, (when using $model->fill(Input::all()), not that it matters how the data comes in), empty fields (empty in a form) come through as an empty string (''). That makes sense, as that's how it's delivered from browser to HTTP server to PHP.
The problem is that if the column is numeric and has a DEFAULT value, or is NULLable, the generated query from Eloquent has '' for the column's value and so MySQL interprets that and enters the value as 0 rather than the default column value or NULL. Is it something I'm doing wrong here, or will I need to put extra work in (e.g. a mutator) to detect this empty string and convert to null to achieve what I actually want?
Of course I understand that from a technical point of view, Laravel, without knowing how your columns work, can't just assume that empty string means pass NULL to the INSERT query, because sometimes you actually want to set a field (specifically a character-based one) to an empty string rather than NULL.
That said, I'd rather not have to define mutators for all my models just because I'm using $model->fill(), but is there anything I don't know about that I can do?
For the MySQL people reading this - is it correct behaviour to set a numeric field to 0 if passed ''? Seems like it should be seen as NULL as it's not explicitly 0, but I guess it's maybe weak typing equating '' to 0 rather than the more distant NULL.
There is a very simple way to do this, and that is by using an array_filter.
$input = array_filter(Input::all(), 'strlen');
$model->fill($input);
The array_filter will return all of the keys that have something assigned to them.
There are some caveats with this solution:
strlen has been used, and not empty. This is because empty will cause other items (such as the number 0) to also be unset.
this means that edits that are made with an update, such as a text box being completely emptied, will not be fulfilled by your application, so use wisely!
EDIT: As for the MySQL question, yes, this is normal.
mysql> SELECT CAST("tim?" AS SIGNED);
+------------------------+
| CAST("tim?" AS SIGNED) |
+------------------------+
| 0 |
+------------------------+
1 row in set, 1 warning (0.00 sec)
mysql> SHOW WARNINGS;
+---------+------+-------------------------------------------+
| Level | Code | Message |
+---------+------+-------------------------------------------+
| Warning | 1292 | Truncated incorrect INTEGER value: 'tim?' |
+---------+------+-------------------------------------------+
For the default values to be inserted on some fields then do not set values for those fields explicitly.
When you receive form data, process each of the fields and decide for which of them you want to insert the default values. Then remove them from insert into ... statement.
Example:
Form fields: field1_1, field_2.
If valid input is given for both of them, then you can write sql statement like:
insert into my_table values( field_1_value, field_2_value );
If one of the fields, say field_2 does not have valid input and you still want the record go into the database table. Then write the sql statement like:
insert into my_table( field_1 ) values( field_1_value );
When you do this, SQL engine will use the default valued defined on the omitted fields in the insert statement.
Note: This only works when you have set default someValue on the columns at the time of creating or altering them in a database table.
"Alias" is probably the wrong word, since that's used in the context of referencing column/table names as something else in a Query.
What I'm interested in is if there's a way to give a column two names in the database. If I were to print such a table, it would look like this:
mysql> SELECT * FROM User;
+--------------------------+-----------------+
| id | username | uname | password | pswd |
+----+---------------------+-----------------+
| 0 | bob_jones#gmail.com | some_pw_hash |
| 1 | sue_smith#gmail.com | some_pw_hash |
+--------------------------------------------+
In this case, username and uname would be synonymous in query statements, as would password and pswd.
So the following statements would have the same output:
mysql> SELECT id, username FROM User;
...
mysql> SELECT id, uname FROM User;
...
I would like to avoid having to do something like
mysql> SELECT id, username AS uname FROM User;
So, does a feature like this exist?
Cheers,
Neil
No, this is not possible. To do so, you'd have to add a new, actual second column and use triggers to keep them in sync, which would be silly.
Just write your SQL properly to use the proper column names.
If you don't mind selecting from V_User instead of User, then views can get you what you need.
CREATE VIEW V_User AS
SELECT username as username,
username as uname
FROM User;
Then these 2 queries have the same result:
mysql> SELECT id, username FROM V_User;
...
mysql> SELECT id, uname FROM V_User;
...
As Ken points out, this is not precisely what was asked. But depending on the precise context, it might be just what's needed.
I've got a table which contains a varchar(1024) field, which in that contains strings which has hex encoded strings. This table is filled automatically and I have to provide an SP to allow users to download this, therefore, I need to change the hex back into human readable form.
If I manually run this statement (taking the Hex data from the field), it works just fine:
SELECT X'5468697320697320612074657374206D6573736167652031323334353637383930';
But I cannot find a working example of getting this to work when calling the field/column name. I've found a few examples, but these just return a null or 0.
I've tried X and UnHex() and neither give me a result.
Where am I going wrong?
Thanks
EDIT:
Okay, after doing a bit more testing, it appears it must be the way it's being written to the database in the first place.
It's a Classic ASP page that calls an SP, which creates the database entry. In this method, the write to the DB works, and I can see the HEX content in the field. Copying the content of the field, and putting this into a Select X'123123' gives me the ASCII values, as I want.
If I try this as a Select, this fails, giving me a zero or Null return.
SELECT Message_Body_Hex, UNHEX(Message_Body_Hex) FROM messages_inbound
returns:
Message_Body_Hex......unhex(Message_Body_Hex)
417265612032........(NULL)
Still confused! :)
I realize this is an old question but I ran into this same problem today and solved it using a combination of HEX and CAST. Using your example, try this:
SELECT HEX(CAST(X'5468697320697320612074657374206D6573736167652031323334353637383930' AS CHAR(33)))
When pulling from a table you'd substitute the field name:
SELECT HEX(CAST(binary_field AS CHAR(33)))
I've seen other answers recommending to use MAX in place of the 33 but this appears to work fine. Here are some sources I used:
SQL Server converting varbinary to string
and
How to convert from varbinary to char/varchar in mysql
Using the UNHEX() function seems to work fine on MySQL 5.5.29-1:
mysql> create table t1 ( f1 varchar(1024) );
Query OK, 0 rows affected (0.03 sec)
mysql> insert into t1 values('5468697320697320612074657374206D6573736167652031323334353637383930');
Query OK, 1 row affected (0.02 sec)
mysql> select f1 from t1;
+--------------------------------------------------------------------+
| f1 |
+--------------------------------------------------------------------+
| 5468697320697320612074657374206D6573736167652031323334353637383930 |
+--------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> select unhex(f1) from t1;
+-----------------------------------+
| unhex(f1) |
+-----------------------------------+
| This is a test message 1234567890 |
+-----------------------------------+
1 row in set (0.00 sec)
I was wondering in case of normal select operation the search is case insenesitive.
So SELECT * FROM tbl WHERE name = aBc will also consider name with values ABC,abc,abC etc
but in case of login function we just do
SELECT * FROM tbl WHERE password = aBc
will be case sensitive and only consider password with aBc value.
How does this happens?I didnt found anything about this in my searches.
Please care to explain.
Thanx All.
I think it depends on collation of columns, default database collation in MySQL utf8_general_ci where ci at the end stands for case insensitive.
case sensitive passwords will work only if you are storing passwords in encrypted format using MD5 or PASSWORD function.
show variables like '%collation%';
+---------------------------+-------------------+
| Variable_name | Value |
+---------------------------+-------------------+
| collation_connection | latin1_swedish_ci |
| collation_database | utf8_general_ci |
| collation_server | latin1_swedish_ci |
+---------------------------+-------------------+
$sql="SELECT * FROM user where username='$username' AND BINARY password='$password'";
for case-sensitive use (BINARY)
SELECT * FROM tbl WHERE BINARY password = aBc
I'm not sure what the answer to your exact question is, however if you're storing passwords in a database as text, then that is a VERY bad idea. What you should do instead is hash the password upon registration and store it in your database in that form. Then each time a user attempts to login, you rehash the submitted password and compare it to the hash stored in the row with the matching username. Since the hash IS case-sensitive, this solves your problem while adding a much needed level of security.
In many implementations passwords or their hashes are compared in the application server so the problem does not arise.