ÚVOD
Společnost Microsoft vydala informační zpravodaj zabezpečení k chybě zabezpečení serveru Microsoft SQL Server, která by mohla umožnit vzdálené spuštění kódu. Tento informační zpravodaj zabezpečení obsahuje dodatečné informace týkající se zabezpečení. Chcete-li zobrazit celý obsah tohoto zpravodaje, navštivte následující web společnosti Microsoft:
http://www.microsoft.com/technet/security/advisory/961040.mspxTento článek obsahuje skript jazyka Visual Basic, který lze použít jako alternativní řešení pro všechny spuštěné instance serveru SQL Server v místním počítači.
UKÁZKA SKRIPTU JAZYKA VISUAL BASIC, KTERÝ LZE POUŽÍT JAKO ALTERNATIVNÍ ŘEŠENÍ
Tento skript jazyka Visual Basic lze použít u role Public k odepření oprávnění pro spouštění rozšířené uložené procedury sp_replwritetovarbin ve všech ovlivněných verzích serveru SQL Server, které jsou spuštěny v místním počítači.
Společnost Microsoft poskytuje ukázky programování pouze pro ilustraci, bez žádné záruky výslovně uvedené nebo odvozené, včetně, bez omezení, odvozených záruk vztahujících se k obchodovatelnosti nebo vhodnosti pro určitý účel. Tento článek předpokládá, že uživatel je obeznámen s programovacím jazykem, který je předmětem ukázky, a s nástroji použitými pro vytvoření a ladění skriptu. Pracovníci technické podpory společnosti Microsoft mohou vysvětlit funkce určité procedury, nemohou však následující příklady rozšířit o další funkce nebo vytvářet procedury podle konkrétních požadavků uživatele. Zkopírujte tento kód do textového souboru, uložte jej s příponou souboru VBS a pak soubor skriptu spusťte pomocí programu CScript.exe. Skript projde všechny spuštěné instance serveru SQL Server v místním počítači a pro ovlivněné verze použije alternativní řešení. Aby bylo možné alternativní řešení použít, je třeba být pro každou instanci serveru SQL Server členem role správce systému. Pokud nemáte účet systému Windows, který by byl členem role správce systému pro všechny ovlivněné servery se spuštěnými servery SQL Server, může být nutné spustit tento skript z více účtů. Pokud v systémech Windows Server 2008 a Windows Vista používáte účet správce systému Windows, který je členem role správce systému, je třeba spustit tento skript v příkazovém řádku s vyššími oprávněními.'*************************************************************************************
'Popis: Tento skript prochází všechny spuštěné instance serveru SQL Server ' a odpírá roli Public oprávnění pro spuštění procedury sp_replwritetovarbin pro všechny ' ovlivněné verze. ' TENTO SKRIPT SLOUŽÍ JAKO ALTERNATIVNÍ ŘEŠENÍ A NEMĚL BY BÝT POUŽÍVÁN V PŘÍPADĚ, ŽE ' BYLA VYDÁNA A INSTALOVÁNA AKTUALIZACE ZABEZPEČENÍ. '************************************************************************************* OPTION EXPLICIT ON ERROR RESUME NEXT ' Konstanty CONST EXIT_SUCCESS = 0 CONST EXIT_FAILURE = 1 CONST EXIT_NOINSTANCES = -1 CONST DEFAULTNAMESPACE = "root\default" CONST STDREGPROV = "stdregprov" CONST HKEY_LOCAL_MACHINE = &H80000002 CONST REG_MULTI_SZ = 7 CONST REG_SZ = 1 CONST adCmdText = 1 Call VBMain() Function VBMain() Err.Clear ON ERROR RESUME NEXT Dim sInstances(), strInstance, i, TotalCount VBMain = EXIT_SUCCESS If GetInstances(sInstances, TotalCount) = FALSE Then WScript.Quit EXIT_FAILURE End If If IsEmptyNull(sInstances) Then WScript.Echo "INFORMACE: Nejsou přítomny žádné instance." VBMain = EXIT_NOINSTANCES Exit Function End If For i = 0 To TotalCount-1 strInstance = sInstances(i,0) GetFullInstance strInstance, sInstances(i,1) If ApplyFix(sInstances(i,0), strInstance) = FALSE Then wscript.echo "CHYBA: Alternativní řešení nelze použít pro instanci " + sInstances(i,0) + "." + vbCRLF VBMain = EXIT_FAILURE End If Next WScript.Echo "INFORMACE: Byly zpracovány všechny spuštěné instance SQL." End Function Function GetInstances(ByRef sInstances, ByRef TotalCount) Err.Clear ON ERROR RESUME NEXT Dim sInstances1, sInstances2, i Dim instCount1, instCount2 GetInstances = FALSE If NOT GetRegValue ("", HKEY_LOCAL_MACHINE, "Software\Microsoft\Microsoft SQL Server", "InstalledInstances", sInstances1, REG_MULTI_SZ, TRUE) Then WScript.Echo "CHYBA: Čtení instancí SQL v tomto počítači se nezdařilo." Exit Function End If sInstances2 = NULL If IsOs64Bit() = TRUE Then If NOT GetRegValue ("", HKEY_LOCAL_MACHINE, "Software\Microsoft\Microsoft SQL Server", "InstalledInstances", sInstances2, REG_MULTI_SZ, FALSE) Then WScript.Echo "CHYBA: Čtení instancí SQL v tomto počítači se nezdařilo." Exit Function End If End If If IsEmptyNull(sInstances1) AND IsEmptyNull(sInstances2) Then WScript.Echo "INFORMACE: Nejsou přítomny žádné instance." WScript.Quit EXIT_SUCCESS End If instCount1 = 0 instCount2 = 0 TotalCount = 0 If IsEmptyNull(sInstances1) = FALSE Then instCount1 = UBound(sInstances1) + 1 TotalCount = instCount1 End If If IsEmptyNull(sInstances2) = FALSE Then instCount2 = UBound(sInstances2) + 1 TotalCount = TotalCount + instCount2 End If ReDim PRESERVE sInstances(TotalCount,1) if instCount1 > 0 Then For i = 0 To UBound(sInstances1) sInstances(i,0) = sInstances1(i) sInstances(i,1) = True Next End If If instCount2 >0 Then For i = 0 To UBound(sInstances2) sInstances(i+instCount1,0) = sInstances2(i) sInstances(i+instCount1,1) = FALSE Next End If GetInstances = TRUE End Function Function ApplyFix(ByVal strInstance, ByVal strServerName) Err.Clear ON ERROR RESUME NEXT Dim objConn, objCmd, objCmd1, objRS, objRS1 Dim strCommand, strConn Dim strBuildVersion, strProductLevel, bApplyFix ' Inicializace návratové hodnoty ApplyFix = FALSE strConn = "Provider=sqloledb;Initial Catalog=master;Integrated Security=SSPI;Data Source=" + strServerName + ";" ' Kvůli zkrácení kódu je kontrola chyb záměrně vynechána Set objConn = CreateObject("ADODB.Connection") Set objCmd = CreateObject("ADODB.Command") Set objCmd1 = CreateObject("ADODB.Command") ' Otevření připojení k hlavní databázi objConn.Open strConn If ErrorOccurred("Chyba: Nelze se připojit k instanci " + strInstance) Then Set objConn = Nothing Exit Function End If ' Ověření verze před použitím opravy strCommand = "select SERVERPROPERTY('ProductVersion') as version, SERVERPROPERTY('productlevel') as productlevel" objCmd.ActiveConnection = objConn objCmd.CommandType = adCmdText objCmd.CommandText = strCommand Set objRS = objCmd.Execute() If ErrorOccurred("CHYBA: Nelze provést příkaz """ + strCommand + """ v instanci " + strInstance) = TRUE Then objConn.Close() Set objConn = Nothing ApplyFix = FALSE Exit Function End If strBuildVersion = objRS("version") strProductLevel = UCase(objRS("productlevel")) bApplyFix = FALSE ' Použití alternativního řešení pouze pro verze SQL 2000 a SQL 2005 (RTM, SP1 a SP2) If (CInt(Mid(strBuildVersion,1,1)) = 8) Then bApplyFix = TRUE ElseIf CInt(Mid(strBuildVersion,1,1)) = 9 AND (StrComp(strProductLevel,"RTM") = 0 OR StrComp(strProductLevel,"SP1") = 0 OR StrComp(strProductLevel,"SP2") = 0) Then bApplyFix = TRUE End If If bApplyFix = TRUE Then strCommand = "deny execute on sp_replwritetovarbin to public" objCmd1.ActiveConnection = objConn objCmd1.CommandType = adCmdText objCmd1.CommandText = strCommand Set objRS1 = objCmd1.Execute() If ErrorOccurred("CHYBA: Nelze provést příkaz """ + strCommand + """ v instanci " + strInstance) = FALSE Then WScript.Echo "INFORMACE: Alternativní řešení bylo úspěšně použito pro instanci " + strInstance + " (" + strBuildVersion + ")." + vbCRLF ApplyFix = TRUE End If Else WScript.Echo "INFORMACE: Shromažďování informací pro instanci " + strInstance + " (" + strBuildVersion + ") bylo vynecháno, protože tato instance není chybou ovlivněna." + vbCRLF ApplyFix = TRUE End If objConn.Close() Set objConn = Nothing Set objCmd = Nothing Set objCmd1 = Nothing Set objRS = Nothing Set objRS1 = Nothing End Function Private Function GetRegValue (ByVal strMachineName, ByVal hMainKey, ByVal strPath, ByVal strValueName, ByRef strValue, ByVal iValueType, ByVal b32bit) Err.Clear ON ERROR RESUME NEXT Dim objLocator, objServices, objRegistry, objCtx Dim sMultiStrings, lRc GetRegValue = TRUE 'Připojení k rozhraní WMI a získání objektu třídy STDREGPROV Set objCtx = CreateObject("WbemScripting.SWbemNamedValueSet") If b32bit = TRUE Then objCtx.Add "__ProviderArchitecture", 32 Else objCtx.Add "__ProviderArchitecture", 64 End If objCtx.Add "__RequiredArchitecture", TRUE set objLocator = createobject("wbemscripting.swbemlocator") set objServices = objLocator.connectserver(strMachineName,DEFAULTNAMESPACE, "", "",,,,objCtx) set objRegistry = objServices.get(STDREGPROV) If ErrorOccurred("CHYBA: Nelze se připojit k oboru názvů WMI " + DEFAULTNAMESPACE) Then GetRegValue = FALSE Exit Function End If lRc = 0 Select Case iValueType ' Předmět zájmu: pouze REG_MULTI_SZ Case REG_MULTI_SZ strValue = "" lRC = objRegistry.GetMultiStringValue(hMainKey, strPath, strValueName, sMultiStrings) strValue = sMultiStrings Case REG_SZ strValue = "" lRC = objRegistry.GetStringValue(hMainKey, strPath, strValueName, strValue) Case Else GetRegValue = FALSE End Select If lRc = 2 Or lRc = 3 Then GetRegValue = TRUE strValue = "" ElseIf Err.Number OR lRc <> 0 Then GetRegValue = FALSE End If Set objLocator = Nothing Set objServices = Nothing Set objRegistry = Nothing End Function Function IsEmptyNull(sCheck) IsEmptyNull = FALSE If IsObject(sCheck) Then Exit Function If IsArray(sCheck) Then Exit Function If VarType(sCheck) = vbEmpty Then IsEmptyNull = TRUE : Exit Function If VarType(sCheck) = vbNull Then IsEmptyNull = TRUE : Exit Function If sCheck = "" Then IsEmptyNull = TRUE End Function Private Function ErrorOccurred (ByVal strIn) If Err.Number <> 0 Then WScript.Echo strIn WScript.Echo "CHYBA: 0x" & Err.Number & " - " & Err.Description Err.Clear ErrorOccurred = TRUE Else ErrorOccurred = FALSE End If End Function Function IsOs64Bit() Err.Clear ON ERROR RESUME NEXT Dim objProc Set objProc = GetObject("winmgmts:root\cimv2:Win32_Processor='cpu0'") If objProc.Architecture = 0 Then IsOs64Bit = FALSE Else IsOs64Bit = TRUE End If End Function Function GetFullInstance (ByRef strInstanceName, ByVal b32bit) Err.Clear ON ERROR RESUME NEXT Dim objServices, objClusters, objCluster Dim strMacName, isEmpty Dim strKey, strInstID GetFullInstance = TRUE If strComp(UCase(strInstanceName), "MICROSOFT##SSEE", 1) = 0 Then strInstanceName = "np:\\.\pipe\mssql$microsoft##ssee\sql\query" Exit Function End if strMacName = "" Set objServices = GetObject("winmgmts:root\cimv2") ' Služba Query Cluster Set objClusters = objServices.ExecQuery ("select * from win32_service where Name='ClusSvc' AND Started = TRUE") isEmpty = TRUE If Err.Number = 0 Then For each objCluster in objClusters isEmpty = FALSE Next End If Set objServices = Nothing Set objClusters = Nothing If isEmpty = TRUE Then strInstanceName = BuildInstanceName (".", strInstanceName) Exit Function End If ' Dosažení tohoto bodu znamená, že počítač je v uzlu clusteru. ' Dotaz na hodnotu registru nyní určí, zda instance SQL je v clusteru nebo ne. ' V případě SQL 2000 bude v dotazu použita následující hodnota ' HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\<název_instance>\Cluster ' ClusterName strKey = "SOFTWARE\Microsoft\Microsoft SQL Server\" + strInstanceName + "\Cluster" GetRegValue "", HKEY_LOCAL_MACHINE, strKey, "ClusterName", strMacName, REG_SZ, b32bit If StrComp(strMacName, "") <> 0 Then strInstanceName = BuildInstanceName (strMacName, strInstanceName) Exit Function End If strKey = "SOFTWARE\Microsoft\" + strInstanceName + "\Cluster" GetRegValue "", HKEY_LOCAL_MACHINE, strKey, "ClusterName", strMacName, REG_SZ, b32bit If StrComp(strMacName, "") <> 0 Then strInstanceName = BuildInstanceName (strMacName, strInstanceName) Exit Function End If ' Nyní vyzkoušíme dotaz na hodnotu registru pro instance 2005/2008 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL ' RegValue = InstanceName strInstID = "" strKey = "SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL" GetRegValue "", HKEY_LOCAL_MACHINE, strKey, strInstanceName, strInstID, REG_SZ, b32bit If StrComp(strInstID, "") = 0 Then ' Pokud tento klíč neexistuje, zpět jako místní instance SQL 2000 strInstanceName = BuildInstanceName (".", strInstanceName) Exit Function End If strKey = "SOFTWARE\Microsoft\Microsoft SQL Server\" + strInstID + "\Cluster" GetRegValue "", HKEY_LOCAL_MACHINE, strKey, "ClusterName", strMacName, REG_SZ, b32bit If StrComp(strMacName, "") = 0 Then strMacName = "." End If strInstanceName = BuildInstanceName (strMacName, strInstanceName) End Function Function BuildInstanceName (ByVal strMachineName, ByVal strInstanceName) Dim strPrefix strPrefix = "" If StrComp(strMachineName, ".") = 0 Then strPrefix = "lpc:" End If If strComp(UCase(strInstanceName), "MSSQLSERVER", 1) = 0 Then BuildInstanceName = strPrefix + strMachineName Else BuildInstanceName = strPrefix + strMachineName + "\" + strInstanceName End if End Function
Další informace o programu CScript.exe naleznete na následujícím webu společnosti Microsoft:
http://technet.microsoft.com/en-us/library/bb490887.aspxPoznámka: Tento skript se nedoporučuje používat v případě, že byla vydána a instalována aktualizace zabezpečení.
ZNÁMÉ PROBLÉMY, KE KTERÝM MŮŽE DOJÍT PŘI SPUŠTĚNÍ TOHOTO SKRIPTU
Problém 1:
Při spuštění skriptu se zobrazí následující chybová zpráva:
CHYBA: Nelze provést příkaz "deny execute on sp_replwritetovarbin to public" v instanci <název_instance>
CHYBA: 0x-2147217900 - Nebyl nalezen objekt 'sp_replwritetovarbin', protože neexistuje nebo nemáte oprávnění pro přístup. CHYBA: Alternativní řešení nelze použít pro instanci <název_instance>.Příčina 1:
Tuto chybovou zprávu obdržíte, pokud nemáte oprávnění vyžadovaná k provedení změny. Tato chybová zpráva říká, že bylo možné se úspěšně přihlásit k instanci "<název_instance>."
Tato chybová zpráva se obvykle zobrazí v produktu SQL Server Express, ve kterém má skupina „Built-In\Users“ podle výchozího nastavení možnost se přihlásit k databázi. Tato skupina ale není členem role správce systému. Tato chybová zpráva se může také zobrazit, pokud jste odstranili proceduru sp_replwritetovarbin. To bylo doporučeno ve zprávě jiného výrobce. My odstranění této uložené procedury nedoporučujeme. Místo toho doporučujeme použití tohoto řešení.Řešení 1:
Zkontrolujte, že účet použitý k připojení je členem role správce systému pro příslušnou instanci databáze. Pokud účet členem není, buď jej přidejte k roli správce systému, nebo použijte jiný uživatelský účet. V produktu SQL Server 2005 a dřívějších verzích je skupina „Built-in\Administrators“ členem role správce systému standardně. Spouštíte-li tento skript v systému Windows Vista nebo Windows Server 2008, zkontrolujte, že jej spouštíte v příkazovém řádku s vyššími oprávněními.
Problém 2:
Spouštíte-li skript na serveru SQL Server 2005, zobrazí se následující chybová zpráva:
Chyba: Nelze se připojit k instanci <název_instance>
CHYBA: 0x-2147217843 - Přihlášení uživatele '<uživatel>' se nezdařilo. CHYBA: Alternativní řešení nelze použít pro instanci <název_instance>.Příčina 2:
Tato chybová zpráva se zobrazí, pokud se nelze připojit k instanci <název_instance>, přestože tato instance existuje.
Tato chybová zpráva se obvykle zobrazí při připojení k instanci interní databáze systému Windows nebo databáze Microsoft SQL Server 2000 Desktop Edition (Windows). Oprávnění přihlásit se k těmto databázím obvykle nemají žádné uživatelské účty.Řešení 2:
Zkontrolujte, že účet použitý ke spuštění skriptu a přihlášení k databázi je členem role správce systému.
Nedoporučuje se přidávat do interní databáze systému Windows či databáze Microsoft SQL Server 2000 Desktop Edition (Windows) jednotlivé uživatele. Pokud to provedete, přidaní uživatelé mohou bránit standardní činnosti těchto databází. Proto v tomto případě zajistěte, že se připojujete pomocí účtu, který je členem role správce systému. V produktu SQL Server 2005 a dřívějších verzích je skupina „Built-in\Administrators“ členem role správce systému standardně. Spouštíte-li tento skript v systému Windows Vista nebo Windows Server 2008, zkontrolujte, že jej spouštíte v příkazovém řádku s vyššími oprávněními.Problém 3:
Můžete si všimnout instance databáze s názvem MICROSOFT##SSEE. Tuto databázi jste však neinstalovali.
Příčina 3:
Tato databáze je interní databází systému Windows, také nazývaná „SQL Server Embedded Edition“, případně „Microsoft SQL Server 2000 Desktop Edition (Windows)“. Instaluje se s některými produkty společnosti Microsoft, například se službou SharePoint Services.
Řešení 3:
Skript alternativního řešení je navržen tak, aby fungoval s interní databází systému Windows. Není vyžadována žádná akce.
Některé aplikace při své odinstalaci neodeberou interní databázi systému Windows. Další informace o odebrání interní databáze systému Windows naleznete v následujícím článku znalostní báze Microsoft Knowledge Base:920277 Interní databáze systému Windows není uvedena v seznamu ovládacího panelu Přidat nebo odebrat programy a není odebrána při odebrání produktu Windows SharePoint Services 3.0 z počítače (Tento článek může obsahovat odkazy na anglický obsah (dosud nepřeložený).)
Problém 4:
Při spuštění skriptu se zobrazí následující chybová zpráva:
Chyba: Nelze se připojit k instanci .\<název_instance> CHYBA: 0x-2147467259 - [DBNETLIB][ConnectionOpen (Connect()).]SQL Server neexistuje nebo byl odepřen přístup
Příčina 4
Tato chybová zpráva se zobrazí v případě splnění následujících podmínek:
-
32bitová verze serveru SQL Server 2000 je nainstalována v 64bitovém operačním systému.
-
V počítači je nainstalována 64bitová verze serveru SQL Server 2005 nebo SQL Server 2008.
Tato chybová se zobrazí, pokud skript používá 64bitovou verzi souboru dbmslpcn.dll. Tato verze nemůže komunikovat s instancemi WoW serveru SQL Server 2000.
Řešení 4
Ke spuštění skriptu použijte 32bitovou verzi souboru cscript.exe ze složky %WINDOWS%\SysWOW64. Bude načtena 32bitová verze souboru dbmslpcn.dll, která dokáže detekovat instance WoW.
Odkazy
Další informace o určení verze a edice serveru SQL Server naleznete v následujícím článku znalostní báze Microsoft Knowledge Base:
321185Určení verze a edice serveru SQL Server (Tento článek může obsahovat odkazy na anglický obsah (dosud nepřeložený).)
Další informace
V následující tabulce jsou uvedeny významné technické revize tohoto článku. Číslo revize a datum poslední kontroly tohoto článku mohou odrážet menší editorské nebo strukturální revize tohoto článku, které nejsou obsaženy v tabulce.
Datum |
Revize |
---|---|
31. prosince 2008 |
Zahrnuje aktualizovaný skript, který detekuje v clusteru instance serveru SQL Server s převzetím služeb při selhání. |
30.12.08 |
Zahrnuje aktualizovaný skript, který detekuje 32bitové verze serveru SQL Server spuštěné v 64bitové verzi systému Windows. |