Aviso de seguridad de Microsoft: una vulnerabilidad en SQL Server podría permitir la ejecución remota de código

Seleccione idioma Seleccione idioma
Id. de artículo: 961040 - Ver los productos a los que se aplica este artículo
Expandir todo | Contraer todo

En esta página

INTRODUCCIÓN

Microsoft ha publicado un aviso de seguridad sobre una vulnerabilidad en Microsoft SQL Server que podría permitir la ejecución del código. El aviso de seguridad contiene información adicional relacionada con la seguridad. Para ver el aviso de seguridad, visite el siguiente sitio Web de Microsoft:
http://www.microsoft.com/spain/technet/security/advisory/961040.mspx
Este artículo incluye una secuencia de comandos VB que puede utilizar para aplicar una solución a todas las instancias de SQL Server que se estén ejecutando en un equipo local.

EJEMPLO DE UNA SECUENCIA DE COMANDOS VB QUE PUEDE UTILIZAR PARA APLICAR LA SOLUCIÓN

Puede utilizar esta secuencia de comandos VB para denegar el permiso de ejecución a la función pública en el procedimiento almacenado extendido sp_replwritetovarbin en todas las versiones afectadas del SQL Server que se ejecutan en el equipo local.

Microsoft proporciona ejemplos de programación con fines ilustrativos únicamente, sin ninguna garantía, ya sea expresa o implícita. Esto incluye, entre otras, las garantías implícitas de comerciabilidad e idoneidad para un fin determinado. En este artículo se da por supuesto que ya conoce el lenguaje de programación que se muestra, así como las herramientas empleadas para crear y depurar procedimientos. Los ingenieros de soporte técnico de Microsoft pueden ayudar a explicar la funcionalidad de un procedimiento en particular. Sin embargo, no modificarán estos ejemplos para proporcionar una funcionalidad adicional ni crearán procedimientos que se adapten a sus necesidades específicas.

Copie este código en un archivo de texto, guarde el archivo utilizando un archivo con la extensión .vbs y ejecute el archivo de la secuencia de comandos utilizando CScript.exe. La secuencia de comandos recorre las instancias SQL Server que se encuentran en ejecución en el equipo local y aplica la solución en las versiones afectadas. Para aplicar la solución temporal, debe ser miembro de la función sysadmin en cada instancia de SQL Server. Si usted no dispone de una cuenta Windows que le haga miembro de la función sysadmin en todos los servidores afectados que se están ejecutando SQL Server, deberá ejecutar esta secuencia de comandos desde múltiples cuentas. Si está utilizando una cuenta del administrador de Windows que es miembro de la función sysadmin en Windows Server 2008 y en Windows Vista, debe ejecutar esta secuencia de comandos desde un símbolo de sistema elevado.
'*************************************************************************************
'Descripción: esta secuencia de comandos recorre las instancias de SQL Server que se están ejecutando
'            y deniega el permiso de ejecución a la función pública en sp_replwritetovarbin en todas
'            las versiones afectadas.
'            ÉSTA ES UNA SOLUCIÓN TEMPORAL Y NO DEBE UTILIZARSE EN CASO DE QUE
'            SE PROPORCIONE E INSTALE UNA ACTUALIZACIÓN DE SEGURIDAD.
'*************************************************************************************

OPTION EXPLICIT
ON ERROR RESUME NEXT

