Prevent delete/update for tables by even superadmin/dba? - mysql

There are some mission critical tables which i need to ensure never get deleted or edited. only possible action is to read from it and the dba can add more rows. That's it.
Now for added security i want to prevent even the dba from being able to delete/alter the records, so basically no one can ever delete or alter a record, no super admin also. These tables are critical for activity tracking of certain type of users who's data i need to preserve indefinitely and some are critical lookup tables. So a mixture of system locked values and user tracked values.
Idea is if someone wants to destroy the data they need to kill that database. Is there a way to do this?

No, not possible, the superuser is always in control of the database. You could REVOKE update and delete permissions, but a superuser can always GRANT these permissions to himself again.

There is no way you can prevent a superuser to do something. The only thing you can do is prevent ANY user from ACCIDENTALLY deleting or updating the records. This can be achieved by creating rule on update and on delete.
CREATE [ OR REPLACE ] RULE name AS ON event
TO table [ WHERE condition ]
DO [ ALSO | INSTEAD ] { NOTHING | command | ( command ; command ... ) }
See this link for reference.

For MySQL, the following approach can be taken.
Once you have your application accounts in place, drop the superuser account (really, any account "WITH GRANT OPTION"). The system admin accounts should only have permission to stop and start the system, but not to read from your sensitive table.
Next, alter your table so that it uses the MEMORY engine. This means that the application administrator (not the DBA) will need to restore the contents whenever the database is restarted. It also means that the DBA cannot restart the database with the "skip-grants" option to gain access to the data - because the data will evaporate during the restart. (However, the system's root user can always dump the system memory and find your data in that.)
A better approach is to encrypt your data in the application with a key only known by the application administrator.

Related

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!

How can I make some tables read-only but allow users to create new ones?

I'm working on some data project with a few other collaborators. Most are fairly new to SQL so have inquired if I can make the 'raw' data tables read-only so they aren't accidentally altered, how would I go about doing that? Currently all users have GRANT SELECT ON mydb.* TO 'user'#'%' permissions, but I need to be a little more open.
There's a question about making a single table read-only, but it seems like it would deny users the ability to make other tables; or if they did, they couldn't do anything with them. There doesn't seem to be (or I can't find) a 'deny' setting like in NTFS that overrides allow/GRANT; from what I read REVOKE is only the opposite of a prior GRANT, you can't "nest" them.
I was considering making a separate 'raw' database that would be SELECT-only so users could copy it into the 'workspace' database, but that seems a bit hacky and will eat up some semi-significant amount of space on my budget cloud server. What's the proper solution?
GRANT SELECT ON example.* to 'someuser'#'somehost';
Give read only privilege.
GRANT CREATE ON example TO 'someuser'#'somehost';
Give create table privilege.
You can make a single MyISAM table read only by compressing the table. Use myisampack on the command line to pack the table.
More info can be found in the MySQL Manual: http://dev.mysql.com/doc/refman/5.0/en/myisampack.html

How do I write to an external audit database in SQL Server 2008?

I have a SQL Server 2008 database with 10 windows users who all have permissions to Insert, Update and Delete tables. Each table has a trigger that writes to an audit table in a different database.
Currently for this to work I have to give the user write permissions to the audit database as well, otherwise the trigger will throw an error.
I could give Insert permission only for each individual user, but I was hoping that there might be a more elegant solution for this problem. Especially from a standpoint that users get deleted/added which would mean setting them up in two databases rather than one.
Ideally I would like to use one account that does all the audit work.
When you create a trigger you have the option to specify credentials: see "Execute As" (http://msdn.microsoft.com/en-us/library/ms189799.aspx and http://msdn.microsoft.com/en-us/library/ms188354.aspx).

Database Authorised Updates

How do I design a database structure so that a number of user of a database can add, update and delete records which may include foreign keys from some of the database's tables and prevent these changes from going live until the user's supervisor authorises these changes, some of these changes or declines these changes from occuring. The database will eventualy have a number of these groups of users and supervisors.
What is the best methodology, or system for this, I am using MySQL database at present.
Views.
All access to "live" data should be through views. The views should select only only those rows that have been "authorized". You'll want to manage permissions (SQL GRANT and REVOKE statements) so application code can't bypass the views by going directly to the tables.
This might not be obvious, but that means that all the user interface code needs to go to the views, too. For example, most user interfaces will ease the burden of picking the right foreign key by loading a combo box or list box, popping up a modal dialog, or something along those lines. Those interface elements need to get their data from views of "authorized" rows, too.