Related
The DESCRIBE function of Snowflake can be applied to many objects, like users, warehouses or databases (https://docs.snowflake.com/en/sql-reference/sql/desc.html).
I cannot find what grants are required to execute DESCRIBE. From experiments, I figured out a few things:
- In most cases, only the OWNER of an object is allowed to DESCRIBE that object
- Exception: DESCRIBE DATABASE is allowed to be executed by non-owners
- (Exception: DESCRIBE SCHEMA fails when the schema holds an external table, but this is probably just not implemented)
I cannot find in the documentation what the general grants are in order to perform DESCRIBE. My test seem to suggest that there is no general rule, but I would be very happy of somebody can prove me wrong :-)
From my experiments, all of the basic objects that lie under a schema, such as Tables, Procedures and Functions, File Formats, Stages, etc. will permit DESCRIBE commands if any of its privilege types is granted to the accessor. This implicit behaviour may be why it is not specially called-out in Snowflake's access control documentation page.
For almost all other types of objects, the MONITOR privilege is necessary to permit DESCRIBE commands. Quoting a relevant part from the documentation:
MONITOR
Resource Monitor , Warehouse , Database , Schema, Task
Grants ability to see details within an object (e.g. queries and usage within a warehouse).
I built an Access db which has a SQL Server backend. I have a stubborn and somewhat knowledgable user who will often go into the tables directly. I am attempting to stop this behavior.
The issue I am having is because he is a legitimate user of the database I had to give him read/write access to SQL Server so he could use the db like everyone else. However, no matter how I compile or hide panels at the end of the day all he has to do is open a new blank Access db, use his ODBC connection, link to the SQL Server backend using linked tables, and poof his read-write access allows him to edit tables directly.
Is there some way for me to give users read only or better yet No access what so ever to the SQL Server tables and still have the db function properly? "Properly" meaning users can make record changes like edit comments etc. Sort of like how a website works. The site itself has write access to the backend database and the user is just allowed to make changes using the GUI while on the site.
This problem is solveable only with significant application changes.
You could redesign your application to only use Stored Procedure for data access. No user (at least not the nasty one) has write permission on any table in your database. Every write operation is done via Stored Procedures.
This is a tried and proven approach to securing databases. However, it is used less nowadays because it requires extra efforts to make it work with OR-Mappers and other RAD-Tools like Access. If you implement this approach in an Access Frontend, you’ll have to implement every write operation to the database manually and thus are losing the main RAD advantage of Access.
Why is this user editing data in tables a problem?
If your database has a solid set of validation rules implemented with Constraints and Triggers and has proper auditing in place to know which user changed what, then this should not be a problem. You just let him do it, if he wants to.
But why is the user doing this at all?
If any user rather uses backend tables directly to read and write data, this indicates a massive usability problem with your application. Address the usability issues in your frontend application and the problem will go away while benefiting all of your users!
PS: The concept of application roles, which could be another approach to address this problem, does not work with Access. Access creates new connections to the database on its own. There is no possibility to activate the application role for these connections.
I had to give him read/write access to SQL Server so he could use the
db like everyone else
You can't both give him access and not.
The only way out is speaking to management to ask for formal rules and to tell users to follow these and behave.
Get your IT department to uninstall Access, install the Access Runtime and have him use your application that way.
I have 4 new data entry users who are using a particular GUI to create/update/delete entries in our main database. The "GUI" client allows them to see database records on a map and make modifications there, which is fine and preferred way of doing it.
But lately lot of guys have been accessing local database directly using PGAdmin and running bulk queries (i.e. update, insert, delete,etc) which introduces lot of problems like people updating lot of records without knowing or making mistakes while setting values. It also effects our logging procedures as we are calculating averages and time stamps for reporting purposes which are quite crucial to us.
So is there a way to prevent users from using PGAdmin (please remember lot of these guys are working from home and we do not have access to their machines) and running SQL queries directly in the database.
We still have to give them access to certain tables and allow them to execute sql as long as it's coming through a certain client but deny access to same user when he/she tries to execute a query directly in the db.
The only sane way to control access to your database is converting your db access methods to 3-tier structure. You should build a middleware (maybe some rest API or something alike) and use this API from your app. Database should be hidden behind this middleware, so no direct access is possible. From DB point of view, there are no ways to tell if one database connection is from your app, or from some other tool (pgadmin, simple psql or some custom build client). Your database should be accessible only from trusted hosts and clients should not have access to those hosts.
This is only possible if you use a trick (which might get exploited, too, but maybe your users are not smart enought).
In your client app set some harmless parameter like geqo_pool_size=1001 (if it is 1000 normally).
Now write a trigger that checks if this parameter is set and outputs "No access through PGAdmin" if this parameter is not set like from your app (and the username is not your admin username).
Alternatives: Create a temporary table and check for its existance.
I believe you should block direct access to the database, and set an application to which your clients (humans and software ones) will be able to connect.
Let this application filter and pass only allowed commands.
A great care should be taken in the filtering - I would carefully think whether raw SQL would be allowed at all. Personally, I would design some simplified API, which would make me sure that a hypothetical client-attacker (In God we trust, all others we monitor) would not find a way to sneak with some dangerous modification.
I suppose that from security standpoint your current approach is very unsafe.
You should study advanced pg_hba.conf settings.
this file is the key point for use authorization. Basic settings imply only simple authentification methods like passwords and lists of IP, but you can have some more advanced solution.
GSSAPI
kerberos
SSPI
Radius server
any pam method
So your official client can use a more advanced method, like somthing with a third tier API, some really complex authentification mechanism. Then without using the application it will at least becomes difficult to redo these tasks. If the kerberos key is encrypted in your client, for example.
What you want to do is to REVOKE your users write access, then create a new role with write access, then as this role you CREATE FUNCTION defined as SECURITY DEFINER, which updates the table in a way you allow with integrity checks, then GRANT EXECUTE access to this function for your users.
There is an answer on this topic on ServerFault which references the following blog entry with detailed description.
I believe that using middleware as other answers suggest is an unnecessary overkill in your situation. The above solution does not require for the users to change the way they access the database, just restricts their right to modify the data only through the predefined server side methods.
For a web application database, from a security standpoint only, what are arguments counter to the point for an sp only solution where the app db account has no rights to tables and views and only exec on sps?
If someone intercepts the app db account, the surface area exposed to an attack is much less then when tables and views aren't exposed. What security advantages would a non sp solution offer (or not)? I see many advantages to using a non sp solution, but exposing all the tables leaves me a little worried.
The question is for major database vendor products in general but specifically, sql server 2008.
From a security point of view only, I can't see any advantages a non-SP approach would have over an SP approach because:
you have to grant permissions directly to the underlying tables etc
with a sproc, all the real-underlying schema information can be encapsulated/hidden away (SPs can be encrypted too)
Let's take a system that needs to be really secure, say your company's accounting system. If you use procs and grant access only to the procs, then users cannot do anything other than what the proc does, ever. This is an internal control designed to make sure that the business rules for the system cannot be gotten around by any user of the system. This is what prevents people from making a company purchase and then approving the funds themselves opening up the door to fraud. This also prevents many people in the organization from deleting all records in the accounts table because they do not have delete rights except the ones granted from the proc which will allow only one delete at a time.
Now developers have to have more rights in order to develop, but they should not have more rights on a production machine ever if you want to consider security. True a developer could write a malicous sp which does something bad when put to prod. This same developer though could put the same code into the application version and be as likely to be caught or not causght as if they maliciously change a proc. Personally I think the proc might be easier to catch because it might get reveiwed separately from the code by the dbas which might mean the manager or configuration management person and the dbas had a chance to look at it vice just the manager or configuration management person. We all know reality is that no one pushing code to prod has the time to review each piece of it personally, so hiring trustworthy developers is critical. Having code review and source control in place can help find a malicious change or roll it back to a previous version but the use of sps vice application code are both at risk from developers no matter what.
The same is true for system admins. The must have full rights to the system in order to do their jobs. They can potentially do a lot of damage without being caught. The best you can do in this case is limit this access to as few people as possible and do the best you can in hiring trustworthy people. At least if you have few people with this access, it is easier to find the source of the problem if it occurs. You can minimize risk by having off-site backups (so at least what the admin breaks if they turn bad can be fixed to some extent) but you can never completely get rid of this risk. Again this is true no matter what way you allow the applications to access data.
So the real use of sps is not to eliminate all possible risk, but to make it so fewer people can harm the system. The use of application code to affect database information is inherently unsecure and in my opinion should not be allowed in any system storing financial information or personal information.
The biggest security advantage to not using stored procedures is clarity. You know exactly what an account can do, by seeing what access to tables it has. With stored procedures, this isn't necessarily the case. If an account has the ability to execute procedure X, that does limit the account to executing that and not hitting an underlying table, but X can do anything. It could drop tables, alter data, delete data etc.
To know what an account can do with stored procedures you have to look at the stored procedure. Each time a sproc is updated, someone will have to look at what it does to make sure that something didn't get "accidentally" placed in it. The real problem with security in sprocs comes from inside the organization, not from rogue attackers.
Here's an example:
Let's say you are trying to restrict access to the employee table. Without stored procedures, you just deny access to the table. To get access someone pretty much has to blatantly ask you to grant permissions. Sure they could get you to run a script to grant access, but most people at least try to review a script which alters the database schema (assuming the script doesn't update a sproc, which I will talk about below).
There are potentially hundreds of stored procedures for an application. In my experience, they get updated quite frequently, add a field here, delete one there. For someone to review the number of update procedure scripts all the time becomes daunting, and in most organizations the database team starts to only quickly look at the procedure (or not look at it all), and move it along. This is where the real problem comes in. Now, in this example, if someone on the IT staff wants to allow access to a table, that person just needs to slip in a line of code granting access or doing something else. In a perfect world this would get caught. Most of us don't work in a perfect world.
The real problem with stored procedures is that they add a level of obfuscation to the system. With obfuscation comes complexity, and with complexity comes ultimately more work to understand an administrate the underlying system. Most people in IT are overworked and things slip through. In this instance you don't try and attack the system to gain access, you use the person in charge of the system to get what you want. Mitnick was right, in security people are the problem.
The majority attacks against an organization come from the inside. Any time you introduce complexity into any system, holes appear, things can get overlooked. Don't believe it, think about where you work. Go through the steps about who you would ask to get access to a system. Pretty soon you realize that you can get people to overlook things at the right moment. The key to successfully penetrating a system with people involved is to do something which seems innocuous, but is really subversive.
Remember, if I am trying to attack a system: I am not your friend; I have no interest in your kids or hobbies; I will use you in any way necessary to get what I want; I don't care if I betray you. The idea of "but he was my friend and that's why I trusted him to believe what he was doing was correct," is no comfort after the fact.
This is one of those areas where conventional wisdom is correct: exposing just the stored procedures gives you more control over security. Giving direct access to tables and views is easier, and there are times you need to do it, but it's going to be less secure.
Well, I guess you really captured the core of the problem yourself: if you don't use stored procedures for all CRUD operations, you have to grant at least a app-specific db user account at least SELECT rights on all tables.
If you want to allow the db account to do even more work, that account might also need other permission, like being able to UPDATE and possibly DELETE on certain tables.
I don't see how a non-stored proc approach would have any security benefits - it does open up the gate just a bit more, the question really is: can you afford to? Can you secure that app-specific DB account enough so it won't compromise your system's overall security?
One possible compromise might be to use views or table access to allow SELECT, but handle everything else (UPDATEs, DELETEs, INSERTs) using stored procs - half secure, half convenient...
As it often is - this is a classic trade-off between convenience (non-sp approach; using an ORM possibly) and security (all SProc approach; probably more cumbersome, but a bit safer).
Marc
In addition to the traditional security separation with stored procedures (EXEC permission on procedures, rely on ownership chaining for data access) stored procedures can be code signed, resulting in very granular and specific access control to any server functionality like linked servers, server scoped management views, controlled access to stored procedures and even data in other databases outside of user ordinary access.
Ordinary requests made in T-SQL batches, no matter how fancy and how many layer upon layers of code generation and ORM are behind it, simply cannot be signed and thus cannot use one of the most specific and powerful access control mechanisms available.
It's an imperfect analogy, but I like to compare the tables in the DB's "dbo" schema to "private" data in OO terminology, and Views and Stored Procs to "public." One can even make a "public" schema separate from the dbo schema to make the distinction explicit. If you follow that idea, you get a security advantage as well as an extensibility advantage.
One account (not the web app's account) has dbo access and owns the database, and the web app connects using another account restricted to the public-facing structures.
The only possible argument against is that I have run into cases where certain statements cannot be effectively parameterized in an SP (and dynamic sql is required) and this gives you the possibility of in-SP SQL-injection. This is really a very narrow consideration however and it is a rare case. At least in PostgreSQL I have once in a while seen a few cases where this had to be subject to extra review.
On the whole even in these cases, I think that SP type approaches give you a benefit security-wise because they mean that the application can use generic anti-SQL-Injection mechanisms where it might not otherwise be possible, and your SP can be used by many applications. Additionally if all activity must go through SP's then you can reduce your exposure to sql-injection and centralize the audits for problems.
In general, the less a user can do the less security exposure generally there is. This means the less a user can do with an sql injection attack.
Stored procedures generally give better and more granular security than you can do without.
Most of the answers here specify the security advantages of using stored procedures. Without disregarding those advantages, there are a few big disadvantages that haven't been mentioned:
The data access patterns are sometimes much more important than a specific procedure that is being done. We want to log/monitor/analyze/raise alerts/block who access the data, when, and how. We can't always get this information when using stored procedures.
Some organizations may have tons of stored procedures. It is impossible to review all of them, and it may make more sense to focus on tables (especially when considering that stored procedures may be very complex, have bugs, and introduce other security issues).
Some organizations may require a separation of concerns. Database administrators (or anyone who writes stored procedures) are not always part of the security personal. It is sometimes necessary for the security personal to focus only on the data simply because they are not responsible for the business logic and the guys that do write the business logic, are not completely trusted.
My previous job involved maintenance and programming for a very large database with massive amounts of data. Users viewed this data primarily through an intranet web interface. Instead of having a table of user accounts, each user account was a real first-class account in the RDBMS, which permitted them to connect with their own query tools, etc., as well as permitting us to control access through the RDBMS itself instead of using our own application logic.
Is this a good setup, assuming you're not on the public intranet and dealing with potentially millions of (potentially malicious) users or something? Or is it always better to define your own means of handling user accounts, your own permissions, your own application security logic, and only hand out RDBMS accounts to power users with special needs?
I don't agree that using the database for user access control is as dangerous others are making it out to be. I come from the Oracle Forms Development realm, where this type of user access control is the norm. Just like any design decision, it has it's advantages and disadvantages.
One of the advantages is that I could control select/insert/update/delete privileges for EACH table from a single setting in the database. On one system we had 4 different applications (managed by different teams and in different languages) hitting the same database tables. We were able to declare that only users with the Manager role were able to insert/update/delete data in a specific table. If we didn't manage it through the database, then each application team would have to correctly implement (duplicate) that logic throughout their application. If one application got it wrong, then the other apps would suffer. Plus you would have duplicate code to manage if you ever wanted to change the permissions on a single resource.
Another advantage is that we did not need to worry about storing user passwords in a database table (and all the restrictions that come with it).
I don't agree that "Database user accounts are inherently more dangerous than anything in an account defined by your application". The privileges required to change database-specific privileges are normally MUCH tougher than the privileges required to update/delete a single row in a "PERSONS" table.
And "scaling" was not a problem because we assigned privileges to Oracle roles and then assigned roles to users. With a single Oracle statement we could change the privilege for millions of users (not that we had that many users).
Application authorization is not a trivial problem. Many custom solutions have holes that hackers can easily exploit. The big names like Oracle have put a lot of thought and code into providing a robust application authorization system. I agree that using Oracle security doesn't work for every application. But I wouldn't be so quick to dismiss it in favor of a custom solution.
Edit: I should clarify that despite anything in the OP, what you're doing is logically defining an application even if no code exists. Otherwise it's just a public database with all the dangers that entails by itself.
Maybe I'll get flamed to death for this post, but I think this is an extraordinarily dangerous anti-pattern in security and design terms.
A user object should be defined by the system it's running in. If you're actually defining these in another application (the database) you have a loss of control.
It makes no sense from a design point of view because if you wanted to extend those accounts with any kind of data at all (email address, employee number, MyTheme...) you're not going to be able to extend the DB user and you're going to need to build that users table anyway.
Database user accounts are inherently more dangerous than anything in an account defined by your application because they could be promoted, deleted, accessed or otherwise manipulated by not only the database and any passing DBA, but anything else connected to the database. You've exposed a critical system element as public.
Scaling is out of the question. Imagine an abstraction where you're going to have tens or hundreds of thousands of users. That's just not going to manageable as DB accounts, but as records in a table it's just data. The age old argument of "well there's onyl ever going to be X users" doesn't hold any water with me because I've seen very limited internal apps become publicly exposed when the business feels it's could add value to the customer or the company just got bought by a giant partner who now needs access. You must plan for reasonable extensibility.
You're not going to be able to share conn pooling, you're not going to be any more secure than if you just created a handful of e.g. role accounts, and you're not necessarily going to be able to affect mass changes when you need to, or backup effectively.
All in there seems to be numerous serious problems to me, and I imagine other more experienced SOers could list more.
I think generally. In your traditional database application they shouldnt be. For all the reason already given. In a traditional database application there is a business layer that handles all the security and this is because there is such a strong line between people who interact with the application, and people who interact with the database.
In this situation is is generally better to manage these users and roles yourself. You can decide what information you need to store about them, and what you log and audit. And most importantly you define access based on pure business rules rather than database rules. Its got nothing to do with which tables they access and everything to do with whether they can insert business action here. However these are not technical issues. These are design issues. If that is what you are required to control then it makes sense to manage your users yourself.
You have described a system where you allow users to query the database directly. In this case why not use DB accounts. They will do the job far better than you will if you attempt to analyse the querys that users write and vet them against some rules that you have designed. That to me sounds like a nightmare system to write and maintain.
Don't lock things down because you can. Explain to those in charge what the security implications are but dont attempt to prevent people from doing things because you can. Especially not when they are used to accessing the data directly.
Our job as developers is to enable people to do what they need to do. And in the situation you have described. Specifically connect to the database and query it with their own tools. Then I think that anything other than database accounts is either going to be insecure, or unneccasarily restrictive.
"each user account was a real first-class account in the RDBMS, which permitted them to connect with their own query tools, etc.,"
not a good idea if the RDBMS contains:
any information covered by HIPAA or Sarbanes-Oxley or The Official Secrets Act (UK)
credit card information or other customer credit info (POs, lines of credit etc)
personal information (ssn, dob, etc)
competitive, proprietary, or IP information
because when users can use their own non-managed query tools the company has no way of knowing or auditing what information was queried or where the query results were delivered.
oh and what #annakata said.
I would avoid giving any user database access. Later, when this starts causing problems, taking away their access becomes very dificult.
At the very least, give them access to a read-only replica of the database so they can't kill your whole company with a bad query.
A lot of database query tools are very advanced these days, and it can feel a real shame to reimplement the world just to add restrictions. And as long as the database user permissions are properly locked down it might be okay. However in many cases you can't do this, you should be exposing a high-level API to the database to insert objects over many tables properly, without the user needing specific training that they should "just add an address into that table there, why isn't it working?".
If they only want to use the data to generate reports in Excel, etc, then maybe you could use a reporting front end like BIRT instead.
So basically: if the users are knowledgeable about databases, and resources to implement a proper front-end are low, keep on doing this. However is the resource does come up, it is probably time to get people's requirements in for creating a simpler, task-oriented front-end for them.
This is, in a way, similar to: is sql server/AD good for anything
I don't think it's a bad idea to throw your security model, at least a basic one, in the database itself. You can add restrictions in the application layer for cosmetics, but whichever account the user is accessing the database with, be it based on the application or the user, it's best if that account is restricted to only the operations the user is allowed.
I don't speak for all apps, but there are a large number I have seen where capturing the password is as simple as opening the code in notepad, using an included dll to decrypt the configuration file, or finding a backup file (e.g. web.config.bak in asp.net) that can be accessed from the browser.
*not a good idea if the RDBMS contains:
* any information covered by HIPAA or Sarbanes-Oxley or The Official Secrets Act (UK)
* credit card information or other customer credit info (POs, lines of credit etc)
* personal information (ssn, dob, etc)
* competitive, proprietary, or IP information*
Not true, one can perfectly manage which data a database user can see and which data it can modify. A database (at least Oracle) can also audit all activities, including selects. To have thousands of database users is also perfectly normal.
It is more difficult to build good secure applications because you have to program this security, a database offers this security and you can configure it in a declarative way, no code required.
I know, I am replying to a very old post, but recently came across same situation in my current project. I was also thinking on similar lines, whether "Application users be Database users?".
This is what I analysed:
Definitely it doesn't make sense to create that big number of application users on database(if your application is going to be used by many users).
Let's say you created X(huge number) of users on database. You are opening a clear gateway to your database.
Let's take a scenario for the solution:
There are two types of application users (Managers and Assistant). Both needs access to database for some transactions.
It's obvious you would create two roles, one for each type(Manager and Assistant) in database. But how about database user to connect from application. If you create one account per user then you would end up linearly creating the accounts on the database.
What I suggest:
Create one database account per Role. (Let's say Manager_Role_Account)
Let your application have business logic to map an application user with corresponding role.(User Tom with Manager role to Manager_Role_Account)
Use the database user(Manager_Role_Account) corresponding to identified role in #2 to connect to database and execute your query.
Hope this makes sense!
Updated: As I said, I came across similar situation in my project (with respect to Postgresql database at back end and a Java Web app at front end), I found something very useful called as Proxy Authentication.
This means that you can login to the database as one user but limit or extend your privileges based on the Proxy user.
I found very good links explaining the same.
For Postgresql below Choice of authentication approach for
financial app on PostgreSQL
For Oracle Proxy Authentication
Hope this helps!
It depends (like most things).
Having multiple database users negates connection pooling, since most libraries handle pooling based on connection strings and user accounts.
On the other hand, it's probably a more secure solution than anything you or I will do from scratch. It leaves security up to the OS and Database server, which I trust much more than myself. However, this is only the case if you go to the effort to configure the database permissions well. If you're using a bunch of OS/db users with the same permissions,it won't help much. You'll still get an audit trail, but that's about it.
All that said, I don't know that I'd feel comfortable letting normal users connect directly to the database with their own tools.
I think it's worth highlighting what other answers have touched upon:
A database can only define restrictions based on the data. Ie restrict select/insert/update/delete on particular tables or columns. I'm sure some databases can do somewhat cleverer things, but they'll never be able to implement business-rule based restrictions like an application can. What if a certain user is allowed to update a column only to certain values (say <1000) or only increase prices, or change either of two columns but not both?
I'd say unless you are absolutely sure you'll never need anything but table/column granularity, this is reason enough by itself.
This is not a good idea for any application where you store data for multiple users in the same table and you don't want one user to be able to read or modify another user's data. How would you restrict access in this case?