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