UVOD
Microsoft je objavio bezbednosno savetovanje o ranjivosti u Microsoft SQL Serveru koje bi moglo da dozvoli daljinsko izvršavanje koda. Bezbednosni savet sadrži dodatne informacije vezane za bezbednost. Da biste prikazali bezbednosni savet, posetite sledeću Microsoft Web lokaciju:
http://www.microsoft.com/technet/security/advisory/961040.mspxOvaj članak sadrži VB skriptu koju možete da koristite za primenu zaobilaznog rešenja na sve pokrenute instance sistema SQL Server na lokalnom računaru.
PRIMER VB SKRIPTE KOJU MOŽETE KORISTITI ZA PRIMENU ZAOBILAZNOG REŠENJA
Ovu VB skriptu možete da koristite da biste uskratili dozvolu za izvršavanje javne uloge u sp_replwritetovarbin proširenoj uskladištenoj proceduri na svim pogođenim verzijama sistema SQL Server koje su pokrenute na lokalnom računaru.Microsoft daje programske primere samo za ilustraciju, bez garancije izražene ili podrazumevane. To uključuje, ali nije ograničeno na podrazumevane garancije o prodaji ili podesnosti za određenu namenu. Ovaj članak pretpostavlja da ste upoznati sa programskim jezikom koji se prikazuje i alatkama koje se koriste za kreiranje i otklanjanje grešaka u procedurama. Inženjeri Microsoft podrške mogu da objasne funkcionalnost određene procedure. Međutim, oni neće menjati ove primere da bi obezbedili dodatnu funkcionalnost ili konstruisali procedure da bi ispunili vaše specifične zahteve. Kopirajte ovaj kôd u tekstualnu datoteku, sačuvajte datoteku koristeći oznaku tipa datoteke .vbs, a zatim pokrenite datoteku skripte koristeći datoteku CScript.exe. Skripta se iterate kroz pokrenute instance SQL servera na lokalnom računaru i primenjuje zaobilazno rešenje za pogođene verzije. Morate biti član sysadmin uloge na svakoj instanci SQL Servera da biste primenili zaobilazno rešenje. Ako ne imate Windows nalog koji je član sysadmin uloge na svim serverima na kojima je pokrenut SQL Server, možda ćete morati da pokrenete ovu skriptu sa više naloga. U operativnim sistemima Windows Server 2008 i Windows Vista, ako koristite Windows administratorski nalog koji je član uloge sysadmin, morate pokrenuti ovu skriptu sa komandne linije "u potpunosti".
'*************************************************************************************'Description: This script iterates through all the running instances of SQL Server ' and denies execute permission on sp_replwritetovarbin to public on all' the affected versions.' THIS IS PROVIDED AS A WORKAROUND AND SHOULD NOT BE USED IN THE EVENT THAT ' A SECURITY UPDATE IS PROVIDED AND INSTALLED.'*************************************************************************************OPTION EXPLICITON ERROR RESUME NEXT' Constant valuesCONST EXIT_SUCCESS = 0CONST EXIT_FAILURE = 1CONST EXIT_NOINSTANCES = -1CONST DEFAULTNAMESPACE = "root\default"CONST STDREGPROV = "stdregprov"CONST HKEY_LOCAL_MACHINE = &H80000002CONST REG_MULTI_SZ = 7CONST REG_SZ = 1CONST adCmdText = 1Call 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 "INFO: No instances are present." 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 "ERROR: Could not apply the workaround on " + sInstances(i,0) + "." + vbCRLF VBMain = EXIT_FAILURE End If Next WScript.Echo "INFO: Completed processing all the running SQL instances."End FunctionFunction 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 "ERROR:Failed to read SQL instances installed on the machine." 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 "ERROR:Failed to read SQL instances installed on the machine." Exit Function End If End If If IsEmptyNull(sInstances1) AND IsEmptyNull(sInstances2) Then WScript.Echo "INFO: No instances present." 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 = TRUEEnd FunctionFunction ApplyFix(ByVal strInstance, ByVal strServerName) Err.Clear ON ERROR RESUME NEXT Dim objConn, objCmd, objCmd1, objRS, objRS1 Dim strCommand, strConn Dim strBuildVersion, strProductLevel, bApplyFix ' Initialize return value ApplyFix = FALSE strConn = "Provider=sqloledb;Initial Catalog=master;Integrated Security=SSPI;Data Source=" + strServerName + ";" ' Error checking is intentionally left to keep the code short Set objConn = CreateObject("ADODB.Connection") Set objCmd = CreateObject("ADODB.Command") Set objCmd1 = CreateObject("ADODB.Command") ' Open a Connection to the master Database objConn.Open strConn If ErrorOccurred("Error: Could not connect to " + strInstance) Then Set objConn = Nothing Exit Function End If ' Validate the version before applying the fix 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("ERROR: Could not execute """ + strCommand + """ on " + strInstance) = TRUE Then objConn.Close() Set objConn = Nothing ApplyFix = FALSE Exit Function End If strBuildVersion = objRS("version") strProductLevel = UCase(objRS("productlevel")) bApplyFix = FALSE ' Apply the workaround only for SQL 2000 and SQL 2005 (RTM, SP1 and SP2) versions 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("ERROR: Could not execute """ + strCommand + """ on " + strInstance) = FALSE Then WScript.Echo "INFO: Successfully applied the workaround on " + strInstance + " (" + strBuildVersion + ")." + vbCRLF ApplyFix = TRUE End If Else WScript.Echo "INFO: Skipping collecting information for " + strInstance + " (" + strBuildVersion + ") as this instance is not vulnerable." + vbCRLF ApplyFix = TRUE End If objConn.Close() Set objConn = Nothing Set objCmd = Nothing Set objCmd1 = Nothing Set objRS = Nothing Set objRS1 = NothingEnd FunctionPrivate 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 'Connect to WMI and get an object to STDREGPROV class. 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 ("ERROR: Could not connect to WMI namespace " + DEFAULTNAMESPACE) Then GetRegValue = FALSE Exit Function End If lRc = 0 Select Case iValueType ' We only care about 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 = NothingEnd FunctionFunction 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 = TRUEEnd FunctionPrivate Function ErrorOccurred (ByVal strIn) If Err.Number <> 0 Then WScript.Echo strIn WScript.Echo "ERROR: 0x" & Err.Number & " - " & Err.Description Err.Clear ErrorOccurred = TRUE Else ErrorOccurred = FALSE End IfEnd FunctionFunction 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 IfEnd FunctionFunction 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") ' Query Cluster service 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 ' If we reach here that means the machine is a clustered node. ' So lets query registry to determine whether the SQL instance is clustered or not. ' For SQL 2000 query the following value ' HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\<InstanceName>\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 ' Lets try querying the registry value for 2005/2008 instances '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 ' If this key doesnt exist, then return back as a SQL 2000 local instance 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 FunctionFunction 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 ifEnd Function
Za više informacija o CScript.exe posetite sledeću Microsoft Web lokaciju:
http://technet.microsoft.com/en-us/library/bb490887.aspxNapomena Preporučujemo da ne koristite ovu skriptu ako je obezbeđena bezbednosna ispravka i ako ste je instalirali.
POZNATI PROBLEMI DO KOJIH MOŽE DOĆI KADA POKRENETE OVU SKRIPTU
Problem 1
Kada pokrenete skriptu, dobijate sledeću poruku o grešci:
GREŠKA: Nije moguće izvršiti grešku "zabrani izvršavanje na sp_replwritetovarbin na javno" na <instancename> ERROR: 0x-2147217900 - Nije moguće pronaći objekat "sp_replwritetovarbin", jer on ne postoji ili nema dozvolu. GREŠKA: Nije moguće primeniti zaobilazno rešenje <ime>.
Uzrok 1
Ovu poruku o grešci dobijate ako nemate potrebne dozvole za primenu promene. Ova poruka o grešci ukazuje na to da ste uspeli uspešno da se prijavite u instancu "<ime>". Ova poruka o grešci se obično javlja u SQL Server Expressu u kojem grupa "Ugrađeni\korisnici" podrazumevano ima prijavljivanje na bazu podataka. Međutim, ova grupa nije član sisadminske uloge. Do ove poruke o grešci može doći i ako ste sp_replwritetovarbin proceduru. To je bila preporuka iz izveštaja trećeg proizvođača. Ne preporučujemo odustajanje od uskladištene procedure. Umesto toga, preporučujemo da primenite ovu rezoluciju.
Rezolucija 1
Uverite se da je nalog sa kojiom se povezujete član sysadmin uloge na toj instanci baze podataka. Ako nalog nije član, dodajte korisnika koga povezujete u vezi sa sysadmin ulogom ili koristite drugi korisnički nalog. Za SQL Server 2005 i starije verzije, grupa "Ugrađeni\administratori" je podrazumevano član sysadmin uloge. Kada pokrenete ovu skriptu u operativnom sistemu Windows Vista ili Windows Server 2008, uverite se da ste je pokrenuli sa komandne linije "podignuto".
Problem 2
Ako pokrenete ovu skriptu u sistemu SQL Server 2005, dobićete sledeću poruku o grešci:
Greška: Nije moguće povezati se <ime>: 0x-2147217843 - Prijavljivanje nije uspelo za korisničko "<korisničko>". GREŠKA: Nije moguće primeniti zaobilazno rešenje <ime>.
Uzrok 2
Ovu poruku o grešci dobijate ako niste mogli da se povežete sa instancom "<ime>" iako ova instanca postoji. Do ove poruke o grešci obično dolazi kada se povežete sa Windows internom bazom podataka ili sa instancama operativnog sistema Microsoft SQL Server 2000 Desktop Edition (Windows). Obično nijedan korisnički nalog nema prijave na ove baze podataka.
Rezolucija 2
Uverite se da nalog koji koristite za pokretanje skripte ima prijavu na bazu podataka koja je član sysadmin uloge. Ne preporučujemo da pojedinačne korisnike dodajete u Windows Internu bazu podataka i u Microsoft SQL Server 2000 Desktop Edition (Windows) baze podataka. Ako to uradite, korisnici koje dodate mogu da ometaju običan rad ovih baza podataka. U tom slučaju, uverite se da ste povezani sa nalogom koji je član sysadmin uloge. Grupa "Ugrađeni\administratori" u operativnom sistemu Windows obično je podrazumevano član sysadmin uloge u sistemu SQL Server 2005 i u ranijim verzijama. Kada pokrenete ovu skriptu u operativnom sistemu Windows Vista ili Windows Server 2008, uverite se da ste je pokrenuli sa komandne linije "podignuto".
Problem 3
Možda ćete primetiti instancu baze podataka pod imenom MICROSOFT##SSEE. Međutim, niste instalirali ovu bazu podataka.
Uzrok 3
Ova baza podataka je Windows interna baza podataka, poznata i kao "SQL Server Embedded Edition" ili ponekad poznata kao "Windows Unutrašnja baza podataka" ili "Microsoft SQL Server 2000 Desktop Edition (Windows)." Instalira se sa nekim proizvodima korporacije Microsoft, uključujući SharePoint Services.
Rezolucija 3
Skripta za zaobilazno rešenje je dizajnirana da funkcioniše sa Windows internom bazom podataka. Nikakva akcija nije potrebna sa vaše strane. Neke aplikacije ne uklanjaju Windows internu bazu podataka kada se deinstaliraju. Za više informacija o uklanjanju Windows interne baze podataka kliknite na sledeći broj članka da biste videli članak u Microsoft bazi znanja:
920277 Windows interna baza podataka nije navedena u alatki "Dodaj ili ukloni programe" i ne uklanja se kada uklonite Sistem Windows SharePoint Services 3.0 sa računara
Problem 4
Kada pokrenete skriptu, dobijate sledeću poruku o grešci:
Greška: nije moguće povezati se sa .\<imenom instance>ERROR: 0x-2147467259 - [DBNETLIB][ConnectionOpen (Connect()).] SQL Server ne postoji niti je zabranjen pristup
Uzrok 4
Ovu poruku o grešci dobijate ako su ispunjeni sledeći uslovi:
-
Imate instaliranu 32-bitnu verziju sistema SQL Server 2000 na x64-bitni operativni sistem.
-
Na računaru imate instaliranu 64-bitnu verziju sistema SQL Server 2005 ili SQL Server 2008.
Do ove poruke o grešci dolazi kada skripta koristi 64-bitnu verziju datoteke dbmslpcn.dll. Ova verzija ne može da komunicira sa WoW instancama sistema SQL Server 2000.
Rezolucija 4
Koristite 32-bitnu verziju datoteke cscript.exe iz fascikle %WINDOWS%\SysWOW64 da biste pokrenuli skriptu. Ovo učitava 32-bitnu verziju datoteke dbmslpcn.dll koja može da otkrije WoW instance.
Reference
Za više informacija o identifikovanju verzije i izdanja sistema SQL Server kliknite na sledeći broj članka da biste videli članak u Microsoft bazi znanja:
321185Kako da identifikujete SQL Server verziju i izdanje
Više informacija
Sledeća tabela navodi značajne tehničke revizije ovog članka. Broj revizije i datum poslednjeg redigonja u ovom članku mogu da ukazuju na manje uredničke revizije ili strukturne revizije ovog članka koje nisu uključene u tabelu.
Datum |
Revizije |
---|---|
31 decembar 2008 |
Uključuje ažuriranu skriptu koja otkriva instance grupisanja neuspešnog sql servera. |
30 decembar 2008 |
Uključuje ažuriranu skriptu koja otkriva 32-bitne verzije sistema SQL Server koje rade u 64-bitnim verzijama operativnog sistema Windows. |