xp_cmdshell access in SQL Server - sql-server

I had inherited a stored procedure from a colleague that uses the xp_cmdshell within it. In order to enable this feature for the particular login, I need to run the following commands to enable it.
EXEC sp_configure 'show advanced options', 1
GO
-- To update the currently configured value for advanced options.
RECONFIGURE
GO
-- To enable the feature.
EXEC sp_configure 'xp_cmdshell', 1
GO
-- To update the currently configured value for this feature.
RECONFIGURE
GO
I had added sysadmin server role access to this particular login, and running this stored procedure require sysadmin access so far.
We had granted this particular user with sysadmin access in the development SQL Server. As we migrate the stored procedure to production environment, DBA had concerns there is too much privilege for this user in production environment.
Is there any way we can continue to run the stored procedure with this login without the sysadmin access in the production environment?
Thank you for your help in advance.

Thanks for all the help. I am continuing the comment here as I need markup for the sample code.
The stored procedure tries to perform basic file IO operation to move, copy, delete files to a network drive.
e.g. exec #ret_val = master..xp_cmdshell #stmt, no_output #stmt
#stmt can be "copy //hostname/mapdrive/subdirectory/somefile //hostname/mapped directory" using sharing mechanism.
or create a subdirectory.
e.g. select #stmt = 'md '+#pri_path
I believe they perform this using stored procedure so they can contain all the file I/O operation within the stored procedure.
As for the xp_cmd_shell_proxy_account, I found this https://msdn.microsoft.com/en-us/library/ms190359.aspx. Based on my interpretation, we are providing a windows login username and password to the sql server to gain access to a shell. Am I correct?
Thanks.

Related

SQL xp_create_subdir for non-admin

