August 10, 2015 at 5:14 am
I have a very simply SQLCLR project.
using System;
using System.Data;
using System.Data.SqlTypes;
using System.IO;
using Microsoft.SqlServer.Server;
namespace CmdShell
{
public class CmdShellBridge
{
[SqlProcedure]
public static int processCMD(string fileName, string arguments)
{
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = fileName;
proc.StartInfo.Arguments = arguments;
try
{
proc.Start();
proc.WaitForExit();
}
catch (Exception e)
{
return -1;
}
return 0;
}
};
}
It will be used to replace xp_cmdshell calls in our stored procedures.
I followed all steps from http://blogs.msdn.com/b/dataaccesstechnologies/archive/2011/10/29/deploying-sql-clr-assembly-using-asymmetric-key.aspx, but now I have a problem when I try to execute stored procedures in which I use my new extended procedure (processCMD).
I used this script to create assembly.
USE master
GO
IF NOT EXISTS(select * from sys.asymmetric_keys where name = 'SQLCLRTestKey')
CREATE ASYMMETRIC KEY SQLCLRTestKeyFROM EXECUTABLE FILE = 'C:\Test\CmdShellBridge.dll'
go
CREATE LOGIN SQLCLRTestLogin FROM ASYMMETRIC KEY SQLCLRTestKey
GRANT EXTERNAL ACCESS ASSEMBLY TO SQLCLRTestLogin
GO
USE cssprod
GO
CREATE USER SQLCLRTestLogin FOR LOGIN SQLCLRTestLogin
GO
use cssprod
CREATE ASSEMBLY CmdShellBridge
FROM 'C:\Test\CmdShellBridge.dll'
WITH PERMISSION_SET = EXTERNAL_ACCESS;
And after this somebody grant EXTERNAL ACCESS ASSEMBLY to my account too.
GRANT EXTERNAL ACCESS ASSEMBLY TO myaccount
I execute the stored procedure with my account and the error message was:
Msg 6522, Level 16, State 1, Procedure processCMD, Line 0
A .NET Framework error occurred during execution of user-defined routine or aggregate "processCMD":
System.Security.SecurityException: Request failed.
System.Security.SecurityException:
at CmdShell.CmdShellBridge.processCMD(String fileName, String arguments)
.
What can be the problem in my case ?
August 10, 2015 at 5:43 am
just like xp_cmdshell, the service account that SQL is using is the credentials used for accessing objects outside of SQL server.
if your process was accessing local folders , special folders like [my documents], the root of C:, network folders, other objects, the registry, etc it might not have permissions.
take a look at Administrative Tools>>Services, and see what account the service is running under; would that account be able to do the work your call is doing(ie has access to some network share or something?
,
Lowell
August 10, 2015 at 5:49 am
SQL Servers run under Local System account.
August 10, 2015 at 6:00 am
levaif (8/10/2015)
SQL Servers run under Local System account.
right, so local system does not have domain access to any network shares, for example. it cannot browse to \\machinename\d$\somefolder.
to do that, you must change the account.
what, specifically, is this test call to your process doing? a call to powershell or robocopy, for example?
Lowell
August 10, 2015 at 6:18 am
We have several stored procedures. In these sp's we want to made some IO operations with bcp, osql or other utilities.
Example :
SET @ExecCommand ="SELECT * from ##temp_CH" queryout \\WYVSTSITTS01\backoffice\ExportImport\FIRE\CEGBIROSAG_20150808.txt -c -S WYVSTSITCSS01\CSS_SQL01 -t -r -t; -T -C1250
EXEC @result = dbo.processCMD @@PROCID, 'bcp.exe ', @ExecCommand
August 10, 2015 at 6:31 am
levaif (8/10/2015)
We have several stored procedures. In these sp's we want to made some IO operations with bcp, osql or other utilities.Example :
SET @ExecCommand ="SELECT * from ##temp_CH" queryout \\WYVSTSITTS01\backoffice\ExportImport\FIRE\CEGBIROSAG_20150808.txt -c -S WYVSTSITCSS01\CSS_SQL01 -t -r -t; -T -C1250
EXEC @result = dbo.processCMD @@PROCID, 'bcp.exe ', @ExecCommand
if you were to change the code to write to a local drive (ie c:\Data\CEGBIROSAG_20150808.txt) your bcp would work.
because SQL is running under the local system account, and you are trying to access a server share, you must change the startup account to a domain account. Local system would have access to most local drives, but nothing on the network.
\\WYVSTSITTS01\backoffice\ExportImport\FIRE\CEGBIROSAG_20150808.txt
Lowell
August 10, 2015 at 6:43 am
It's something which is not clear for me.
So, SQL server is running under Local system account, on an terminal server.
I use my domain account to log into the server, and also I can connect to SQL server via SQL Server Manager.
Then I try to execute the stored procedure.
My account has EXTERNAL ACCESS grant to ASSEMBLY.
The problem is, that SQL Server runs under local system account, not under my domain account ?
August 10, 2015 at 6:48 am
levaif (8/10/2015)
It's something which is not clear for me.So, SQL server is running under Local system account, on an terminal server.
I use my domain account to log into the server, and also I can connect to SQL server via SQL Server Manager.
Then I try to execute the stored procedure.
My account has EXTERNAL ACCESS grant to ASSEMBLY.
The problem is, that SQL Server runs under local system account, not under my domain account ?
that is correct.
SQL does not care if you are local administrator, domain administrator or anything when it has to touch objects OUTSIDE of SQL server;
inside sql, in databases and such, it certainly uses your credentials to determine access.
OUTSIDE of SQL server, it is one specific account that is used, and that is the account under which the service runs.
SQL doesn't have a mechanism to pass your credentials to xp_cmdshell or external processes like CLR, so it uses it's own.
this is one of those annoying permissions gotchas you encounter related to SQL.
Lowell
September 9, 2015 at 3:23 am
I'm still not 100 percent clear in this problem.
I verified that SQL Server runs under Local system account.
I publish my assembly with EXTERNAL ACCESS permission set and I tried to run an stored procedure where I use a call using one stored procedure from my assembly. As I expected I still got an error:
Msg 6522, Level 16, State 1, Procedure processReturn, Line 0
A .NET Framework error occurred during execution of user-defined routine or aggregate "processReturn":
System.Security.SecurityException: Request failed.
System.Security.SecurityException:
at CmdShell.CmdShellBridge.processReturn(String fileName, String& ReturnMessage)
When publish the assembly with UNSAFE permission set, the stored procedure runs without any problem, I can access external files, I can read from, and write to it.
Using whoami.exe I found that the user in which name runs the stored procedure was :
nt authority\system
Because I have no experience in security problems, it would be useful for me some an example how can I fix my problem.
We have over than 30 stored procedures in which I have to use my assembly. This procedures has to access many external files for read and write purpose. For these external folders I have to add permissions for a large number of users. I understand that I could use credentials for not to set those permissions for users individually, but I don't know exactly how to do it.
I have to resolve my problem with minimal security issues.
Viewing 9 posts - 1 through 8 (of 8 total)
You must be logged in to reply to this topic. Login to reply