MySQL API - restricting records - mysql

It seems that MySQL provides some sort of API interface to it. I have never used it, but I think it would be an interesting feature if I could:
Specify which tables a user has access to
Restrict read, update, and delete operations only to records the users created (so an ownership concept needs to be supported)
Will the API support that? If not, are there any other solutions that might allow me to do so?

As the author of mysql-crud-api I can say that I understand your question. Although the permission rules regarding tables and/or users are application specific and should thus need to be configurable.
You may want to read about multitenancy. You may want to support multiple users, but the ownership and permissions may vary between applications. That is why I think the tool you are looking for does not exist.
In order to support multitenancy mysql-crud-api supports a multi-database mode. Using MySQL's built-in permission system you can use it to partition the database.
Not sure this helps you, as I do not know what you want to use it for.

I've used a MySQL API for python and it lets you directly interact with your databases by name (an empty string in the database name parameter will get you to your root database where you can create databases, grant all permissions, etc). You are able to execute sql queries directly on the database.

SQL is an API to a database; there are numerous other interfaces supported as well (either that compile into SQL or that use some other API).
You question appears to be more about row-level permissioning than about a particular API. MySQL does not have a built-in permissioning system at the row-level. A quick glance at the web (Google: "MySQL row level permissions") yields hits such as this.

Related

One-off Read-only SQL Statement Verification in MySQL 5.5?

I have an interface that I want to allow an arbitrary SQL select statement (as an input string) to be input that will select data from a given table for use in an operation. I want to make sure that this statement does not make changes to the database.
string query = GetStringFromForm(...);
DatabaseStatement statement(query);
statement.execute();
while (statement.fetch(...))
...
One way to implement this would be to create a new database user with the appropriate permissions and then execute the statement under that user. This would be a hassle as it would require setting up this new user and creating a new database connection for it and so on.
Is there a way to isolate the permissions for a single statement MySQL 5.5? Or some other way to do this?
With MySQL 5.6 you can do:
START TRANSACTION READ ONLY;
https://dev.mysql.com/doc/refman/5.6/en/commit.html
I think it's what you're looking for, but you have to upgrade to 5.6 to use it.
Don't connect to the database with the same login for everything.
At the very least you should use thee logins for this achitecture:
A development level login for creating tables, etc
The login used by your application to make the application run
The login used to execute user specified queries
This means that your application login only has the permissions it needs - to read or write to the tables necessary, not to do everything to every table; application logins shouldn't need to be able to CREATE or DROP tables, for example.
This limits the impact of mistakes in code, but also the scope to which someone could hack your system (such as with SQL Injection attacks).
It also means that the login for running user specific queries needs only to be granted SELECT permissions, and only to the tables/views/function that it should be able to use. If they try to run an INSERT or a DELETE that they don't have permissions for, you can catch the error and tell the user that they're a very naughty boy - secure in the mind the the RDBMS simply won't let the user damage anything that you haven't already given them permission to do.
In short, RDBMS already have login permission architectures. Use those to limit the permissions and functionallity of different aspects of your code.
I would not try to re-invent this wheel. It is extremely likely that there is a trick or hack that you missed that exposes a vulnerability in your application. I appreciate that you say this is a hassle, but it really is the right way of doing things, and the only reliable way of doing things. There's a reason that it's the standard approach to data security, sorry.
(And trust me, even if no-one is trying to hack your system, eventually someone will type some screwball query in - accidentally bypassing your security and making a pigs ear of your database.)

MySQL: Create a user for reading and another for writing?