' Constant values
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: No existe ninguna instancia."
        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: No se puedo aplicar la solución en " + sInstances(i,0) + "." + vbCRLF
            VBMain = EXIT_FAILURE
        End If
    Next
	
    WScript.Echo "INFO: el proceso de todas las instancias de SQL que se están ejecutando se ha completado".
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 "ERROR: error al leer las instancias SQL instaladas en el equipo."
        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: error al leer las instancias SQL instaladas en el equipo."
            Exit Function
        End If
    End If

    If IsEmptyNull(sInstances1) AND IsEmptyNull(sInstances2) Then 
        +WScript.Echo "INFO: no existe ninguna instancia".
        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

    ' Initialize return value
    ApplyFix = FALSE
    
    strConn = "Provider=sqloledb;Initial Catalog=master;Integrated Security=SSPI;Data Source=" + strServerName + ";"
    ' La comprobación de errores se ha mantenido de manera intencionada para reducir el código
    Set objConn = CreateObject("ADODB.Connection")
    Set objCmd = CreateObject("ADODB.Command")
    Set objCmd1 = CreateObject("ADODB.Command")
    
    ' Abrir una conexión a la base de datos maestra
    objConn.Open strConn 
    If ErrorOccurred("Error: no se pudo establecer la conexión a " + strInstance) Por consiguiente,
        Set objConn = Nothing
        Exit Function
    End If

    ' Valide la versión antes de aplicar la solución
    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: no se pudo ejecutar """ + strCommand + """ on " + strInstance) = TRUE Por consiguiente,
        objConn.Close()
        Set objConn = Nothing
        ApplyFix = FALSE
        Exit Function   
    End If

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

    bApplyFix = FALSE
    ' Aplique la solución únicamente en las versiones SQL 2000 y SQL 2005 (RTM, SP1 y 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("ERROR: no se pudo ejecutar """ + strCommand + """ on " + strInstance) = FALSE Then
            WScript.Echo "INFO: se aplicó correctamente la solución en " + strInstance + " (" + strBuildVersion + ")." + vbCRLF
            ApplyFix = TRUE
        End If
    Else
        WScript.Echo "INFO: omisión de la recopilación de información para " + strInstance + " (" + strBuildVersion + ") ya que esta instancia no es vulnerable". + 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

    'Conéctese al servicio WMI y obtenga un objeto para la clase 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 ("ERROR: No se pudo conectar al espacio de nombres " + 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 = 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 "ERROR: 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")

    ' Consultar el servicio de clúster
    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
    
    ' Si logramos llegar hasta aquí, significa que el equipo es un nodo de clúster.
    ' Así que solicite el registro para determinar si la instancia SQL está agrupada o no.
    ' Para SQL 2000 solicite el valor siguiente
    ' 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

    ' Intente solicitar el valor del registro para las instancias 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
        ' Si esta clave no existe, volverá a ser una instancia local 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
Para obtener más información acerca de CScript.exe, visite el siguiente sitio Web de Microsoft:
http://technet.microsoft.com/en-us/library/bb490887.aspx
Nota: le recomendamos que no utilice esta secuencia de comandos si ha instalado la actualización de seguridad que se le ha proporcionado.

PROBLEMAS CONOCIDOS QUE PUEDEN PRODUCIRSE AL EJECUTAR ESTA SECUENCIA DE COMANDOS

Problema 1

Cuando ejecuta la secuencia de comandos, recibirá el mensaje de error siguiente:
ERROR: No se puede ejecutar "denegar ejecutar en sp_replwritetovarbin para público" en <instancename>.
ERROR: 0x-2147217900 - no se puede encontrar el objeto 'sp_replwritetovarbin', porque no existe o no tiene permiso.
ERROR: no se puede aplicar la solución en <nombreInstancia>.

Causa 1

Recibirá este mensaje de error si no tiene los permisos necesarios para aplicar el cambio. Este mensaje de error indica que se le permite conectarse correctamente a la instancia "<instancename>."

Este mensaje de error suele ocurrir en SQL Server Express en el que el grupo de "Built-In\Users" tiene un inicio de sesión en la base de datos de forma predeterminada. Sin embargo, este grupo no es miembro de la función sysadmin.

Este mensaje de error podría producirse también si se interrumpe el procedimiento sp_replwritetovarbin. Esta es la recomendación de un informe de otros fabricantes. No se recomienda colocar el procedimiento almacenado. En su lugar, le recomendamos que aplique esta solución.

Resolución 1

Asegúrese de que la cuenta con la que se conecta sea miembro de la función sysadmin en esa instancia de la base de datos. Si la cuenta no es miembro, debe agregar el usuario con el que se está conectando a la función sysadmin o bien, utilizar otra cuenta de usuario. Para SQL Server 2005 y versiones anteriores, el grupo "Built-in\Administrators" es miembro de la función sysadmin de forma predeterminada. Cuando ejecuta esta secuencia de comandos en Windows Vista o en Windows Server 2008, asegúrese de que se ejecute desde un símbolo del sistema con privilegios elevados.

Problema 2

Si ejecuta esta secuencia de comandos en SQL Server 2005, recibirá el siguiente mensaje de error:
Error: no se puede conectar a <nombreInstancia>
ERROR: 0x-2147217843 - error en el inicio de sesión para el usuario '<usuario>'.
ERROR: no se puede aplicar la solución en <nombreInstancia>.

Causa 2

Recibirá este mensaje de error si no se pudo conectar a la instancia "<nombreInstancia>" incluso si existe dicha instancia.

