37

I am seeing an error message when trying to execute xp_cmdshell from within a stored procedure.

xp_cmdshell is enabled on the instance. And the execute permission was granted to my user, but I am still seeing the exception.

The EXECUTE permission was denied on the object ‘xp_cmdshell’, database ‘mssqlsystemresource’, schema ‘sys’

Part of the issue is that this is a shared cluster, and we have a single database on the instance, so we don't have a full range of admin permissions. So I can't go in and grant permissions, and what-not.

David Griffiths
  • 640
  • 1
  • 7
  • 14
  • 5
    Why are you using the most dangerous stored procedure ever built? (`xp_cmdshell`) – SLaks Jan 06 '10 at 22:18
  • 1
    It's older code, and no time to currently rewrite. We are using it to call BCP to import a file into a temp table for processing. The temp table is dynamic sql, and we generate the .fmt file based on the same logic that the dynamic sql uses. It would be more than a day to re-implement this. – David Griffiths Jan 06 '10 at 22:22
  • Can you post the exact SQL Server version number, including build number? – Remus Rusanu Jan 06 '10 at 22:28
  • SQLServer 2005, 9.00.3042.00, Enterprise Edition, 64-bit – David Griffiths Jan 06 '10 at 22:31
  • Is it possible to run this query on your system and post the date returned? `select expiry_date from master.sys.certificates where name = '##MS_SQLResourceSigningCertificate##'` – Remus Rusanu Jan 06 '10 at 22:32
  • No results returned. No results returned when I skip the where clause and select everything from master.sys.certificates. It may be a permissions issue – David Griffiths Jan 06 '10 at 22:35
  • It is a permission issue (the no return). I tried on an close build (3077, SP2) and the certificate is set to expire in 2017, so it should be fine. Besides, code signing is supose to validate the expiry time at signing time, not at verification time. I asked you to do this because is very weird to see the permission denied to refer to mssqlsystemresource db. – Remus Rusanu Jan 06 '10 at 22:45
  • Ok - thanks. I figured. I've seen solutions using a proxy-account, but I am remote-controlling a DBA that has full access to the site. The commands I am sending are getting more and more complicated. – David Griffiths Jan 06 '10 at 22:51

6 Answers6

64

For users that are not members of the sysadmin role on the SQL Server instance you need to do the following actions to grant access to the xp_cmdshell extended stored procedure. In addition if you forgot one of the steps I have listed the error that will be thrown.

  1. Enable the xp_cmdshell procedure

    Msg 15281, Level 16, State 1, Procedure xp_cmdshell, Line 1 SQL Server blocked access to procedure 'sys.xp_cmdshell' of component 'xp_cmdshell' because this component is turned off as part of the security configuration for this server. A system administrator can enable the use of 'xp_cmdshell' by using sp_configure. For more information about enabling 'xp_cmdshell', see "Surface Area Configuration" in SQL Server Books Online.*

  2. Create a login for the non-sysadmin user that has public access to the master database

    Msg 229, Level 14, State 5, Procedure xp_cmdshell, Line 1 The EXECUTE permission was denied on the object 'xp_cmdshell', database 'mssqlsystemresource', schema 'sys'.*

  3. Grant EXEC permission on the xp_cmdshell stored procedure

    Msg 229, Level 14, State 5, Procedure xp_cmdshell, Line 1 The EXECUTE permission was denied on the object 'xp_cmdshell', database 'mssqlsystemresource', schema 'sys'.*

  4. Create a proxy account that xp_cmdshell will be run under using sp_xp_cmdshell_proxy_account

    Msg 15153, Level 16, State 1, Procedure xp_cmdshell, Line 1 The xp_cmdshell proxy account information cannot be retrieved or is invalid. Verify that the '##xp_cmdshell_proxy_account##' credential exists and contains valid information.*

It would seem from your error that either step 2 or 3 was missed. I am not familiar with clusters to know if there is anything particular to that setup.

Community
  • 1
  • 1
  • Step 4 wasn't necessary for me for a SQL Server 2008 R2 instance. – Kenny Evitt Aug 15 '18 at 14:35
  • 1
    as mentioned a few times below, but repeated here under the high scoring answer... Give user Log on as batch job: Open Local Security Policy -> Local Policies -> User Rights Assignment. Add user to "Log on as a batch job" – Trubs Aug 28 '20 at 02:55
54

I want to complete the answer from tchester.

(1) Enable the xp_cmdshell procedure:

-- To allow advanced options to be changed.
EXEC sp_configure 'show advanced options', 1
RECONFIGURE
GO

-- Enable the xp_cmdshell procedure
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE
GO

(2) Create a login 'Domain\TestUser' (windows user) for the non-sysadmin user that has public access to the master database

(3) Grant EXEC permission on the xp_cmdshell stored procedure:

GRANT EXECUTE ON xp_cmdshell TO [Domain\TestUser]

(4) Create a proxy account that xp_cmdshell will be run under using sp_xp_cmdshell_proxy_account

EXEC sp_xp_cmdshell_proxy_account 'Domain\TestUser', 'pwd'
-- Note: pwd means windows password for [Domain\TestUser] account id on the box.
--       Don't include square brackets around Domain\TestUser.

(5) Grant control server permission to user

