非sysadmin使用者執行xp_cmdshell會有2秒延遲

摘要:非sysadmin使用者執行xp_cmdshell會有2秒延遲

-- 建立proxy account

-- (sysadmin role 會透過SQL service account跟OS溝通

-- 非sysadmin role的user,會透過proxy account跟OS溝通)

Use  Master

GO

EXEC sp_xp_cmdshell_proxy_account  'ADVWKS\OS_User','P@ssw0rd'

 

-- 建立非sysadmin role的user

Use Master

GO

create  login  abc with  password='P@ssw0rd'

GO

create  user  abc   for  login  abc

GO

 

-- grant 執行xp_cmdshell的權限

grant  exec  on  xp_cmdshell  to  abc

GO

 

-- 以有sysadmin role的使用者執行dos commend

set  statistics  time  on

    exec  xp_cmdshell  'cmd /c time /t'

set  statistics  time  off

 

 

-- 以沒有sysadmin role的執行dos commend

set  statistics  time  on 

 exec  as  user='abc'  

    exec  xp_cmdshell  'cmd /c time /t'

revert       

 

 

 

可以發現沒有sysadmin role的使用者執行xp_cmdshell時,會有2秒左右的延遲。其實2秒好像也不是太嚴重,但是當一支stored procedure裡重覆執行xp_cmdshell時,就明顯有「慢」的感覺了…..

 

這個問題查了一個多月,最後在微軟的協助下發現與OS 底層MPR (Multiple Provider Router) 呼叫的Network Provider有關。

 

http://www.symantec.com/business/support/index?page=content&id=TECH168053

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\NetworkProvider\HwOrder]

[原來的機碼順序]

"ProviderOrder"="PDVFSNP,SnacNp,RDPNP,LanmanWorkstation"

 

[修改後的機碼順序]

"ProviderOrder"="SnacNp,RDPNP,LanmanWorkstation,PDVFSNP"

 

因PDVFSNP(PureDisk agent) 的DLL 無法做即時的回應,造成了非sysadmin role的使用者在做LogonUser API 呼叫時都會延遲的問題,所以要把順序調到後面。

http://blogs.technet.com/b/instan/archive/2008/04/03/the-case-of-the-mysterious-2-minute-logon-delay.aspx

 

PS. 這是去年就解決的問題了。只是前幾天server上windows patch,結果不知道哪支patch又把機碼順序改回去……  難道以後每次上patch都要來檢查一下順序嗎…. @@

 

後來跟老師討論這個問題時,發現SQL server可以讀寫registry key 值 :

/**** 讀registry ****/
DECLARE @returnValue NVARCHAR(1000)
EXEC  master.dbo.xp_regread
      @rootkey  = N'HKEY_LOCAL_MACHINE',
      @key       = N'SYSTEM\CurrentControlSet\Control\NetworkProvider\Order',
      @value_name = N'ProviderOrder',
      @value       = @returnValue output
SELECT @returnValue as Value

/**** 修改 registry ****/
EXECUTE master..xp_regwrite
@rootkey  = N'HKEY_LOCAL_MACHINE',
@key      = N'SYSTEM\CurrentControlSet\Control\NetworkProvider\Order',
@value_name = N'ProviderOrder',
@data_type  = 'REG_SZ',
@value = 'RDPNP,SnacNp,LanmanWorkstation,webclient,EmLogon' 

 

若要透過SQL 修改registry key值,則需將regitry key的權限grant給SQL serice account