SQL xp_create_subdir for non-admin - sql-server

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).

Related

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

Executing a stored procedure in SQL Server

I have a stored procedure called testSP in my SQL Server Express database.
I am able to execute it using
exec [db_owner].[testSP]
but if I use exec testSP it doesn't work.
What is the cause of this?
I have other databases which do not exhibit this behavior.
Thanks for your help.
Your user is set up with dbo as it's default schema. That's pretty normal
when you run
exec testSP
it's using your default schema which is dbo, so it is running this:
exec [dbo].[testSP]
which doesn't exist.
When you run
exec [db_owner].[testSP]
it find and runs that stored procedure
I don't know the background but I guess someone has incorrectly/accidentally created and used a schema called db_owner
In all the db's that work, I guess the objects are in the dbo schema or your user is set up to use the correct schema. Go look in the object browser and compare
If you want to move the stored procedure into the dbo schema run this:
ALTER SCHEMA dbo TRANSFER [db_owner].[testSP];
If you want to change your users default schema to db_owner run this:
ALTER USER [youruser] WITH DEFAULT_SCHEMA = db_owner;
I reckon the db_owner schema is an accident though.

xp_cmdshell access in 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.

SQL Server : login success but "The database [dbName] is not accessible. (ObjectExplorer)"

I am using windows 8.1 and SQL Server 2012.
I was using an OS account "Manoj" for accessing SQL SERVER with windows authentication.
Recently I have deleted my user account "Manoj" of OS and created a new account with same name "Manoj".
But the system took the new account as "Manoj_2". This change keeps me out from accessing the old databases, I have created.
It says that
The database [dbName] is not accessible. (ObjectExplorer)
whenever I try to access any of the previous DBs I have created.
I used to create new login in SQL Server for "Manoj_2", with default DB as "master". But still the problem persists.
I cannot able to detach the DBs. I am unable to expand the DBs.
Note: In OS, I have admin rights for the "Manoj" account.
Please anybody tell me, what to do? either with OS or with SQL Server
For this situation you have to connect to database in Single-User mode.
Starting SQL Server in single-user mode enables any member of the computer's local Administrators group to connect to the instance of SQL Server as a member of the sysadmin fixed server role.
Here you can find step-by-step instruction to do this.
In short you must start the sqlserver instance with parameters -m, after start Sql Server Management Studio with windows authentication.
Now you are a sysadmin, assign the sysadmin role to your user, exit and remove the -m parameter and restart sql server.
The problem is that the user in the database is an "orphan". This means that there is no login id or password associated with the user. This is true even if there is a login id that matches the user, since there is a GUID (called a SID in Microsoft-speak) that has to match as well.
This used to be a pain to fix, but currently (SQL Server 2000, SP3) there is a stored procedure that does the heavy lifting.
All of these instructions should be done as a database admin, with the restored database selected.
First, make sure that this is the problem. This will lists the orphaned users:
EXEC sp_change_users_login 'Report'
If you already have a login id and password for this user, fix it by doing:
EXEC sp_change_users_login 'Auto_Fix', 'user'
If you want to create a new login id and password for this user, fix it by doing:
EXEC sp_change_users_login 'Auto_Fix', 'user', 'login', 'password'
this text was obtained at http://www.fileformat.info/tip/microsoft/sql_orphan_user.htm in Dez-13-2017
Really stupid solution but I'll add it here in case anyone gets here from a Google search.
I'd just restarted the SQL service and was getting this error and in my case, just waiting 10 minutes was enough and it was fine again. Seems this is the error you get when it is just starting up.
If you are using Sql Management Studio, just start it as Administrator.
Right click->Run as Administrator
This is what led me to this issue and how I fixed it:
Restored my database to another SQL server instance from a .bak file, which included a preexisting user.
Tried to access the restored database from my app as usual using the same connection string but updated server instance.
Received error.
Deleted user as the DBowner, then readded with exact same credentials, mappings, login, etc.
Was able to login as the user after readding the user after the restore.
This is caused when the user's default database is set to a database they don't have permissions or its offline.
Just try to re add the user.Pleae have a look here too.
I had twoo users: one that had the sysadmin role, the other one (the problematic one) didn't.
So I logged in with the other user(you can create a new one) and checked the ckeck box 'sysadmin' from: Security --> Logins --> Right ckick on your SQL user name --> Properties --> Server Roles --> make sure that the 'sysadmin' checkbox has the check mark.
Press OK and try connecting with the newly checked user.
In my case it worked when I had opened SQL Server Management Studio with Administrator credentials and I right-clicked on the database and select "Go online" or something like this.
Please try this script.. What this script does is it looks at the active sessions of the database and kills them so you can bring the database back online.
CREATE TABLE #temp_sp_who2
(
SPID INT,
Status VARCHAR(1000) NULL,
Login SYSNAME NULL,
HostName SYSNAME NULL,
BlkBy SYSNAME NULL,
DBName SYSNAME NULL,
Command VARCHAR(1000) NULL,
CPUTime INT NULL,
DiskIO INT NULL,
LastBatch VARCHAR(1000) NULL,
ProgramName VARCHAR(1000) NULL,
SPID2 INT
, rEQUESTID INT NULL --comment out for SQL 2000 databases
)
INSERT INTO #temp_sp_who2
EXEC sp_who2
declare #kill nvarchar(max)= ''
SELECT #kill = #kill+ 'kill '+convert(varchar,spid) +';'
FROM #temp_sp_who2
WHERE DBName = 'databasename'
exec sp_executesql #kill
ALTER DATABASE DATABASENAME SET ONLINE WITH IMMEDIATE ROLLBACK
In my case, I simply had to start the application with "Run as administrator" in order to access anything. Otherwise I'd get the error you mentioned.
Get this error in this steps:
Run "Get offline".
"Get offline" was running too long, so i closed this window.
Then i got this error.
Steps to fix:
Go to "Activity monitor" and delete all connections to this db. Then DB became really offline and all is ok.
This fixed it for me:
Use [dbName]
GO
EXEC sp_change_users_login 'Auto_Fix','Manoj', null, 'Manojspassword'
GO
In my case, restarting SQL Server Service was enough to resolve the issue.
I experienced a similar problem after running a few jobs of bulk insert through a Python script on a separate machine and a separate user from the one I am logging in to SSMS.
It appears that if the Python kernel (or possibly any other connection) is interrupted in the middle of a bulk insert job without properly 'cleaning up' the mess, some sort of hanging related to user credentials and locks may happen on the SQL Server side. Neither restarting the service nor the whole machine worked for me.
The solution in my case was to take the DB offline and online.
In the SQL Server Management Studio, that is a right click on DB > tasks > take offline and then right click on DB > tasks > bring online.
My issue got resolved by restarting the MS SQL server service, simple.
I had a similar problem, for me I had to create a new user with name that I needed, in your case you should create some like this:
USE [master]
GO
/****** Object: Login [Manoj_2] Script Date: 9/5/2019 12:16:14 PM ******/
CREATE LOGIN [Manoj_2] FROM WINDOWS WITH DEFAULT_DATABASE=[master],
DEFAULT_LANGUAGE=[us_english]
GO
ALTER SERVER ROLE [sysadmin] ADD MEMBER [Manoj_2]
GO
Execute the following sentence:
EXEC rdsadmin.dbo.rds_set_database_online dbname
I performed the below steps and it worked for me:
1) connect to SQL Server->Security->logins->search for the particular user->Properties->server Roles-> enable "sys admin" check box
I just restarted my SQL Server (MSSQLSERVER) with which my SQL Server Agent (MSSQLSERVER) also got restarted. Now am able to access the SQL SERVER 2008 R2 database instance through SSMS with my login.
Issue: The database [dbName] is not accessible. (ObjectExplorer) got the error when expanding the database.
Solution: Deattach the database > Drop Option
Attach the database again with the mdf file under the mssql data folder
Go to
Security >> Logins >>
Right click to the user >> Properties >>
On the left navigation move to >> User Mapping >> Check the database and in the "Database role membership for: <>" check "db_owner" for user that you are experience the issue.
PROBLEM SOLVED...

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]

Resources