USE master;
GRANT CONTROL SERVER TO [Domain\TestUser]
GO
Jared
  • 1,385
  • 11
  • 21
nZeus
  • 2,475
  • 22
  • 21
  • 2
    Doesn't GRANT CONTROL SERVER TO [Domain\TestUser] effectively give sysadmin rights to that user? I thought the whole idea was to minimise the permissions on that user? – Colin Feb 26 '13 at 15:42
  • 2
    When I read this I thought that the non-sys admin user had to be a windows account and was also the proxy account. Not true. The proxy account needs to be windows. Then any non-sys admin user needs public access to master and execute permission on xp_cmdshell – Colin Feb 27 '13 at 00:33
  • 1
    In my case step 4 was completely unnecessary! – Johan Jul 30 '14 at 10:52
  • 1
    If you get this error running step 4: Msg 15137, Level 16, State 1, Procedure sp_xp_cmdshell_proxy_account, Line 1 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: ‘5’ Open SQL Server Management Studio with Admin permission. Credit to: https://dbamohsin.wordpress.com/2017/02/22/xp_cmdshell_proxy_account-credential-could-not-be-created/ – Raphael Nov 17 '17 at 12:44
  • 1
    As @Colin correctly stated above, I also wouldn't give the user the `CONTROL SERVER` permission. Instead you can grant her the permission to log in as batch in Windows as described [here](https://dbamohsin.wordpress.com/2017/05/02/xp_cmdshell-raises-error-a-call-to-logonuserw-failed-with-error-code-1385/). Open *Local Security Settings* in Windows, go to *Local Policies* -> *User Assignment* -> *Log on as batch job* and add the Windows account `[Domain\TestUser]` there. Worked for me without giving too many permissions to the domain user on the server. – taffit Mar 01 '18 at 13:14
1

tchester said:

(2) Create a login for the non-sysadmin user that has public access to the master database

I went to my user's database list (server/security/connections/my user name/properties/user mapping, and wanted to check the box for master database. I got an error message telling that the user already exists in the master database. Went to master database, dropped the user, went back to "user mapping" and checked the box for master. Check the "public" box below.

After that, you need to re-issue the grant execute on xp_cmdshell to "my user name"

TylerH
  • 20,799
  • 66
  • 75
  • 101
Yves Forget
  • 101
  • 3
  • 10
1

To expand on what has been provided for automatically exporting data as csv to a network share via SQL Server Agent.

(1) Enable the xp_cmdshell procedure:

-- To allow advanced options to be changed.
EXEC sp_configure 'show advanced options', 1
RECONFIGURE
GO

-- Enable the xp_cmdshell procedure
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE
GO

(2) Create a login 'Domain\TestUser' (windows user) for the non-sysadmin user that has public access to the master database. Done through user mapping

(3) Give log on as batch job: Navigate to Local Security Policy -> Local Policies -> User Rights Assignment. Add user to "Log on as a batch job"

(4) Give read/write permissions to network folder for domain\user

(5) Grant EXEC permission on the xp_cmdshell stored procedure:

GRANT EXECUTE ON xp_cmdshell TO [Domain\TestUser]

(6) Create a proxy account that xp_cmdshell will be run under using sp_xp_cmdshell_proxy_account

EXEC sp_xp_cmdshell_proxy_account 'Domain\TestUser', 'password_for_domain_user'

(7) If the sp_xp_cmdshell_proxy_account command doesn't work, manually create it

create credential ##xp_cmdshell_proxy_account## with identity = 'Domain\DomainUser', secret = 'password'

(8) Enable SQL Server Agent. Open SQL Server Configuration Manager, navigate to SQL Server Services, enable SQL Server Agent.

(9) Create automated job. Open SSMS, select SQL Server Agent, then right-click jobs and click "New Job".

(10) Select "Owner" as your created user. Select "Steps", make "type" = T-SQL. Fill out command field similar to below. Set delimiter as ','

EXEC master..xp_cmdshell 'SQLCMD -q "select * from master" -o file.csv -s "," 

(11) Fill out schedules accordingly.

Schylar
  • 774
  • 1
  • 5
  • 13
0

Time to contribute now. I am sysadmin role and worked on getting two public access users to execute xp_cmdshell. I am able to execute xp_cmdshell but not the two users.

I did the following steps:

  1. create new role:

    use master
    CREATE ROLE [CmdShell_Executor] AUTHORIZATION [dbo]
    GRANT EXEC ON xp_cmdshell TO [CmdShell_Executor]

  2. add users in master database: Security --> Users. Membership checks only [CmdShell_Executor] that is just created

  3. set up proxy account:

    EXEC sp_xp_cmdshell_proxy_account 'domain\user1','users1 Windows password'
    EXEC sp_xp_cmdshell_proxy_account 'domain\user2','users2 Windows password'

Then both users can execute the stored procedure that contains xp_cmdshell invoking a R script run. I let the users come to my PC to type in the password, execute the one line code, then delete the password.

Laura Y
  • 1
  • 1
-2

Don't grant control to the user, it's totally unnecessay. Select permission on the database is enough. After you have created the login and the user on master (see above answers):

use YourDatabase
go
create user [YourDomain\YourUser] for login [YourDomain\YourUser] with default_schema=[dbo]
go
alter role [db_datareader] add member [YourDomain\YourUser]
go