Mysql: allow query on an otherwise inaccesible column? - mysql

I have a table with a column that I want to prevent certain users from seeing. I understand that I should be able to do this using a view, i.e. have a view which excludes the particular column, and deny access to the table but allow access to the view (note, users do not need to be able to update the table/view).
I do however want to allow an equality query against the field. Such as:
SELECT * FROM some_table_or_view WHERE hidden_field = 'some_value';
To clarify:
it should not be possible to have the hidden_field values be returned in a general query
it should be possible to run a query with a constraint (preferably only an equality constraint) on the hidden_field value
Is this possible?
(EDIT: if there's a solution in a dbms other than Mysql, I'd be happy to hear about that, too).

You can create a stored procedure which would return all the fields you allowed it to return, and then you can pass the hidden_value (filtering criterion) as a parameter.
Forbid your database users accessing the table, but allow them to call stored procedures.
Then of course, you would have to create several stored procedures if you had several types of queries against the table. But at least it solves your problem with the rights.

No it is not. Giving a user a possibility to filter the results with the column hidden_value means that they have select rights, and that also means they can see the column, and therefore select it.
Here http://dev.mysql.com/doc/refman/5.1/en/grant.html
is a list of the rights you can grant or not grant to the users in mySQL.

Related

How to change the values of two table automatically (MySQL)?

I have a database with two tables. The first one contains the user_name, user_password, user_email. The second one contains the user_name, user_age, user_description.
When a person finds the user he needs by the user_name, the script looks through the database using the user_name, to give out the information about certain user.
But if the person changes his user_name via preferences, the value changes only in the first table.
Question:
1) Is there a way to make the user_name in the second table change automatically? (To connect them some how)
I am using MySQL (phpMyAdmin).
This is just a simple example. In "real world" I am trying to manage more serious applications that have more tables. Is there an easier way than to create a separate php query for each table?
You could always create an AFTER UPDATE MySQL trigger targeting single rows for this. See the manual. It's probably not easier than using separate PHP queries for the tables, though. You don't need to spell them all out, just map up what needs to be synchronized when, and abstract your code.
However I'd recommend that you use a unique ID field for the user and only store the username in one of the tables -- and refer to the user with the ID under the hood of your code, and in both tables. Not a good idea to use something changeable as a unique identifier in your database design.

How can I allow users sql access to a table limited to certain rows?

I'm building an stock exchange simulation game. I have a table called 'Market_data' and in the game players simulate being in particular dates and are allowed to use SQL queries to retrieve the historical data and plan their course of action. My difficulty is that I need to limit the rows they can access based on the current date they are playing on so they cant see rows with a date greater than the current date.
Eg: An user is running the game and is currently in the year 2010, if he does a simple select like "SELECT * FROM market_data" I don't want him to see rows with Date > 'x-x-2010'
The only soution that I know of is to parse the user's SQL and add WHERE clauses to remove newer dates but it seems time consuming and prone to errors and I wasn't sure whether there were better alternatives. Any ideas on how to do this right will be thanked.
Solution is SQL Views, Views are used for several different reasons:
*1.*To hide data complexity. Instead of forcing your users to learn the T-SQL JOIN syntax you might wish to provide a view that runs a commonly requested SQL statement.
*2.*To protect the data. If you have a table containing sensitive data in certain columns, you might wish to hide those columns from certain groups of users. For instance, customer names, addresses and their social security numbers might all be stored in the same table; however, for lower level employees like shipping clerks, you can create a view that only displays customer name and address. You can grant permissions to a view without allowing users to query the underlying tables. There are a couple of ways you might want to secure your data:
a.Create a view to allow reading of only certain columns from a table. A common example of this would be the salary column in the employee table. You might not want all personnel to be able to read manager's or each other's salary. This is referred to as partitioning a table vertically and is accomplished by specifying only the appropriate columns in the CREATE VIEW statement.
b.Create a view to allow reading only certain rows from a table. For instance, you might have a view for department managers. This way, each manager can provide raises only to the employees of his or her department. This is referred to as horizontal partitioning and is accomplished by providing a WHERE clause in the SELECT statement that creates a view.
*3.*Enforcing some simple business rules. For example, if you wish to generate a list of customers that need to receive the fall catalog, you can create a view of customers that have previously bought your shirts during the fall.
*4.*Data exports with BCP. If you are using BCP to export your SQL Server data into text files, you can format the data through views since BCP's formatting ability is quite limited.
*5.*Customizing data. If you wish to display some computed values or column names formatted differently than the base table columns, you can do so by creating views.
reference taken from http://sqlserverpedia.com.
1)You can use mysql proxy http://dev.mysql.com/downloads/mysql-proxy/ with custom rules restricting access.
2)You can use stored procedures/functions
3)You can use views
The basic way would be :
-> Prevent that user (or group) from accessing the base table.
-> Define a view on top of that table that shows only the rows these users are supposed to see.
-> Give those users SELECT permission on the view.
-> And you can also use SQL Encryption,Decryption and Hashing concept.
Encryption & Decryption examples can be found here:
http://msdn.microsoft.com/en-us/library/ms179331.aspx
Hashing example can be found here:
http://msdn.microsoft.com/en-us/library/ms174415.aspx

Granting permission to individual fields in MySQL

