Microsoft-säkerhetsmeddelande: Säkerhetsproblem i SQL Server möjliggör fjärrkörning av kod

INLEDNING

Microsoft har gett ut ett säkerhetsmeddelande för ett säkerhetsproblem i Microsoft SQL Server som möjliggör fjärrkörning av kod. Säkerhetsmeddelandet, som innehåller ytterligare säkerhetsrelaterad information, finns på följande Microsoft-webbplats: Denna artikel innehåller ett VB-skript som kan användas för att tillämpa en lösning på alla instanser av SQL Server som körs på en lokal dator.

EXEMPEL PÅ ETT VB-SKRIPT SOM KAN ANVÄNDAS FÖR ATT TILLÄMPA LÖSNINGEN

Du kan använda detta VB-skript för att neka Public-rollen körbehörighet för den utökade lagrade sp_replwritetovarbin-proceduren i alla berörda versioner av SQL Server som körs på den lokala datorn.

Microsoft tillhandahåller programmeringsexempel enbart i förklarande syfte och gör inga utfästelser, varken uttryckligen eller underförstått. Detta omfattar men begränsas inte till underförstådd garanti för säljbarhet eller lämplighet för ett visst syfte. I denna artikel förutsätts att du känner till det programmeringsspråk som demonstreras och de verktyg som används för att skapa och felsöka procedurer. Microsofts supporttekniker kan förklara hur en viss procedur fungerar, men de ändrar inte exemplen för att utöka funktionerna och konstruera procedurer som motsvarar dina behov.


Kopiera denna kod till en textfil, spara filen med filnamnstillägget .vbs och kör sedan skriptfilen med hjälp av CScript.exe. Skriptet upprepas för de instanser av SQL Server som körs på den lokala datorn, och lösningen används på de versioner som berörs. Du måste vara medlem av rollen sysadmin i varje instans av SQL Server för att kunna använda lösningen. Om du inte har ett Windows-konto som är medlem av rollen sysadmin på alla berörda servrar där SQL Server körs, måste du kanske köra skriptet från flera konton. I Windows Server 2008 och Windows Vista måste du köra skriptet från en kommandotolk med "förhöjd rättighet", om du använder ett Windows-administratörskonto som är medlem av rollen sysadmin.
'*************************************************************************************
'Beskrivning: Detta skript upprepas i alla instanser av SQL Server som körs
' och nekar Public-rollen körbehörighet på sp_replwritetovarbin i alla
' berörda versioner.
' DETTA ÄR EN TILLFÄLLIG LÖSNING OCH BÖR INTE ANVÄNDAS OM EN SÄKERHETSUPPDATERING
' HAR GJORTS TILLGÄNGLIG OCH INSTALLERATS.
'*************************************************************************************

OPTION EXPLICIT
ON ERROR RESUME NEXT

' Konstanta värden
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 "INFO: Det finns inte några instanser."
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 "FEL: Det gick inte att använda lösningen på " + sInstances(i,0) + "." + vbCRLF
VBMain = EXIT_FAILURE
End If
Next

WScript.Echo "INFO: Alla SQL-instanser som körs har bearbetats."
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 "FEL:Det går inte att läsa SQL-instanser som är installerade på datorn."
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 "FEL:Det går inte att läsa SQL-instanser som är installerade på datorn."
Exit Function
End If
End If

If IsEmptyNull(sInstances1) AND IsEmptyNull(sInstances2) Then
WScript.Echo "INFO: Det finns inte några instanser."
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

' Initiera returvärde
ApplyFix = FALSE

strConn = "Provider=sqloledb;Initial Catalog=master;Integrated Security=SSPI;Data Source=" + strServerName + ";"
' Felkontroll utesluts avsiktligt för att koden ska bli kort
Set objConn = CreateObject("ADODB.Connection")
Set objCmd = CreateObject("ADODB.Command")
Set objCmd1 = CreateObject("ADODB.Command")

' Öppna en anslutning till huvuddatabasen
objConn.Open strConn
If ErrorOccurred("Fel: Det gick inte att ansluta till " + strInstance) Then
Set objConn = Nothing
Exit Function
End If

' Kontrollera versionen innan korrigeringen installeras
strCommand = "välj SERVERPROPERTY('ProductVersion') som version, SERVERPROPERTY('productlevel') som produktnivå"
objCmd.ActiveConnection = objConn
objCmd.CommandType = adCmdText
objCmd.CommandText = strCommand

