xp_cmdshell user is not listing newly created user "CustomUserX" - sql-server

I am trying to execute a powershell script from within an AFTER UPDATE SQL TRIGGER. From a component perspective the UPDATE and powershell cmd appear to function properly. However, the TRIGGER script as a whole fails at the point of executing the powershell script.
I recently discovered that to execute xp_cmdshell, it needs a user proxied to a windows account. Makes sense as anything executed outside of the SQL space needs a windows account to do so.
I then proceeded (after some research) to create the proxy user using the steps as follows
/* Enable xp_cmdshell */
EXEC sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE
GO
/* Target DB */
USE master
/* Created a custom user with pwd */
CREATE LOGIN CustomUserX WITH PASSWORD = 'strong_password'
/* Created a user from the login */
CREATE USER CustomUserX FROM LOGIN CustomUserX
/* Granted execute for CustomUserX */
GRANT EXECUTE ON xp_cmdshell TO CustomUserX
/* Created proxy user using local machine account and pwd */
EXEC sp_xp_cmdshell_proxy_account 'LOCALMACHINENAME\WinsAccount','pwd'
/* Execute as login CustomUserX */
EXECUTE AS login = 'CustomUserX'
/* Ran simply listing of contents of drive E:/ */
EXEC xp_cmdshell 'DIR E:\*.*'
REVERT
When I tried to execute the script from with the trigger, the trigger failed with.
SQL Server Database Error: The server principal "CustomUserX" is not able to access the database "AnotherDB1" under the current security context.
I ran exec ex_cmdshell 'echo %username% only to discover the "CustomUserX" account is not listed (only SQL$.., and NULL).
The above proxy scripts were executed for the master table as suggested. Would I need to do the same thing under the db instance ("AnotherDB1") as well?

you need to grant the user to use the database
https://learn.microsoft.com/en-us/sql/t-sql/statements/grant-database-permissions-transact-sql

Related

SQL proxy account credentials Error code - 0, Status code - 0

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?

DbCreator role can restore a database but not then access it in MSSQL Server

I am working on a tool which is having restore command to restore MSSQL databases. Till now tool was restoring the databases with sysadmin privileges. However, as per new requirement I want to minimize the access privilege for this command i.e restore should be done with dbcreator role instead of sysadmin. With dbcreator I am able to restore the databases, however this command also does some post-operation on the restored databases i.e. updating some value in table. Post-operation is failing with lack of access, since db_owner is required for this user. How to grant db_owner to current user(dbcreator) on the restored databases who is not sysadmin at run time so that my restore command succeeds along with post-operation.
One way to follow security principles of least privilege and role-based access controls is to encapsulate the T-SQL commands that require elevated permissions in a stored procedure. One can then sign the proc with a certificate to confer additional permissions without granting those permissions directly to users. Only execute permissions on the signed stored procedure are required and authorized users are limited to the encapsulated functionality.
Below is an example script to create a stored procedure and DBRestore role using this technique. If your actual RESTORE command contains options that can't be parameterized (e.g. WITH MOVE file locations), you'll need to use dynamic SQL in the proc and take special care to ensure the values validated and/or obtained from a trusted source (e.g. configuration table instead of ad-hoc parameter value).
USE master
GO
--create certificate in master database
CREATE CERTIFICATE sysadmin_cert_login_cert
ENCRYPTION BY PASSWORD = '<cert-password>'
WITH SUBJECT = 'For sysadmin privileges';
GO
--create login from certificate
CREATE LOGIN sysadmin_cert_login FROM CERTIFICATE sysadmin_cert_login_cert;
--confer sysadmin permissions to certificate login
ALTER SERVER ROLE sysadmin
ADD MEMBER sysadmin_cert_login;
GO
--create role for restore user(s)
CREATE ROLE DBRestoreRole;
GO
--create restore proc in master database
CREATE PROC dbo.usp_RestoreDatabase
#DatabaseName sysname
, #BackupFilePath varchar(255)
AS
BEGIN TRY
RESTORE DATABASE #DatabaseName FROM DISK=#BackupFilePath WITH REPLACE;
--after restore, set database owner as desired
ALTER AUTHORIZATION ON DATABASE::RestoreTest TO sa;
--execute post restore DML
UPDATE RestoreTest.dbo.SomeTable
SET SomeColumn = 1;
END TRY
BEGIN CATCH
THROW;
END CATCH;
GO
--grant execute permission to DBRestoreRole
GRANT EXECUTE ON dbo.usp_RestoreDatabase TO DBRestoreRole;
--sign proc with sysadmin certificate
ADD SIGNATURE TO dbo.usp_RestoreDatabase BY CERTIFICATE sysadmin_cert_login_cert WITH PASSWORD='<cert-password>';
--optionally, remove ephemoral private key after signing
ALTER CERTIFICATE sysadmin_cert_login_cert REMOVE PRIVATE KEY;
GO
--create example DBRestoreRole login/user
CREATE LOGIN RestoreTestLogin WITH PASSWORD = '<login-password>';
CREATE USER RestoreTestLogin;
ALTER ROLE DBRestoreRole
ADD MEMBER RestoreTestLogin;
GO
--test execution
EXECUTE AS LOGIN = 'RestoreTestLogin';
GO
EXEC dbo.usp_RestoreDatabase
#DatabaseName = N'RestoreExample'
, #BackupFilePath = 'E:\BackupFiles\RestoreExample.bak';
GO
REVERT;
GO

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 Exception: No Process Is on the Other End of the Pipe

