MySQL - mysql database priviledges and root user - mysql

so..
I'm watching a Tutorial Video courtesy of Lynda.com on the basics of MySQL (cool Stuff),
The instructor is instructing us on setting up Root User Password via Console (which i've actually already Done).
He stated the following :
MySQL Stores it Users,Root Users and Permission for those users in a table called user, located in a datbase called mysql
Then a little lightbulb appeared above my head and i typed this in
{SHOW DATABASES;}
{USE mysql;}
{SHOW TABLES;}
{SELECT * FROM user;)
Then a bunch of stuff appeared that was obviously all the user info
so HERE'S MY QUESTION (actually 2 if i may)
1.Am i correct in assuming that if i (hypothetically) modify they "Y"'s or the "N"'s , i then effectively alter the permissions and/or access grants to those corresponding users.
LASTLY, i have set my password, and next to my name in the list, under the password column, there is a really long string of what appears to be a Hexadecimal string
Just for fun How would i convert that back so that it shows my password
(FYI I'm familiar with conversion of Binary to hex and to decimal and so on, but i'm guessing there's some sort of encryption at work here, perhaps AES or 3DES or something)
it's starts with a Star , followed by 40 Hex Characters, my password is only 12 Characters Long
so..to finish up, in doing all this, i now think i understand what the purpose of the mysql schema is in MYSQL
and needless to say i shouldn't delete it... right LOL
all input on this subject is greatly appreciated ahead of time
thanks guys

Am i correct in assuming that if i (hypothetically) modify they "Y"'s or the "N"'s , i then effectively alter the permissions and/or access grants to those corresponding users.
Yes - however the data is cached independently of the query cache - hence updating the table won't immediately give you this access - you need to reload the privileges or restart the database before the changes take effect.
How would i convert that back so that it shows my password
You can't. It's a cryptographic hash of your password. However given enough time and enough computing resource you can find a string which results in the same hash (which might be the same as the pasword) - this could then be used to log in as that user. But we're talking about millions of CPU hours here.

Yes, you can set 'Y' or 'N' in those rows, but after modifying system security tables you will have to execute FLUSH PRIVILEGES; command. I'd suggest you to use GRANT or REVOKE command instead of editing system tables directly.
No, it is not possible to decrypt MySQL user's password.

Related

Authentication management using "in-database" design

I want to discuss wether good or bad idea:
I got a MySQL DB and created a common table "user" to authenticate an login.
|User|
|user_id|username|password|created_at|
I implemented a stored function and some triggers.
First of all:
ON BEFORE UPDATE
will generate a SHA256 hash and salt when password was changed.
salt is generated out witha mix of created_at, user_id and a global salt_mod which is stored in another "config-table".
So when entering 123 in "password" via normal UPDATe it will produce user-unique password and salt hashes.
Next I implemented a stored function
checkUserAuth('username', 'password')
returns: bool true or false
Ofcourse: receives PLAIN username and password, replicates same hashing logic and returns
bool "true" or "false", depends on if the credentials have been correct.
Pro:
This makes completely sync of password algorithm changes obsolete to any connected apps.
Database-account that is being used by the app can work without SELECT privileges on "username", "password" and "salt" privileges.
Even if the user-account of the database is stolen, passwords are still safe due to lacking permissions to read the FUNCTIONS source-code and the columns that store login-information. We only have an EXECUTE privilege here.
Contra:
Well if someone breaks in on the DB with root privileges, pretty much the source-code on "how to generate the hashes" is leaked (pretty much the salting formula) together with all information in one place. However its still hard to rainbow-table that due to unique hashes on created_at date and user_id in mix with global_salt.
The question to above scenario:
Is this a good approach or totally vulnerable in point of data-security?
I mean on one side, a break-in inside the database is always a problem that should never happen
On the other side, even with stolen source-code of the apps or stolen database-account by a bug in the app you cannot steal any login related data.
The root account is ofcourse excluded from being using elsewhere then on the localhost/server.
What do you think about this?
The primary weakness is that you pass the password in plaintext when you create the row, and every time you call your checkUserAuth() function.
This can be wiretapped (unless you ensure using SSL connections between app and database) and it will be written to the query log if you have the query log enabled. It's also visible in the processlist and the performance_schema statements history tables.
This is a good reason to do the hashing in the client, and send only the salted hash of the password when you create the row. When you authenticate, fetch the salted hash from the database, and validate it against user input in the client.

MySQL Read-Only column based

I want to lock some fields/columns in a MySQL-Database, is this somehow possible?
Backgorund: We are using Revive also known as OpenX (of course the latest version) but it get hacked all the time. Especially the fields prepend and append in the ox_zone table.
What we already did to secure the system:
The Adserver is on a different Server
The Backend is not at the default location anymore
The Backend is secured by an .htaccess and .htpasswd
We removed all install files
We check the Core-Files every minute with the remote Git-Repo to ensure that we dont have compromised files (unauthorized file changes)
We removed the file: adxmlrpc.php Because its known as entry point for attackers
And some nice other tricks which I dont remember now...
But still sometimes the columns prepend and append are compromised, so I thought it would be great if we could lock these fields or set them to read only.
But I am of course up for any other solution.
You can set privileges on the column-level (and therefore only grant SELECT and INSERT) to the user that needs to be on read-only :
GRANT SELECT (column), INSERT (column) ON table TO user;
By replacing column, table and user with the appropriate values. GRANT documentation
You also need to be sure not to grant higher levels (table, data or global) privileges otherwise it would override the table-level privilege.
Best,

User with no permissions can still SELECT

I'm fairly new to MySQL and I've been creating test tables, etc.
Anyway, I created a new user, using
CREATE USER 'myUser'#'localhost' IDENTIFIED BY 'myPassword';
Now, when I log into this user, I can SELECT from a table I created with root earlier. Surely this should not be possible? The user has no SELECT permissions, or indeed any permissions. If (logged in as root) I do either:
SHOW GRANTS FOR 'myUser'#'localhost';
Or
SELECT * FROM information_schema.user_privileges WHERE grantee LIKE "'myUser'#%";
I can see they only have USAGE permissions. My understanding is this permission is set to indicate a user has no permissions.
So how is this user able to SELECT from my table?
If I do:
SELECT * FROM information_schema.table_privileges;
No results are returned.
What am I missing here? Are certain things like SELECT implicitly granted to new users? Do I have to explicitly revoke this?
If so, what other permissions are implicitly granted?
Ideally what I'm aiming for is a user that can do nothing except run one (or more) stored procedures that I specify with GRANT EXECUTE ON.
It never even occurred to me that you would be creating production tables in a test schema -- but it turns out this is documented in the MySQL refman (emphasis added):
In addition, the mysql.db table contains rows that permit all accounts
to access the test database and other databases with names that start
with test_. This is true even for accounts that otherwise have no
special privileges such as the default anonymous accounts. This is
convenient for testing but inadvisable on production servers.
Administrators who want database access restricted only to accounts
that have permissions granted explicitly for that purpose should
remove these mysql.db table rows.
So that explains your find that "Either way, even with deleting it and then recreating it, if it has the name 'test', it will always be accessible to anonymous users, etc."
During my testing, I created a schema called 'test'. Unknown to me, 'test', is actually some sort of reserved database schema name for MySQL. Anonymous users can use it, etc.
As a result, the stuff I was creating in there for testing purposes didn't have certain permission restrictions that other databases would have done.
I can't really find any information on this beyond this page:
http://www.greensql.com/content/mysql-security-best-practices-hardening-mysql-tips
That page says that it comes with it, but I'm pretty sure my installation didn't have it by default.
Either way, even with deleting it and then recreating it, if it has the name 'test', it will always be accessible to anonymous users, etc.
I hope this helps someone, I spent too long puzzling over this!

What is this SQL injection doing?

Long story short, through an old asp site I run someone found an unfiltered URL parameter and was able to run this query. I'm trying to figure out what it DOES though...
The query should read:
select * from reserve where id = 345
the one that was ran was:
select * from reserve where id = 345 and ascii(substring((select concat(user,0x3a,password,0x3a,host) from mysql.user limit 0,1),17,1))=53
I'm really not sure what this obtains. Any Input?
It might be probing whether or not the web application is accessing the database as root. Removing the ascii(substring()) portions returns the following when run as root:
mysql> select concat(user,0x3a,password,0x3a,host) from mysql.user limit 0,1;
+--------------------------------------+
| concat(user,0x3a,password,0x3a,host) |
+--------------------------------------+
| root:<rootpw-hash>:localhost |
+--------------------------------------+
Following a successful probe, they may then attempt to retrieve the contents of mysql.user from which they can start cracking passwords against rainbow tables.
The second part of where condition is really strange: it looks for a mysql credentials and process them as follows:
concat(user,0x3a,password,0x3a,host) will be something like 'someUser:hisPass:localhost'
the above string will be splitted in a smaller one
the above string is converted to ascii code (you might know it from legacy languages as ord())
the result of the conversion is compared to 53 integer
I suppose that the first part of WHERE statement (id = 345) will always return true while the second one is too specific, so the entire query will probably return an empty result all the time.
the query is seemingly one from the a set of them:
by changing the charcode and substring start position and you can find out all usernames and the corresponding password hashes (when the page renders as expected you have a char match)
it allows to find out that the current user has access to the mysql schema.
An sql injection exploit does not necessarily immediately output the query result to the attackers screen, often the result is only either an error, or no error, or maybe the injection causes a measurable (to the attacker) delay. in that way the attacker can obtain 1 bit of information per request.
By sending lots of requests, iterating over string positions, doing a binary search on the characters - or as in this case a linear search ( which may indicate that the attacker does not really understand what he is doing, but he will get there eventually ), he will be able to find all the characters in the mysql root user passwordhash. ( Which can possibly be bruteforced offline ).
The SQL is trying to read user data from the My-Sql user table which typically contains a list of users and hosts that are allowed to access a given my-sql server.
It looks to me like the perp is trying to trick mysql into dumping the contents of the user table so they can then record the password hashes offline and dcrypt them to find valid logins.
If your web application is using a login that will allow access to the mysql users table, then this is a serious security flaw, if it's using a login that is only granted permission to the tables required for the app then no information will be obtainable.
Security tip: When setting up ANY kind of database it's vitally important that the application using does so with a login/access role that grants it ONLY what it needs.
If your application only ever needs to read data and never modify it, then it should never have any permissions other than to read. You always need to double check this, because most database systems will by default create user roles for a given database with full read, create, modify privileges.
Always create a specific user, just for that db and or collection of tables, and always give that user the absolute minimum that's required, if your app does then get hacked with a cross site scripting attack, the most their going to get access too is that one specific database.

MySQL chops off characters from md5 password

I'm developing a website locally using XAMPP. There is a registration page in which I save the password, after encrypting it with MD5, to a MySQL database. The problem is that when I try to log in, I'm unable to. I discovered that the password was the problem. I checked the database and compared the MD5-ed password with the one I logged in with (I just echoed the MD5 hash of the password onto the page to compare). I found that the one in the database was shorter than the one echoed. My conclusion was that MySQL was chopping off some characters at the end of the hash. What should I do? I know it has to do with some settings on MySQL but I need help.
As at now, I have to use substr function on the hash in the registration and login processes so as to be able to log in.
If the column length is causing the problem, alter the column to accept a longer length. MD5's are always 32 hex digits, so VARCHAR(32) would be a good option.
It depends by the length of the value in the database ... check your field in the database and verify that his type is atleast something like a varchar(32)
To fix it you can use a query like that
ALTER TABLE Example
MODIFY password varchar(32)
or use the phpMyAdmin interface