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

Artikelöversättning Artikelöversättning
Artikel-id: 961040 - Visa produkter som artikeln gäller.
Visa alla | Dölj alla

På den här sidan

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:
http://www.microsoft.com/technet/security/advisory/961040.mspx
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:
http://technet.microsoft.com/en-us/library/bb490887.aspx
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.
Dölj tabellenVisa 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: den 7 januari 2009 - Revision: 3.0
Informationen i denna artikel gäller:
  • Windows Internal Database
  • Microsoft SQL Server 2005 Service Pack 2 på följande plattformar
    • Microsoft SQL Server 2005 Standard Edition
    • Microsoft SQL 2005 Server Enterprise
    • Microsoft SQL Server 2005 Express Edition
    • Microsoft SQL Server 2005 Express Edition with Advanced Services
    • Microsoft SQL Server 2005 Enterprise X64 Edition
    • Microsoft SQL Server 2005 Standard X64 Edition
    • Microsoft SQL Server 2005 Enterprise Edition for Itanium Based Systems
  • Microsoft SQL Server 2000 Desktop Engine (Windows)
  • Microsoft SQL Server 2000 Desktop Engine (Windows)
  • Microsoft SQL Server 2000 Service Pack 4
Nyckelord: 
kbpubtypekc kbfix kbbug kbsecvulnerability kbsecbulletin kbsecurity KB961040

Ge feedback

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com