I have been searching for this for a while and unable to find something useful.
Is it a good practice or even important to create 2 MySQL users, one for reading and then use that whenever I'm initiating a MySQL SELECT.
And on the other side, create another user for writing and use it whenever I'm doing an INSERT, UPDATE, DELETE, ...?
Would this help at anything for example if I'm writing and reading to the database at the same time?
Assume we're using InnoDB tables.
"good practice" is very hard to define - you've got a whole bunch of different things to trade off against each other.
I'm assuming that the database is being used as a back-end for some other system, and that your users don't have direct access to a SQL prompt. In that case, there are no real benefits to creating different MySQL users - it simply makes the front-end more complex, and an attacker who can reach the database and knows the "read-only" credentials almost certainly also knows the "read/write" credentials. From a security point of view, you should invest your time in network security of the database server, and secure storage of connection details.
From a concurrency point of view - two or more users reading and writing at the same time - you won't really gain anything either. This particular requirement is one of the things relational databases do very well, and I don't think it's affected at all by the permissions of the users - it's far more to do with whether you're using transactions, and how quickly your SQL executes.

Is there a Veil-like plug-in for MySQL?

We have a MySQL database and would like to have row-level security implemented at the database level. I have been playing with the Veil plug-in for PostgreSQL and like what it does. Is there something similar for MySQL so we do not have to convert over to PostgreSQL?
Update
It isn't so much that we would be using veil, or its MySQL equivalent, for authentication but to determine which rows to display for an already authenticated user. User privileges are based on a relational context. Without concerning ourselves with a plug-in, how efficient would a view be where the user privilege is based on multiple joins on a table with 100k rows? The ultimate goal is to be able to display different data to two different users based on the individual users privileges to the rows in a table of 100k> rows using the same query.
This isn't a common feature mainly because its in most cases this is not the right place for this security system. If you could provide more details into the exact attack you are attempting to defend against perhaps there is a more suitable secuirty system to fill this requirement.
Usually you are looking to limit to a specific user based on an Access Control List implementation that you application dictates. There are cases where you want two applications to share the same data and you want to limit the impact of a compromise of one of the applications. In this case you could split it up and give 1 application read access to a database while the the other has write or read/write. Using the databases native access control like this it is possible to safely pass information between applications. The main threat being defended against is that if 1 application where compromised due to a vulnerability like SQL Injection both databases would also succumb to the attack.
There is also sepgsql which does also this for PostgreSQL. This secuirty system could be used for better separation of applications with some dependent data, but this a very unusual software requirement. In general this secuirty system should be avoided in favor of other more common and proven systems.

CRUD Admins: Why not use MySQL users for auth/acl instead of User/Group tables?

In several frameworks (symfony/Django), you have admin generators that usually control access via a User table (which assigns a user to a specified Group table).
I'm curious, why not simply use MySQL's actual users (with select/read/write access already baked in) instead?
Another good reason that hasn't been listed is the fact that MySQL usernames/passwords are stored in clear text in config files. There maybe a vulnerability in your code that allows a user to read a text file, which then would give immediate access to a hacker without having to breaking a password hash. Having a your database remotely accessible is a serious secuirty hazard and is prohibited by PCI-DSS.
Another good reason is that in order to add new accounts or change your password your web application would need ROOT access, which is among the worst things you could do. In many databases (including mysql) this makes it very easy for a hacker to turn a sql injection vulnerability into full remote code execution (like uploading a .php file).
I would presume one reason would be, that many ISPs provide you with only one user account (without extra cost) to your mysql database, and thus, such an aproach wouldn't work as everyone would have identical priviledges.
The magic here being lowest common denominator and easy deployment as far and wide as possible, with minimum requirement in server administration.
I'd imagine most people are a little leery giving their application's MySQL user the ability to create and grant privileges to new MySQL users, particularly in a shared hosting environment. It's not that difficult to handle, it keeps everything within one database table, and you can have any permission you like.

Providing MySQL users with just the minimum privileges

