I dont know if im doing something completely wrong or im just missing the point of SQL Server security.
Here's what I'm trying to do using SSMS, a simple two-level access (network\DomainUsers, network\SQLAdmins).
Domain users would not be unable to view any tables within SSMS but can access data via applications.
SQLAdmins see all
To start with I thought I had it cracked by setting up a new server role for domain users and assigning view and database/definition permisions then removing these from the public role - no joy!
Staying with the same settings I then branches down to the table to grant permissions but again no joy.
I've setup several roles / users and applied all forms of permissions but as soon as database/definition is altered in public it overrides everything. I thought public was a default setting which then became redundant when other roles became active?
Can someone please point me in the correct direction before either my head pops or the machine learns to fly :-)
SSMS: v17.8.1
SQL Server: 2012
Depending on how you actually defined your roles (which isn't clear from your question) it can simply be that you DENY view any database on the public role. This will in turn make it so everyone is denied. Because everyone is always a part of the public role. (This is why messing with the public role is a bad idea).
Deny's trump Grants. So no matter what you grant them later on, the deny overrides it. So if you denied it at the top level, it will stay like that no matter what you specify later on.
The exception to this is, that you can always see the objects that you own. And members of the sysadmin server role can't be denied since they always jump in as the owner. So you can technically hide all databases by revoking view permissions on the public database. But then you need to make a shared login and assign ownership to the databases that you want to be viewable.
Of note is that in this case, it means they can do whatever they want in said databases. Since you can't 'deny' them rights in something they own (which is why they can view it in the first place).
In overall, you're better off finetuning roles on the DB level, or making some custom server roles depending on what you want to accomplish.
Note, unless you messed with the public role. Logins with no user mapping in a database can't see the tables within a database, they can only see the existance of the database itself.
Related
The problem is our user cannot be granted permission to VIEW ANY DATABASE, nor CREATE DATABASE. So we've setup an account that is db_owner of the database and created blank database to fill.
Tested locally, above works only when we GRANT user to VIEW ANY DATABASE so won't apply in our target environment. My assumption was that EF is trying to establish whether database is already there, but since it cannot see any it'll always try to create one. Is there any way around it? Ideally - is there a setting that will tell EF that DB is there and there's no need to look for it?
This is a bug in EF6. The code makes the incorrect assumption that db_id('dbname') works without VIEW ANY DATABASE. It only works if the login running the query is the database owner. Not a mere member of the DB_OWNER fixed database role. I've reported it, and suggesed an improvement. But I'm not sure it will get fixed.
As a workaround just make the app user the real database owner. That won't prevent sysadmins from connecting as dbo. eg
alter authorization on database::AppDatabase to Appuser
You'll have to drop the database user before making the login the owner.
Our SQL auditors have issues with the Public role being able to query master.sys.syslogins, master.sys.databases, master.sys.configurations from a specific database. Has anyone had to remove these rights to the Public role and does this cause any issues? Thanks all.
This is unfortunately a common false positive when using DB vulnerability scanning tools, and unfortunately there are no absolute answers. It will depend on your particular scenario & auditors to determine if such findings are indeed something you need to change, or accept it as operational risks.
For the most part, I have been able to argue that these permissions are acceptable, especially since the typical best-practice recommendation is to not modify the default permissions granted to public role.
The default permissions granted to public on SQL Server are intended to make tools & some features in SQL Server work, and typically there will be mitigating factors around these permissions.
In the particular case of catalog view access, it is not only governed by having select permission to the catalog view itself, but also by metadata visibility rules. For details Please visit Metadata Visibility Configuration (https://msdn.microsoft.com/en-us/library/ms187113.aspx) on BOL; I especially recommend reading the "Benefits and Limits of Metadata Visibility Configuration" section.
For example, a low-privileged user in the system will have different visibility on sys.server_principals (master.sys.syslogins is deprecated) that a user with sysadmin access:
CREATE LOGIN [test00] WITH PASSWORD = '<s3cr3t P#zzw0Rd>';
ALTER LOGIN [test00] DISABLE;
CREATE LOGIN [test01] WITH PASSWORD = '<s3cr3t P#zzw0Rd>';
ALTER LOGIN [test01] DISABLE;
CREATE SERVER ROLE [srvrole00];
go
ALTER SERVER ROLE [srvrole00] ADD MEMBER [test00]
go
SELECT * FROM sys.server_principals -- Can see all server principals
EXECUTE ('SELECT * FROM sys.server_principals') AS LOGIN = 'test00' -- besides the system principals, can see only himself & the server role he is a member of
EXECUTE ('SELECT * FROM sys.server_principals') AS LOGIN = 'test01' -- besides the system principals, can see only himself
go
You will notice on the results that the 3 principals have a different view of the metadata.
If your SQL auditors think any of these permissions is not acceptable for any reason, you may revoke the permission as they deems as necessary, but the cave-at is that such actions are likely to limit (or in some cases completely break) functionality of SQL server and/or tools. I would strongly recommend looking at what operations they are trying to block/prevent, and act accordingly.
For example. For access to DB metadata, there is one special permission granted by default to public: VIEW ANY DATABASE. This permission was introduced to allow users using SSMS & similar tools to navigate to different databases.
Revoking this permission will affect how some tools work in order to allow you to switch between databases, but it doesn't change the access to the DB; therefore it may be an acceptable trade-off if your users do not need such functionality and you want to prevent users from looking at all the DB metadata.
I hope this information helps. Please feel free to follow up with any question. I will be glad to help.
-Raul
None of our general users even have public access to the Master database, and likely shouldn't in most environments. Only DBAs really need access to the Master database generally. As long as you only grant the public role on the Master database to logins that have any business being in it... then it's really not necessary to remove the public role from any objects in there. If you remove the public role access to those objects, then only system administrators will be able to query them.
Is there a way to prevent that a user sees all databases in an instance? I tried to deny this from user 'mark' by
DENY VIEW ANY DATABASE TO mark
but this prevented him to see (in the SSMS Object Explorer) also the database he is attached to (as a db_reader).
In this case you DENY VIEW ANY DATABASE TO public because "mark" is a member of public (as are all logins). Reference
You don't remove rights for logins indivially because then all rights are lost even where expected.
Generally, if a login has permissions on an object (database, table, whatever) they can see that object in Object Explorer in SSMS
Edit: it's not foolproof and the database owner needs changed. Sorry, forgot about that.
Even if the DB is visible, no rights are conferred or implied.
Here is the scenario. I have a SQL Server 2005 production database/server. It currently has developers and supporters who can connect to it. I need to create a security module that gives developers read-only access to all areas of the database. This means that a developer should be able to view all objects as well as scheduled activities/jobs only.
Is it possible to enable security in this way and if so can I be gently guided on how to achieve this. I am learning to be a DBA and creating snapshots of the databases are not an option.
Thank you all in advance.
There is permission to every object.
Create a stored procedure that grant each gruop the exact permission you need on the objects you need to protect.
I'm not quite sure I follow where this "security module" will be in the architecture. Anyhow, here's one possibility that secures it from the database end.
I'm going to assume you already have users created.
Create a new role (yourdb > security > roles > new database role), say "ReadOnlyDevelopers". Make the owner dbo or whatever makes sense. Do not select any schemas to be owned by the role. Populate the "Role Members" with your developers.
Next, open the properties page on your database. Go to the permissions page. Click Add... and add the new role. Under the permissions grid at the bottom, Grant SELECT to the role.
Now assuming your developers already belong to some other role, you'll need to go into the user properties and under Database Role Membership restrict them to just the new role. At this point they should be able to just read
I'm guessing that I'm missing a detail or two (the role may need to be grated a few additional rights to "see" the database, alter passwords, etc.) but I can't get to that level of detail without setting up the entire scenario. Hopefully this pushes you in the right direction.
I have a SQL Server 2005 database that I'm trying to access as a limited user account, using Windows authentication. I've got BUILTIN\Users added as a database user (before I did so, I couldn't even open the database). I'm working under the assumption that everybody is supposed to have permissions for the "public" role applied to them, so I didn't do anything with role assignment. Under tblFoo, I can use the SSMS Properties dialog (Permissions page) to add "public", then set explicit permissions. Among these is "Grant" for SELECT. But running
SELECT * from tblFoo;
as a limited (BUILTIN\Users) account gives me an error "Select permission denied on object 'tblFoo', database 'bar', schema 'dbo'". In the properties dialog, there's an "Effective Permissions button, but it's greyed out.
Further, I tried creating a non-priv account called "UserTest", adding that at the server level, then mapping it down to the "bar" database. This let me add UserTest to the "Users or Roles" list, which let me run "Effective Permissions" for the account. No permissions are listed at all -- this doesn't seem right. The account must be in public, and public grants (among other things) Select on tblFoo, so why doesn't the UserTest account show an effective permission? I feel like I'm going a bit crazy here.
ASIDE: I am aware that many people don't like using the "public" role to set permissions. This is just my tinkering time; in final design I'm sure we'll have several flexible (custom) database roles. I'm just trying to figure out the behavior I'm seeing, so please no "don't do that!" answers.
UPDATE: Apparently I know just enough SQL Server to be a danger to myself and others. In setting permissions (as I said, "among others"), I had DENY CONTROL. When I set this permission, I think I tried to look up what it did, had a vague idea, and decided on DENY. I cannot currently recall why this seemed the thing to do, but it would appear that that was the reason I was getting permission failures. So I'm updating my question: can anyone explain the "CONTROL" permission, as it pertains to tables?
You only need to have SELECT rights. In raw SQL (see the "script" icon/button in your dialogue box), it's GRANT SELECT ON dbo.tblFoo to public. This is the only permission needed to view the data,
In this case, the error message explicitly mentions "deny". "DENY" is a right in itself, so it mentions it,
If you had no rights, you'd get the message (very approximately) "tblFoo does not exist or you do not have rights"
"DENY CONTROL" is mentioned here. In this case, you denied all rights to the public role.
The grantee effectively has all
defined permissions on the securable
Assuming "UserTest" is a domain user account, connect as a member of the sysadmin role and run
EXEC MASTER.dbo.xp_logininfo 'Domain\UserTest', 'all'
(substituting your domain name for "Domain")
this will display the Windows groups etc. that the account is inheriting security permissions from and the level of access, e.g. you would expect to see something like:
account name type privilege mapped login name permission path
domain\usertest user user domain\usertest BUILTIN\Users
This will help troubleshoot where the account is inheriting permissions from, e.g. which Windows groups it is part of that have permissions to the database. If this all looks OK then I would follow your own advice and not mess with the public role.
Create a database role in your
database
Assign explicit permissions for that
role
Create a server login for your user
account
Open the server login, go to the
User Mapping section, click on the
database and select the database
role you created