I can not access my sql server connection from c# code. I get this error:
Sql Exception: No Process Is on the Other End of the Pipe
thats the connection string in my app.config:
<add name="DefaultConnection" providerName="System.Data.SqlClient" connectionString="Data Source=BELLA\SQLEXPRESS;Initial Catalog=TLP;User Id=pascal;Password=test;Pooling=False"/>
When I use windows authentication: Integrated Security=True;
Then I can connect to the database.
BUT I can NOT use windows authentication because the opening of the sql connection is done from within a windows service which is run as LocalSystem. When I do this I get this error:
Login failed. Login failed for user 'NT AUTHORITY\SYSTEM'
Its the first time I create a login + user in sql management studio so I am nearly sure I did something wrong and its my fault.
This is what I did:
1) Create a new login in the server`s security folder with sql authentication user:pascal and password:test.
2) Went to my database and create a new user in the security folder with user: pascal and login: pascal and schema: dbo
3) Did I forget something?
Solutions from other people:
1) I have also tried this link but no luck my Sql Select on the suspect_pages table is empty.
Error: No process is on the other end of the pipe
2) My Sql Server network configuration has ENABLED on the tcp/ip, names pipes and shared memory settings.
3) SQL Server 2008 can't login with newly created user
Number 1 to 3 did not help at all.
All this is done on my local machine. No network is here.
Did you enable Shared Memory and TCP/IP providers in SQL configuration?
If not, try opening the SQL Server Configuration Manager utility and enabling Shared Memory and TCP/IP. The order that works for me is Shared Memory (1) and TCP/IP (2) for both server and client.
Also, make sure you are creating both a SQL LOGIN and DATABASE USER for PASCAL with correct rights.
Check out my blog article on creating logins. http://craftydba.com/?p=656
The snippet below will blow away and recreate your login/user with the correct default database, default schema and read/write privileges.
-- Which database to use.
USE [TLP]
GO
-- Delete existing user.
IF EXISTS (SELECT * FROM sys.database_principals WHERE name = N'pascal')
DROP USER [pascal]
GO
-- Which database to use.
USE [master]
GO
-- Delete existing login.
IF EXISTS (SELECT * FROM sys.server_principals WHERE name = N'pascal')
DROP LOGIN [pascal]
GO
-- Add new login.
CREATE LOGIN [pascal] WITH PASSWORD=N'test', DEFAULT_DATABASE=[TLP]
GO
-- Which database to use.
USE [TLP]
GO
-- Add new user.
CREATE USER [pascal] FOR LOGIN [pascal] WITH DEFAULT_SCHEMA=[dbo]
GO
-- Add to database read / write roles
EXEC sp_addrolemember 'db_datareader', 'pascal'
EXEC sp_addrolemember 'db_datawriter', 'pascal'
GO
-- Add to database owner role?
-- Only give out if application needs a high level of privileges.
-- EXEC sp_addrolemember 'db_owner', 'pascal'
-- GO
Server level protocols.
Client level protocols.
I never choose NETBIOS since it is a non-routable protocol.
If you are still having issues, please post a screen shot and more details.
Probably an unusual scenario but I just got this exception and tracked it down to an invalid database name in the Initial Catalogue value of the connection string.

Access denied for enabled xp_cmdshell for the admin user

I'm using xp_cmdshell within a database trigger to launch a exe file.
xp_cmdshell is enabled(it can execute simple cmd command like 'echo'). But when I try to launch the exe through xp_cmdshell, the access is denied.
I am the database administrator. And I can launch the exe through cmd directly. Anyone know why I get denied and how to fix it?
Use xp_cmdshell to run "whoami", then check effective permissions for the stated user on the exe and any resources it accesses.
Odds are that an account like localsystem is being used to run processes via xp_cmdshell.
EXEC xp_cmdshell 'whoami'
Likely insufficient NTFS permissions. Make sure the 'user account' that the SQL Server is running as, has permission (Read+Execute) to the *.EXE (and any dependent files)
Not sure, but I believe that the trigger is run by the user running the SQL command that "triggered" the trigger.
Is the user issuing the SQL command a Windows user or a SQL user ? If it's a SQL user, you need to set an "SQL Proxy". The SQL Proxy is used to tell SQL which Windows user will be used to access the file system.
Hope this helps,
Yves
I was getting ACCESS DENIED when trying to run BCP and then COPY.
What I found is that xp_cmdshell starts in c:\windows\system32
I modified my CMD file to change to my working folder
L:
cd L:\myworkingfolder
This solved my problem, Event though my sqlagent was a local administrator and I had full pathed my copy command.
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:
create new role:
use master
CREATE ROLE [CmdShell_Executor] AUTHORIZATION [dbo]
GRANT EXEC ON xp_cmdshell TO [CmdShell_Executor]
add users in master database: Security --> Users. Membership checks only [CmdShell_Executor] that is just created
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 to type in the password, execute the one line code, then delete the password. All in my pc.
You can also get Access is denied. when you don't specify path to executable correctly. Note if your path contains spaces, you need to enclose the executable into double quotes:
EXEC xp_cmdshell '"D:\My path\With spaces\runme.exe"'
I had the same problem and I solved it like this:
Open SQL Server Configuration Manager
Select your instance and right-click -> properties
Select Log on tab
And select authorized account

Resources