Este mensaje de error suele producirse cuando se conecta a Windows Internal Database o a las instancias de Microsoft SQL Server 2000 Desktop Edition (Windows). Normalmente, no hay cuentas de usuario que tengan inicios de sesión a estas bases de datos.

Resolución 2

Asegúrese de que la cuenta que utiliza para ejecutar la secuencia de comandos tenga un inicio de sesión a la base de datos que sea miembro de la función sysadmin.

No es recomendable que agregue usuarios individuales a Windows Internal Database y a bases de datos de Microsoft SQL Server 2000 Desktop Edition (Windows). Si lo hace, los usuarios que agregue pueden interferir en el funcionamiento normal de estas bases de datos. En este caso, asegúrese de conectarse desde una cuenta que sea miembro de la función sysadmin. El grupo "Built-in\Administrators" de Windows es normalmente miembro de la función sysadmin de forma predeterminada en SQL Server 2005 y en versiones anteriores. Cuando ejecuta esta secuencia de comandos en Windows Vista o en Windows Server 2008, asegúrese de ejecutarla desde un símbolo del sistema con privilegios elevados.

Problema 3

Puede que observe una instancia de una base de datos con nombre MICROSOFT##SSEE. Sin embargo, no ha instalado esta base de datos.

Causa 3

Esta base de datos es la Windows Internal Database, también conocida como "SQL Server Embedded Edition" o, a veces, como "Windows Internal Database" o "Microsoft SQL Server 2000 Desktop Edition (Windows)". Se instala con algunos productos de Microsoft, como SharePoint Services.

Resolución 3

La secuencia de comandos de la solución está diseñada para que funcione con Windows Internal Database. No es necesaria ninguna acción por su parte.

Algunas aplicaciones no eliminan Windows Internal Database cuando no están instaladas. Para obtener más información acerca de cómo eliminar Windows Internal Database, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
920277 Windows Internal Database no se muestra en ninguna herramienta como Agregar o quitar programas y no se elimina cuando borra Windows SharePoint Services 3.0 de su equipo.

Problema 4

Cuando ejecuta la secuencia de comandos, recibirá el mensaje de error siguiente:
Error: No se puede conectar a .\<instancename>
ERROR: 0x-2147467259 - [DBNETLIB][ConnectionOpen (Connect()).]El servidor SQL Server no existe o se denegó el acceso

Causa 4

Usted va a recibir este mensaje de error si se cumplen las condiciones siguientes:
  • Posee una versión de 32 bits de SQL Server 2000 instalado en un sistema operativo de 64 bits.
  • Tiene una versión de 64 bits de SQL Server 2005 o de SQL Server 2008 instalado en el equipo.
Este mensaje de error sucede cuando la secuencia de comandos que se utiliza en la versión de 64 bits del archivo dbmslpcn.dll. Esta versión no se puede comunicar con las instancias WoW de SQL Server 2000.

Resolución 4

Utilice la versión de 32 bits del archivo cscript.exe desde la carpeta %WINDOWS%\SysWOW64 para iniciar la secuencia de comandos. Esto carga la versión de 32 bits del archivo dbmslpcn.dll que puede detectar las instancias WoW.

Referencias

Para obtener más información sobre cómo identificar la versión y edición de SQL Server, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
321185 Cómo identificar la versión y la edición de SQL Server

Más información

En la tabla siguiente se enumeran las revisiones técnicas significativas de este artículo. El número de revisión y la fecha de revisión más reciente del artículo podrían indicar revisiones estructurales o revisiones editoriales menores que no se incluyen en la tabla.
Contraer esta tablaAmpliar esta tabla
FechaRevisiones
31 de diciembre de 2008Incluye una secuencia de comandos actualizada que detecta las instancias de clúster de conmutación por error en SQL Server.
30 de diciembre de 2008Incluye una secuencia de comandos actualizada que detecta las versiones de 32 bits de SQL Server que se están ejecutando en las versiones de Windows de 64 bits.

Propiedades

Id. de artículo: 961040 - Última revisión: viernes, 09 de enero de 2009 - Versión: 3.0
La información de este artículo se refiere a:
  • Windows Internal Database
  • Microsoft SQL Server 2005 Service Pack 2 sobre las siguientes plataformas
    • Microsoft SQL Server 2005 Standard Edition
    • Microsoft SQL Server 2005 Enterprise Edition
    • 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
Palabras clave: 
kbpubtypekc kbfix kbbug kbsecvulnerability kbsecbulletin kbsecurity KB961040

Enviar comentarios

 

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