I have MySQL Database and have several tables in it. One, of course, is the users table for storing the username and passwords (which also has the rest of their information). For all the tables in the schema, I want to be able to grant users (or groups) permission to individual fields. Maybe an example will help:
There;'s a table called ACCOUNTS. In this table, the user fills out (and keeps up to date) all the data about their company (name, address, POC, etc). But I also want to have fields attached to this table that are read only for those users, such as LastPaymentDate (can't have them changing that!). Further, among those users, permissions differ. For example, the admin/superuser can change the name and address of the company, but standard users should not.
I'm thinking this might need to be done by making several Views for the table, one for each level of permission (group). I'm relatively new to MySQL, so I don't know if this is the best way. I can also see a lookup table that says which fields is allowed to view/edit.
My initial thought was to include in the comments (or the name of the field) a value from 0-5, and then the user would have a permission level (0-can't see; 1-Read only; 2-Read-write; 3-(not used); 4-(not used); 5-Edit/Delete the field itself.
Any suggestions? Views? Lookup table to determine which fields to display? Again, it'd not for the whole table, for each column within a table.
You can GRANT the rights to individual columns to a user, using this code:
GRANT SELECT (col1), INSERT (col1,col2) ON mydb.mytbl TO 'someuser'#'somehost';
Example taken from here:
http://dev.mysql.com/doc/refman/5.1/en/grant.html
Also there is no support for groups of users or SQL ROLES (which are groups of privileges) in MySQL.

Regex for SQL string to allow SELECT queries on variable named tables only?

The table names are variable, but what is certain is that SELECT only is allowed and certain tables are excluded (ie Users, Log). I'm making a reporting form where a user can just enter sql queries to make template reports.
SELECT 'field1' As 'foo', 'field2' as 'bar'.. 'fieldn'
FROM 'table1',..'tablen'
JOIN ... ON ...
WHERE CONDITION
Although I'm thinking I can have the table names in a html select list of existing tables.
Also make a user reporter_appname#localhost with SELECT access only to all tables except Users and Log? In that case I won't need to bother with a regex check of the query?
(This would be in PHP)
(Ideally I just wanted a single textarea where the admin can just type their query, my report function would then take the output and present it nicely etc.)
I suggest you re-think your design.
Identifying valid select statements (and excluding all other statements) is basically impossible without completely parsing SQL. A regex is not going to be up to the task.
Even if you allow only select statements, users could perform denial-of-service attacks on your database. It is very easy to create select statements that run forever (we've all done it). A malicious user could crash your site in a hurry. And even well-intentioned users might do this by accident.
It would be much better to give the users more limited options for creating reports. Let them select certain tables and columns from a list, and create the appropriate query for them.
There is probably free MySQL reporting software out there that could serve as a good starting point, though I don't have any experience with this myself.
I think that you should rethink the design of your application.
The Users and Log tables should be on one database and the tables with the data for the reports should be on another database.
If you have them all in one database already just create another database, link them and then create synonyms from one database to another only for the tables that the user can access via his queries.
The user will run his queries on the database you have just created and he will be limited to those tables that have synonyms on it.
I do not know if this would be the best option because your description of the case is relatively vague but based on the information I have this could be a solution.

mysql- How to apply grants to column?

username - revoke select to database.Person
I set
GRANT SELECT (id) ON database.Person TO 'username'#'localhost'
not is work ->
SELECT secret FROM Person // Good!
not is work ->
SELECT id FROM Person WHERE secret = 1 // BAD!
I need that would SELECT id FROM Person WHERE secret = 1 is worked!
I'm not sure that I'm understanding the question correctly, but it seems to be asking for the ability to restrict the person selecting data from the Persons table so that they cannot see the value in the Secret column, but they should be allowed to use the Secret column in the interior of the query (in the WHERE clause, etc).
CREATE TABLE Person
(
Id ...,
Secret ...,
...
);
REVOKE ALL ON Person FROM PUBLIC;
GRANT SELECT(id) ON Person TO SomeOne;
So, if my interpretation is correct, when SomeOne selects data:
SELECT Id FROM Person; -- Works (as required)
SELECT Secret FROM Person; -- Fails (as required)
SELECT Id
FROM Person
WHERE Secret = 1; -- Fails (but we want it to work)
SQL does not allow that, and for good reason. Basically, if you can condition query results on Secret, you can determine the value of Secret with repeated queries, so what is supposed to be secret does not remain a secret. It is very easy to leak information.
Looking at the query that fails but "shouldn't"...from its results, you know that every Id returned has the Secret value of 1, so for those Id values, the Secret is no longer secret.
If you look into Statistical Databases, where you're only allowed to search on aggregate data, you find there are things called Unique Trackers which basically allow you to identify the characteristics of one person, even if you're only allowed to see aggregate (SUM, COUNT, ...) values in the result sets. This is a more complex scenario than you're facing (but a fascinating one). C J Date's (long out of print) "Introduction to Database Systems, Vol II" has a discussion of Statistical Database and Unique Trackers. (Google search on 'statistical database unique tracker' reveals useful looking information that is more accessible.)
So, if I've understood what is desired, I believe the desire is misguided — and the SQL standard does not permit what you seek.
Are there any workarounds?
If the query can be built into a view, the person creating the view can access the underlying detail data and grant access to the view, but the people using the view cannot execute the raw query; this might give you protection you seek. Similar comments apply to stored procedures and allow the query to be parameterized better.
That is impossible to work, as you have not allowed access to the "Secret" column. Either you want the programmer to be able to read Secret. In that case, you should GRANT him access to the Secret column.
If you do NOT want to allow access to the Secret column, then you should not allow a WHERE clause either. Using binary search, it is possible to find out the actual value of Secret. Simply perform a SELECT and check if it returns anything each time, and repeat.