I'd like to give a non-admin the ability to create folders on the SQL server's local hard disk using xp_create_subdir. Reason - need to create a folder structure so that manufacturing equipment can FTP large files. Meta data for the files is stored in SQL.
Server is SQL 2016 Express. OS is Windows 10 Pro.
I've found lots of explanations of how to get this to work but can't figure out what I'm missing. Using the SA account I've created a stored procedure like this:
use [DBname]
CREATE PROCEDURE dbo.usp_CreateDirectory
#directoryFullPath varchar(500)
WITH EXECUTE AS owner
AS
BEGIN
SET NOCOUNT ON;
EXEC master.dbo.xp_create_subdir #directoryFullPath;
END
GO
GRANT EXECUTE ON dbo.usp_CreateDirectory TO [TestUser]
GO
Code to run the stored procedure:
DECLARE #RC int
DECLARE #directoryFullPath varchar(500)
set #directoryFullPath = 'd:\FTP_Root\2020\08\22\'
EXECUTE #RC = dbo.usp_CreateDirectory
#directoryFullPath
GO
In Windows I've given NT Service\MSSQL${InstanceName} full access to d:\FTP_Root\
What am I missing? Running xp_create_subdir 'C:\FTP_Root\2020\08\22' in MSSMS works fine.
Running the stored procedure as SA or the non-admin TestUser gives this result:
Msg 229, Level 14, State 5, Procedure xp_create_subdir, Line 1 [Batch
Start Line 2] The EXECUTE permission was denied on the object
'xp_create_subdir', database 'mssqlsystemresource', schema 'sys'.
I found this on another site: https://www.sqlservercentral.com/forums/topic/xp_create_subdir-for-non-sysadmins
The headlines here are two main points
Although this post is old,
In order to solve this issue, you should make sure that your database is Trustworthy - since the SP xp_create_subdir is on different DB
You still need to set "with Execute as 'dbo'
alter database [DBNAME] set trustworthy on
- Guy-456224
And DO understand the security ramifications of using SET TRUSTWORTHY ON. It may not be a problem or... it may. "It Depends" but you won't know until you read about it.
- Jeff Moden
I completely agree with Jeff on this one. If you remotely care about security, understand what the TRUSTWORTHY setting does before adjusting it.
I think the larger question here is to ask why SQL Server needs to create the directory? Powershell could both query the database for the Directory Path and create the Directory. You could have a SQL Server Agent job that will execute this under the security context of either a SQL Server Proxy account, or the SQL Agent service account (I would pick the proxy account personally, but that's just me).

Get full capacity of a disk via SQL query without granting permissions?

I've been struggling to get the total capacity of a disk drive where SQL Server is installed; I know I can achieve that with sys.dm_os_volume_stats or xp_cmdshell but to run the query you need some permissions like VIEW SERVER STATE or ALTER permission.
Is there a way for a normal user to get the full capacity of the disk without granting special permissions?
You can Execute any Stored Procedure or Table Value Function as a specific caller :
CREATE PROCEDURE dbo.MyProcedure
WITH EXECUTE AS 'domain\user'
AS
...
More info in StackOverflow
More info in MSDN
Also, If you got a Certificate problem :
Signing Stored Procedures with a Certificate

Cannot enable select into/bulkcopy on SQL Server 2005 database using sp_dboption

I am trying to enable the select into/bulkcopy database option on a SQL Server 2005 database using the command:
EXEC sp_dboption 'mydbname', 'select into/bulkcopy', 'true'
After executing the above, running EXEC sp_dboption 'mydbname', 'select into/bulkcopy' tells me that the option is still set to OFF.
I've confirmed that my Windows login is a user in the database and that it belongs to the db_owner role. Having read the MSDN Documentation for sp_dboption, this appears to be the only prerequisite for using the procedure to change options on a database.
Are there any other steps or settings I am missing that could prevent me from being able to enable this option?
That procedure is deprecated. You can use
ALTER DATABASE [mydbname] SET RECOVERY BULK_LOGGED WITH NO_WAIT
This seems to happen if your DB is currently in SIMPLE recovery model.
Looking at the sp_dboption procedure definition the relevant bit of code is
if #alt_optvalue = 'ON'
begin
if databaseproperty(#dbname, 'IsTrunclog') = 1
select #alt_optvalue = 'RECMODEL_70BACKCOMP'
else
select #alt_optvalue = 'BULK_LOGGED'
end
The effect of running ALTER DATABASE [mydbname] SET RECOVERY RECMODEL_70BACKCOMP WITH NO_WAIT seems to be to set the recovery model to SIMPLE so basically it has no effect in this instance

How to alter database on the linked server WITHOUT SYSADMIN rights?

My requirement is that user performing alter CANNOT be sysadmin (it can have all other rights but not sysadmin).
I am running a query from local server which should modify a remote one
EXEC ('ALTER DATABASE REMOTEDB MODIFY FILEGROUP ftfg_REMOTEDB NAME=ftfg_REMOTEDB') at [REMOTESERVER]
This query works once I add sysadmin right to the user but without the right, it give the following error:
The server principal "USERWITHOUTSYSADMIN" is not able to access the database "REMOTEDB" under the current security context.
I am on SQL Serve 2008.
Please Help!
After much research: This is not possible:(
Put the EXEC command in a stored procedure and grant execute on the procedure to the user. It won't STOP a sysadmin from executing it, but it will allow others to execute it as well. Be VERY, VERY careful with this!
Can you allow the user to impersonate someone with the appropriate permissions?
EXEC ('ALTER DATABASE REMOTEDB MODIFY FILEGROUP ftfg_REMOTEDB NAME=ftfg_REMOTEDB')
AS USER = 'UserWithAppropriatePermissions'
AT [REMOTESERVER]

Checking sp_send_email permission before executing

In my stored procedure, I send emails with sp_send_email. My stored procedure will be run in different environments; some will have emailing enabled, some won't.
If I run sp_send_email without it being enabled, I (quite rightly) get this error message
SQL Server blocked access to procedure 'dbo.sp_send_dbmail' of component 'Database Mail XPs' because this component is turned off as part of the security configuration for this server.
I want to check whether emailing is enabled first, so I can avoid the error by doing the following:
IF #is_enabled
BEGIN
EXEC sp_send_email ...
END
How do I correctly set #is_enabled?
You can query sys.configurations
IF EXISTS (SELECT *
FROM sys.configurations
WHERE name = 'Database Mail XPs' AND value_in_use = 1)
PRINT 'enabled'
ELSE
PRINT 'no luck'
The downside is that it may not be visible to non-sysadmin users because of "MetaData Visibility"
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Database Mail XPs';
GO
The sp_send_mail falls under the 'Database Mail XPs' umbrella. You application may not have the rights to run sp_configure and RECONFIGURE, so in the end you may be better if you simply try to invoke the sp_send_mail and handle the error.
BOL says:
To send Database mail, users must be a user in the msdb database and a member of the DatabaseMailUserRole database role in the msdb database. To add msdb users or groups to this role use SQL Server Management Studio or execute the following statement for the user or role that needs to send Database Mail.
So, you can give to user the appropriate role:
EXEC msdb.dbo.sp_addrolemember #rolename = 'DatabaseMailUserRole'
,#membername = '<user or role name>'; GO

Resources