For a web application, when creating the user which will connect to the MySQL database, you have the choice of privileges. Assuming that the only actions intended to be done by that user are SELECT/INSERT/UPDATE/DELETE, it seems to make sense to only provide those privileges, however I've never seen that recommended anywhere - what are the reasons for and against this method?
I disagree with Bill here and Atomix's line of thinking is more suitable. Unless it can be demonstrated otherwise, Bill's answer highly increases the risk of the database being compromised.
Perhaps for very experienced developers there is other security in place, but for other developers giving a script full, unfettered access to do ~anything~ to a database is asking for trouble, when there is no need to.
The principle of least privilege should be in use here. For MySQL, have a super user with all privileges which is used for creating tables, drop database, and so on. Ideally this username and password is never seen in any PHP file or any file on the web server. (I'm using PHP as an example but it applies to other web applications). You would only use this username and password with something like PHPMyAdmin or MySQL Workbench.
Then, for PHP scripts, have one with the minimum required, such as just INSERT, SELECT, UPDATE, maybe not even DELETE, depending on your PHP script. This would be in the PHP files, that is, actually only ONE file OUTSIDE of the document root, as is recommended by most.
The reason is thus: yes, you do not need a MySQL user for every web application user. But principle of least privilege ( http://en.wikipedia.org/wiki/Principle_of_least_privilege ) should apply. If somehow your MySQL super user is compromised because you accidentally named your MySQL connect script as .txt instead of .php, or someone gained access to the web server files, at least the "worst" they can do is SELECT, UPDATE and INSERT... Which while can cause big problems anyway, is not as bad as giving them DROP DATABASE, DROP TABLES and much worse things.
Additionally, in my current project due to agile development practices (I do not work for but recommend http://www.agilealliance.org/), one or two "non-tech" team members are directly using PHPMyAdmin to make direct changes to the MySQL database. This is because creating a CMS for simple direct data entry is not required. In this case, a third MySQL user with reasonable but again, "just enough" privileges is suitable for them. We don't want to cripple the team member with too little privileges, but of course they shouldn't be able to accidentally delete or change things.
Since MySQL doesn't have ROLES (as of the time the original question was asked, and as per Bill) then allowing any web script to just access MySQL with only one Super User is very risky.
There are other privileges that a user might need during an ordinary application, for example:
CREATE TEMPORARY TABLE
EXECUTE (stored procedures)
FILE (for SELECT INTO and LOAD DATA)
LOCK TABLES
There's also the possibility that minimal privileges could mean only SELECT on certain tables, and only SELECT and UPDATE on other tables, etc. This is subject to change any time the application's functionality is enhanced. And there are weird cases, like the need to have SELECT privilege on a table you never query, because it's referenced by the foreign keys in a table you UPDATE. So tracking minimal privileges is a royal pain.
What are you trying to restrict by using SQL privileges? You're the one who wrote all the code, so managing SQL privileges at a fine granularity shouldn't be necessary. Frankly, if your users are able to upload and run SQL statements that you haven't vetted, you have bigger problems:
SELECT * FROM mytable, mytable, mytable, mytable, mytable ORDER BY 1;
The real tasks you want to govern aren't at the database level, they're at the application business level. For example, a CMS has operations like create a page, edit a page, administer comments, etc. These tasks are higher-level than SQL privileges. You could mimic them with SQL roles (which are groups of privileges), but SQL roles aren't widely supported.
I don't know anyone who maps their application users to distinct MySQL users. They're users you authenticate in your application, after the app has connected to the database (the users are just rows of data in the database).
So you're probably better off having your web app use a single MySQL user with full privileges.
A web app usually uses just one user to access the DB, rather than a user per actual user account. Applying minimal privileges is good practice. The username and password is going to be coded into your script (does anyone obfuscate this?) so there's room for compromise if your scripts aren't managed properly.
In my experience, I very, very rarely have the app delete rows - much better to flag a row as deleted as you then have an audit of what is there rather than not knowing what was there! This approach also helps keep tables and indexes optimised.
Therefore, I would suggest allowing only INSERT, UPDATE and SELECT - it will quickly become apparent if parts of your app need to be relaxed a bit!
Allowing more privileges can only broaden the possibility for DoS attacks by issuing resource intensive commands, or allowing malicious data attacks.