Set objRS = objCmd.Execute()
If ErrorOccurred("FEL: Det gick inte att köra """ + strCommand + """ på " + strInstance) = TRUE Then
objConn.Close()
Set objConn = Nothing
ApplyFix = FALSE
Exit Function
End If

strBuildVersion = objRS("version")
strProductLevel = UCase(objRS("productlevel"))

bApplyFix = FALSE
' Lösningen ska endast användas på SQL 2000 och SQL 2005 (RTM, SP1 och 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 = "neka Public-rollen körbehörighet på sp_replwritetovarbin"
objCmd1.ActiveConnection = objConn
objCmd1.CommandType = adCmdText
objCmd1.CommandText = strCommand
Set objRS1 = objCmd1.Execute()
If ErrorOccurred("FEL: Det gick inte att köra """ + strCommand + """ på " + strInstance) = FALSE Then
WScript.Echo "INFO: Lösningen har installerats på " + strInstance + " (" + strBuildVersion + ")." + vbCRLF
ApplyFix = TRUE
End If
Else
WScript.Echo "INFO: Information för " + strInstance + " (" + strBuildVersion + ") samlas inte in, eftersom denna instans inte är sårbar." + 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

'Anslut till WMI och få ett objekt till STDREGPROV-klassen.
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 ("FEL: Det gick inte att ansluta till WMI-namnområde " + DEFAULTNAMESPACE) Then
GetRegValue = FALSE
Exit Function
End If

lRc = 0
Select Case iValueType
' Endast REG_MULTI_SZ är av intresse
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 "FEL: 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")

' Fråga klustertjänst
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

' Om vi kommer hit innebär det att datorn är en klusternod.
' Låt oss därför förfråga registret för att fastställa om SQL-instansen är klustrad.
' Förfråga följande värde för SQL 2000
' HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\<Instansnamn>\Cluster
' Klusternamn
strKey = "SOFTWARE\Microsoft\Microsoft SQL Server\" + strInstanceName + "\Cluster"
GetRegValue "", HKEY_LOCAL_MACHINE, strKey, "Klusternamn", 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, "Klusternamn", strMacName, REG_SZ, b32bit

If StrComp(strMacName, "") <> 0 Then
strInstanceName = BuildInstanceName (strMacName, strInstanceName)
Exit Function
End If

' Låt oss försöka förfråga registervärdet för 2005/2008-instanser
'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
' Om denna nyckel inte finns, återgå som en lokal SQL 2000-instans
strInstanceName = BuildInstanceName (".", strInstanceName)
Exit Function
End If

strKey = "SOFTWARE\Microsoft\Microsoft SQL Server\" + strInstID + "\Cluster"
GetRegValue "", HKEY_LOCAL_MACHINE, strKey, "Klusternamn", 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
Mer information om CScript.exe finns på följande Microsoft-webbplats: Obs! Vi rekommenderar att du inte använder detta skript om en säkerhetsuppdatering har tillhandahållits och du har installerat den.

KÄNDA PROBLEM SOM KAN UPPSTÅ VID KÖRNING AV DETTA SKRIPT

Problem 1

När skriptet körs visas följande felmeddelande:
FEL: Det gick inte att köra "neka Public-rollen körbehörighet på sp_replwritetovarbin" på <instansnamn>
FEL: 0x-2147217900 - Det går inte att hitta objektet 'sp_replwritetovarbin'. Objektet finns inte eller så har du inte den behörighet som krävs.
FEL: Det gick inte att använda lösningen på <instansnamn>.

Orsak 1

Detta felmeddelande visas om du inte har den behörighet som krävs för att göra ändringen. Felmeddelandet anger att du kunde logga in på instansen "<instansnamn>".


Detta felmeddelande förekommer vanligen i SQL Server Express, där gruppen "Built-In\Users" har ett inloggningsnamn till databasen som standard. Denna grupp är emellertid inte medlem av rollen sysadmin.

Felmeddelandet kan även förekomma om du har släppt proceduren sp_replwritetovarbin, vilket rekommenderades i en tredjepartsrapport. Vi rekommenderar inte att du släpper den lagrade proceduren, utan att du i stället använder denna lösning.

Lösning 1

Se till att det konto du ansluter med är medlem av rollen sysadmin i denna instans av databasen. Om kontot inte är medlem lägger du till den användare du ansluter som till rollen sysadmin eller använder ett annat användarkonto. För SQL Server 2005 och tidigare är gruppen "Built-in\Administrators" medlem av rollen sysadmin som standard. När du kör detta skript i Windows Vista eller Windows Server 2008 måste du se till att köra det från en kommandotolk med "förhöjd behörighet".

Problem 2

Om du kör detta skript i SQL Server 2005 visas följande felmeddelande:
Fel: Det gick inte att ansluta till <instansnamn>
FEL: 0x-2147217843 - Inloggning misslyckades för användare '<användare>'.
FEL: Det gick inte att använda lösningen på <instansnamn>.

Orsak 2

Detta felmeddelande visas om du inte har kunnat ansluta till instansen "<instansnamn>", trots att den finns.


Felmeddelandet visas vanligen när du ansluter till Windows Internal Database eller till Microsoft SQL Server 2000 Desktop Edition (Windows)-instanser. Normalt har inga användarkonton inloggningsnamn för dessa databaser.

Lösning 2

Se till att det konto du använder för att köra skriptet har ett databasinloggningsnamn som är medlem av rollen sysadmin.

Vi rekommenderar inte att du lägger till enskilda användare till Windows Internal Database och till Microsoft SQL Server 2000 Desktop Edition (Windows)-databaser. Om du gör detta kan de användare du lägger till störa den normala funktionen hos dessa databaser. I detta fall måste du se till att ansluta från ett konto som är medlem av rollen sysadmin. Gruppen "Built-in\Administrators" i Windows brukar i standardfallet vara medlem av rollen sysadmin i SQL Server 2005 och i tidigare versioner. När du kör detta skript i Windows Vista eller Windows Server 2008 måste du se till att köra det från en kommandotolk med "förhöjd behörighet".

Problem 3

Det kan förekomma en instans av en databas med beteckningen MICROSOFT##SSEE, som du inte har installerat.

Orsak 3

Denna databas är Windows Internal Database, även kallad "SQL Server Embedded Edition" eller ibland "Windows Internal Database" eller "Microsoft SQL Server 2000 Desktop Edition (Windows)". Den installeras tillsammans med vissa produkter från Microsoft, däribland SharePoint Services.

Lösning 3

Lösningsskriptet är konstruerat för att fungera med Windows Internal Database, och du behöver inte vidta några åtgärder.

Vissa program tar inte bort Windows Internal Database när de avinstalleras.
Om du vill veta mer om hur du tar bort Windows Internal Database, klickar du på följande artikelnummer och läser artikeln i Microsoft Knowledge Base:
920277 Windows Internal Database visas inte i Lägg till eller ta bort program och tas inte bort när Windows SharePoint Services 3.0 tas bort från datorn (Länken kan leda till en webbplats som är helt eller delvis på engelska)

Problem 4

När skriptet körs visas följande felmeddelande:

Fel: Det gick inte att ansluta till .\<instansnamn>
FEL: 0x-2147467259 - [DBNETLIB][ConnectionOpen (Connect()).]SQL Server finns inte eller åtkomst nekad

Orsak 4

Detta felmeddelande visas under följande förutsättningar:
  • En 32-bitars version av SQL Server 2000 är installerad i ett x64-bitars operativsystem.
  • En 64-bitars version av SQL Server 2005 eller SQL Server 2008 är installerad på datorn.

Detta felmeddelande visas när en 64-bitars version av filen dbmslpcn.dll används av skriptet. Denna version kan inte kommunicera med WoW-instanserna av SQL Server 2000.

Lösning 4

Använd 32-bitarsversionen av filen cscript.exe från mappen %WINDOWS%\SysWOW64 för att starta skriptet. Därmed läser du in 32-bitarsversionen av filen dbmslpcn.dll, som kan identifiera WoW-instanser.

Referenser

Om du vill veta mer om hur du tar reda på version och utgåva för SQL Server, klickar du på följande artikelnummer och läser artikeln i Microsoft Knowledge Base:
321185 Identifiera version och utgåva för SQL Server (Länken kan leda till en webbplats som är helt eller delvis på engelska)

Mer Information

Viktiga tekniska revideringar av den här artikeln anges i följande tabell. Revisionsnummer och datum för senaste granskning i artikeln kan avspegla mindre redaktionella eller strukturella revideringar som inte ingår i tabellen.
DatumRevideringar
31 december 2008Innehåller ett uppdaterat skript som identifierar SQL Server-instanser av kluster för växling vid fel.
30 december 2008Innehåller ett uppdaterat skript som identifierar 32-bitars versioner av SQL Server som körs i 64-bitars versioner av Windows.
Egenskaper

Artikel-id: 961040 – senaste granskning 7 jan. 2009 – revision: 1

Feedback