I have a public user and need to exec xp_regread. However I keep getting the error
xp_regread() returned error 5, 'Access is denied.'
even though I granted the exec permission to that user & read permission for the registry key.
USE master
GO
GRANT EXECUTE ON [sys].[xp_regread] TO [domain\user]
GO
Can anyone give me some advise?
Related
I want to create a proxy user that will be able to run xp_cmdshell tasks like an administrator user does.
Note: I don't want to give this new user sysadmin permissions!
When I login from administrator, I can create the credentials for the proxy user and when I run select * From sys.credentials I can see the created credential there but when I try to run a simple xp_cmdshell task from the testuser like EXECUTE MASTER ..XP_CMDSHELL 'echo HI'
it gives an error like:
The server principal "testuser" is not able to access the database "master" under the current security context.
From the administrator side I tried:
EXEC sp_configure 'show advanced options', 1
RECONFIGURE
GO
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE
GRANT EXECUTE ON xp_cmdshell TO [testuser]
create credential xp_cmdshell_proxy_account with identity = 'test\testuser', secret = 'test123'
When I run all these statements they all give me a successful response but if I try to run the credential like : EXEC sp_xp_cmdshell_proxy_account 'test\testuser','test123';
I get an error saying:
An error occurred during the execution of sp_xp_cmdshell_proxy_account. Possible reasons: the provided account was invalid or the '##xp_cmdshell_proxy_account##' credential could not be created. Error code: 0(null), Error Status: 0.
Can you help me and tell me what I am missing here?
I have restored a SQL Server 2019 database from a .BAK file to a Google Cloud SQL instance.
I can connect to the instance using Visual Studio SQL Connection. I issue the following command to check the database owner, which should be: mydb_adm
USE master;
SELECT suser_sname(owner_sid) AS 'DB Owner' FROM sys.databases WHERE name = 'mydb';
DB Owner
--------
sqlserver
The above is expected, as the restore was done while using the sqlserver account which is the default user created when the SQL instance is provisioned by Google Cloud (according to the docs).
So, I need to change the DB owner; I execute the following command:
USE mydb
EXEC sp_changedbowner 'mydb_adm'
The system displays the following error message:
Msg 15151, Level 16, State 1, Line 1
Cannot find the principal 'mydb_adm', because it does not exist or you do not have permission.
The same message is displayed for:
ALTER AUTHORIZATION ON DATABASE::mydb TO mydb_adm;
However, the "mydb_adm" principal DOES exist, i.e.:
SELECT name, sid FROM sys.server_principals WHERE name = 'mydb_adm';
name sid
---- ---
mydb_adm 0xD81398C7DB0D724BB2738A2EC59BB554
.. so it must be a permission problem with the sqlserver account. When I query the DB, it appears the "sqlserver" user does NOT have ALTER permissions, i.e.:
UserName Permission Type Permission State
-------- --------------- ----------------
sqlserver ALTER DENY
... So how can I change the database owner or issue any ALTER commands using the "sqlserver" account? (There seems to be no way to grant the ALTER permission to the sqlserver user).
Any help / advice would be appreciated.
Thank-you to #DanGuzman for providing a "work-around", i.e.: while connected to the SQL instance using the "sqlserver" user, the following commands were used:
USE mydb;
CREATE USER mydb_adm;
ALTER ROLE db_owner ADD member mydb_adm;
After some additional digging, I also found the following in the Google Cloud docs at https://cloud.google.com/sql/docs/sqlserver/users, which states:
Cloud SQL for SQL Server is a managed service, so it restricts access
to certain system stored procedures and tables that require advanced
privileges. In Cloud SQL, you cannot create or have access to users
with superuser permissions.
Note: The sysadmin role is not supported. Therefore, you cannot run
system stored procedures that require the sysadmin role. As one of
the many examples, you cannot run the sp_OADestroy stored procedure
because it requires the sysadmin role.
As well as the following from the SQL Server docs at https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-authorization-transact-sql?view=sql-server-ver15#remarks, which state:
Requirements for the person executing the ALTER AUTHORIZATION
statement: If you are not a member of the sysadmin fixed server role,
you must have at least TAKE OWNERSHIP permission on the database, and
must have IMPERSONATE permission on the new owner login.
hence, commands such as EXEC sp_changedbowner ... or ALTER AUTHORIZATION ON DATABASE:: ... will raise the error (Msg 15151, ... you do not have permission.)
Hope that helps anyone else that may run into this type of issue.
I'm having an issue giving a single user the ability to perform
select * from msdb..sysmail_profile
I get the following error:
Msg 229, Level 14, State 5, Line 1
The SELECT permission was denied on the object 'sysmail_profile', database 'msdb', schema 'dbo'
I've tried to grant permissions by using:
use msdb;
grant select on msdb.dbo.sysmail_profile to [My User];
but still no avail. However, if I do the exact same grant permission command for [Public], then the user is able to perform the needed select statement, but I don't want [Public] to have access to select from that table.
I have not found any Deny's anywhere for this user, yet I am still unable to give this single user SELECT permissions. Any thoughts?
I think your context is not switched. Try with EXECUTE AS and see if the issue still persists. For me, the below code worked successfully without issues.
use master
go
CREATE LOGIN TestLogin with password = 'YOURSTRONGPASSWORD'
GO
use msdb
go
CREATE USER TestLogin for login testlogin
GO
grant select on msdb.dbo.sysmail_profile to [testlogin]
GO
EXECUTE AS user = 'Testlogin'
go
SELECT * FROM msdb.dbo.sysmail_profile
go
Revert
go
make sure in security > logins > [myuser]> user mapping > check msdb
(if the user still does not have access try to revoke public server role because I think the default in public server role for msdb is denied)
use msdb;
REVOKE select on msdb.dbo.sysmail_profile to public;
The problem can be emulated this way:
DECLARE #C1 BIGINT,#C2 BIGINT;
PRINT SUSER_NAME()+ ' '+ USER_NAME();
SELECT #C1=transaction_id from sys.dm_tran_current_transaction (nolock)
PRINT #C1
EXECUTE AS USER = 'dbo';
PRINT SUSER_NAME()+ ' '+ USER_NAME();
SELECT #C2=transaction_id from sys.dm_tran_current_transaction (nolock)
PRINT #C2
REVERT;
Called from 'Administrator' login (db owner, linked to dbo user) returns:
Administrator dbo
2209599
Administrator dbo
Msg 297, Level 16, State 1, Line 7
The user does not have permission to perform this action.
The same user but different results. Why?
Details:
I have a SP that contains select from sys.dm_os_sys_info and therefore this SP's caller should have VIEW SERVER STATE permissions.
I have modified SP header with "WITH EXECUTE AS OWNER". Owner is standard 'dbo' database user linked to 'Administrator' server login. Administrator is a member of sysadmin and have effective permission 'VIEW SERVER STATE', but execution of my modified procedure brings the 'The user does not have permission to perform this action' error... I see there logic since DBO database user by itself doesn't have server permissions (even if Administrator login has). But what next?
I have tried:
GRANT VIEW SERVER STATE TO DBO - doesn't work because of 'dbo is
not a user-defined server role' error.
Create new user 'ServerStateViewer' linked to 'Administrator' - doesn't work becuase of 'the login already has an account under a different user name' (as I understand it - dbo user exits in the dabatabse)
Create new user 'ServerStateViewer' not linked to any login - doesn't work because I can't to add any server permissions to this user.
WITH EXECUTE AS 'Administrator' - doesn't work because of 'Administrator is not a database user' error.
So it seems I'm forced to create new server login. I am interesting, may be there are still other ways to get WITH EXECUTE AS working under dbo user / Administrator login permissions?
You'll need to use code signing. This is not a problem, since code signing is what you should be using to start with to grant permission to procedures... The proper sequence is this:
inspect the procedure code to ensure that you trust it
change the procedure to have an EXECUTE AS OWNER clause
create a certificate with a private key in the SP's database
sign the procedure with the private key of the certificate you created
drop the private key of the certificate (to prevent it from ever being used again)
copy the certificate into the master database
create a login from the certificate
grant AUTHENTICATE SERVER to the certificate derived login
grant any additional priviledge required by the procedure (e.g. VIEW SERVER STATE) to the certificate derived login
For an example see Signing an activate procedure.
Note that during development code signing can be a pain because you will have to re-sign the procedure after every change to it. For dev purposes, do not drop the private key right after signing, so it can be reused.
I have a client that is having an 'Access Denied' to a call to xp_regread (trying to find the database path), but I cannot seem to reproduce this. I have tried running the following
REVOKE execute on xp_regread to public
But it still works. I also found some articles on SQL Server 2000 problems (http://support.microsoft.com/kb/887165) but the clients server is 2005. Any ideas on how to go about fixing this problem.
Edit: I have tried the following
USE MASTER
GO
REVOKE execute on xp_regread to public
GO
DECLARE #InstanceName nvarchar( 128 )
SET #InstanceName = ISNULL( CONVERT( nvarchar( 128 ), SERVERPROPERTY( 'InstanceName' ) ), N'MSSQLSERVER' )
DECLARE #InstanceKey nvarchar( 128 )
EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\Microsoft SQL Server\Instance Names\SQL\', #InstanceName, #InstanceKey OUTPUT
print #InstanceName
print #InstanceKey
But it is still working. To be clear, I am trying to reproduce an issue where the call does NOT work. Revoking permissions was one way that I read should do it, but it still works for me.
It's an extended stored procedure so needs
EXEC master..xp_regread ...
Then, it would be
USE master
GO
GRANT EXECUTE ON xp_regread TO public
GO
If an explicit DENY has been set then REVOKE will remove it. This is not the same as GRANT though. This only applies to a normal user.
Anyone with sysadmin rights or db_owner in master (sa is dbo in master) will bypass permissions anyway
You should explicitly DENY the permission:
GRANT DENY ON xp_regread TO XYuser.
Be careful though, it might cause issues later. Like the backup dialog in SSMS won't work for that person.
To reproduce the issue, first you have to make a difference between two different errors: 'Access is denied.' and 'EXECUTE permission was denied'.
The first error is due to a configuration issue over a non sysadmin user. The second is due to lack of execute permission over the extended procedure.
For both please follow the post How to configure permissions for xp_regread