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.mspxEste 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 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 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 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: 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 = 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 + ";"    ' 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 = 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    '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 = 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")    ' 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 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

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.aspxNota: 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:

321185Có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.

Fecha

Revisiones

31 de diciembre de 2008

Incluye una secuencia de comandos actualizada que detecta las instancias de clúster de conmutación por error en SQL Server.

30 de diciembre de 2008

Incluye 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.

¿Necesita más ayuda?

¿Quiere más opciones?

Explore las ventajas de las suscripciones, examine los cursos de aprendizaje, aprenda a proteger su dispositivo y mucho más.

Las comunidades le ayudan a formular y responder preguntas, enviar comentarios y leer a expertos con conocimientos extensos.