Si te interesa la virtualización, y sobre todo si estas probando Hyper-V y trabajas también con ESX, este producto va a dar bastante que hablar. Se trata de la evolución de SCVMM 2007 para gestionar también hosts con Hyper-V y VMWARE ESX como venía haciendo hasta ahora con Virtual Server 2005 R2 SP1.
He de reconocer que hace unos días que lo tengo en uno de los equipos, y tanto el proceso de instalación, como el de agregar los hosts y trabajar con sus VMs es bastante sencillo. No le he dado mucho más uso aún porque me hubiera resultado complicado estarme calladito, y teníamos órdenes explicitas de no enseñarlo hasta ahora.
Os lo podés descargar de http://connect.microsoft.com (debería bastar con hacer clic aquí para solicitar la participación en la "conexion", o aquí si ya lo habéis hecho):
Más información aqui: http://www.microsoft.com/systemcenter/scvmm/default.mspx
y pronto, más por mi parte.
Saludos
David Cervigón
Ya está publicado para los subscriptores de TechNet y MSDN (http://technet.microsoft.com/es-es/subscriptions/bb545043.aspx):
Pronto estará disponible para descarga general en el Windows XP Service Pack 3 website. Por ahora lo que sí se ha publicado es información general sobre el mismo, además del Windows XP Service Pack 3 Overview, un documento con detalles más técnicos, organizado por mejoras a las funcionalidades ya existentes, y las nuevas características que se han introducido.
Mi recomendación es lógicamente probarlo e desplegarlo en las máquinas con Windows XP. Yo de hecho voy a ponerlo raudo y veloz en mis máquinas virtuales para poder instalar las Integration Components de Hyper-V. Pero supongo que ahora tocará escuchar (o leer) cantarle alabanzas y desearle larga vida a todos los que en su dia denostaron el SP2, que era malo malísimo y un paso en la dirección equivocada. Veremos estudios sobre lo estupenda y niquelada que te deja la máquina, sobre todo si se compara con el SP1 de Windows Vista, y sabremos de casos milagrosos en los que Office abre archivos en menos de 2 segundos, y equipos que arrancan en menos de medio minuto, incluso desde discos de 5 1/4. Todo ello superado de largo, como no podía ser de otra manera, por cualquier otro SO que el investigador, o alguien a quien conoce, tiene instalado, con arranque dual.
En fin, lo de siempre.
Piensa por ti mismo.
Hola
El viernes nos preguntábamos si para poder instalar los Language Interface Packs (LIP) del Catalá, Euskera y Galego en Windows Vista era necesario que el Sistema Operativo base estuviese en Español o si con el Inglés también se podía. Dado que el requerimiento de estos LIP es que la interfaz de usuario esté en Español la duda era si la base en Inglés con el MUI en Español bastaba para poder instalarlos.
Los MUI (Multillingual User Interface) están incluidos como extra en Windows Vista Ultimate y hasta ahora yo había probado tanto a instalar Vista en inglés y aplicar el Language Pack en español como a la inversa; instalar Windows Vista en Español y aplicarle el MUI en Inglés. Y lo mismo con Office 2007. De hecho, es la configuración del equipo desde el que estoy escribiendo, a contracorriente de lo que se suele hacer dentro de Microsoft.
Estos pantallazos confirman que si es posible usar una instalación base en Inglés, instalar el Language Pack en Español, y luego aplicar los LIP del Catalán, el Gallego y el Euskera.
Partimos de una máquina virtual con una versión de windows Vista Ultimate en Inglés, instalamos el Language Pack en Español, que aparece como un extra, iniciamos sesión con la interfaz en el nuevo idioma, nos descargamos los LIPs, y los agregamos todos a la vez si queremos (nótese que el Euskera y el Catalán pueden usar como base un Vista en Francés):
Para entender mejor todo esto de los Sistemas Operativos base, los MUI y los LIP lo mejor es leerse la Guide to Windows Vista Multilingual User Interface. Si lo que queremos es integrarlos en despliegues de Windows Vista, las instrucciones están en la Windows Vista Multilingual User Interface Step-by-Step Guide
Pablo, uno de nuestros participantes en el IT Momentum que está muy animado probando Windows Server 2008, me pregunta acerca del compartamiento de una instalación Server Core con respecto a las actualizaciones automáticas.
La respuesta corta es que Server Core mantiene intacto el Agente de Windows Update. Por tanto, correctamente configurado, puede descargar e instalar actualizaciones tanto de Microsoft Update como de un servidor WSUS.
Con respecto a cómo configurarlo, pues igual que siempre. O bien por políticas de grupo, o a mano. Para una configuración rápida del agente, hay un comando rápido:
c:\windows\system32> cscript scregedit.wsf /AU 4 NOTA: Aqui podríamos poner 1, 2, 3 o 5. En Server Core no podemos recibir notificaciones, por lo que no tienen demasiado sentido, asi es que cuidado con los las GPOs que afecten a los Server Cores de la red. El valor 0 deshabilita la descarga e instalación automática de las actualizaciones, pero aun asi se pueden hacer a mano (ver más abajo)
c:\windows\system32> cscript scregedit.wsf /AU 4
NOTA: Aqui podríamos poner 1, 2, 3 o 5. En Server Core no podemos recibir notificaciones, por lo que no tienen demasiado sentido, asi es que cuidado con los las GPOs que afecten a los Server Cores de la red. El valor 0 deshabilita la descarga e instalación automática de las actualizaciones, pero aun asi se pueden hacer a mano (ver más abajo)
Ahora bien. ¿Como sabemos si esto esta funcionando?. ¿Como fuerzo el chequeo contra Microsoft Update o contra el servidor WSUS en su caso?. ¿Como forzar la instalación de una actualización en particular?
Aqui os dejo algunos scripts que he fusilado de aquí y de allá. Hay que ejecutarlos mediante cscript.
ListInstalledUpdates.vbs
Set objSession = CreateObject("Microsoft.Update.Session")Set objSearcher = objSession.CreateUpdateSearcherintHistoryCount = objSearcher.GetTotalHistoryCount Set colHistory = objSearcher.QueryHistory(1, intHistoryCount) For Each objEntry in colHistory Wscript.Echo "Title: " & objEntry.Title Wscript.Echo "Date: " & objEntry.Date Wscript.Echo "Service ID: " & objEntry.ServiceID Wscript.Echo "Support URL: " & objEntry.SupportURL Wscript.EchoNext
Set objSession = CreateObject("Microsoft.Update.Session")Set objSearcher = objSession.CreateUpdateSearcherintHistoryCount = objSearcher.GetTotalHistoryCount
Set colHistory = objSearcher.QueryHistory(1, intHistoryCount)
For Each objEntry in colHistory Wscript.Echo "Title: " & objEntry.Title Wscript.Echo "Date: " & objEntry.Date Wscript.Echo "Service ID: " & objEntry.ServiceID Wscript.Echo "Support URL: " & objEntry.SupportURL Wscript.EchoNext
CheckUpdates.vbs
Set objSearcher = CreateObject("Microsoft.Update.Searcher")Set objResults = objSearcher.Search("Type='Software'")Set colUpdates = objResults.Updates For i = 0 to colUpdates.Count - 1 Wscript.Echo "Title: " & colUpdates.Item(i).Title Set objIdentity = colUpdates.Item(i).Identity Wscript.Echo "Revision number: " & objIdentity.RevisionNumber Wscript.Echo "Update ID: " & objIdentity.UpdateID Set objInstallationBehavior = colUpdates.Item(i).InstallationBehavior Wscript.Echo "Can request user input: " & _ objInstallationBehavior.CanRequestUserInput Wscript.Echo "Support URL: " & colUpdates.Item(i).SupportURL Wscript.Echo "Type: " & colUpdates.Item(i).Type For Each strArticle in colUpdates.Item(i).KBArticleIDs Wscript.Echo "KB article: " & strArticle Next Wscript.EchoNext
Set objSearcher = CreateObject("Microsoft.Update.Searcher")Set objResults = objSearcher.Search("Type='Software'")Set colUpdates = objResults.Updates
For i = 0 to colUpdates.Count - 1 Wscript.Echo "Title: " & colUpdates.Item(i).Title Set objIdentity = colUpdates.Item(i).Identity Wscript.Echo "Revision number: " & objIdentity.RevisionNumber Wscript.Echo "Update ID: " & objIdentity.UpdateID
Set objInstallationBehavior = colUpdates.Item(i).InstallationBehavior Wscript.Echo "Can request user input: " & _ objInstallationBehavior.CanRequestUserInput Wscript.Echo "Support URL: " & colUpdates.Item(i).SupportURL Wscript.Echo "Type: " & colUpdates.Item(i).Type For Each strArticle in colUpdates.Item(i).KBArticleIDs Wscript.Echo "KB article: " & strArticle Next Wscript.EchoNext
InstallUpdate.vbs (necesita como parámetro el UpdateID que suelta CheckUpdates.vbs)
Set objArgs = WScript.ArgumentsUpdate = objArgs(0) Set objCollection = CreateObject("Microsoft.Update.UpdateColl") Set objSearcher = CreateObject("Microsoft.Update.Searcher")Set objResults = objSearcher.Search _ ("UpdateID='" & Update & "'")Set colUpdates = objResults.UpdatesobjCollection.Add(colUpdates.Item(0)) Set objInstaller = CreateObject("Microsoft.Update.Installer")objInstaller.Updates = objCollectionSet objInstallResults = objInstaller.InstallWscript.Echo objInstallResults.RebootRequiredWscript.Echo objInstallResults.ResultCode
Set objArgs = WScript.ArgumentsUpdate = objArgs(0)
Set objCollection = CreateObject("Microsoft.Update.UpdateColl")
Set objSearcher = CreateObject("Microsoft.Update.Searcher")Set objResults = objSearcher.Search _ ("UpdateID='" & Update & "'")Set colUpdates = objResults.UpdatesobjCollection.Add(colUpdates.Item(0))
Set objInstaller = CreateObject("Microsoft.Update.Installer")objInstaller.Updates = objCollectionSet objInstallResults = objInstaller.InstallWscript.Echo objInstallResults.RebootRequiredWscript.Echo objInstallResults.ResultCode
SCWindowsUpdate.vbs (todo lo anterior junto)
Set updateSession = CreateObject("Microsoft.Update.Session")Set updateSearcher = updateSession.CreateupdateSearcher() WScript.Echo "Searching for updates..." & vbCRLF Set searchResult = _updateSearcher.Search("IsInstalled=0 and Type='Software'") WScript.Echo "List of applicable items on the machine:" For I = 0 To searchResult.Updates.Count-1 Set update = searchResult.Updates.Item(I) WScript.Echo I + 1 & "> " & update.TitleNext If searchResult.Updates.Count = 0 Then WScript.Echo "There are no applicable updates." WScript.QuitEnd If WScript.Echo vbCRLF & "Would you like to install updates now? (Y/N)"strInput = WScript.StdIn.ReadlineWScript.Echo If (strInput = "N" or strInput = "n") Then WScript.QuitElseIf (strInput = "Y" or strInput = "y") Then WScript.Echo vbCRLF & "Creating collection of updates to download:" Set updatesToDownload = CreateObject("Microsoft.Update.UpdateColl") For I = 0 to searchResult.Updates.Count-1 Set update = searchResult.Updates.Item(I) WScript.Echo I + 1 & "> adding: " & update.Title updatesToDownload.Add(update) Next WScript.Echo vbCRLF & "Downloading updates..." Set downloader = updateSession.CreateUpdateDownloader() downloader.Updates = updatesToDownload downloader.Download() WScript.Echo vbCRLF & "List of downloaded updates:" For I = 0 To searchResult.Updates.Count-1 Set update = searchResult.Updates.Item(I) If update.IsDownloaded Then WScript.Echo I + 1 & "> " & update.Title End If Next Set updatesToInstall = CreateObject("Microsoft.Update.UpdateColl") WScript.Echo vbCRLF & _ "Creating collection of downloaded updates to install:" For I = 0 To searchResult.Updates.Count-1 set update = searchResult.Updates.Item(I) If update.IsDownloaded = true Then WScript.Echo I + 1 & "> adding: " & update.Title updatesToInstall.Add(update) End If Next End If WScript.Echo vbCRLF & "Would you like to install updates now? (Y/N)"strInput = WScript.StdIn.ReadlineWScript.Echo If (strInput = "N" or strInput = "n") Then WScript.QuitElseIf (strInput = "Y" or strInput = "y") Then WScript.Echo "Installing updates..." Set installer = updateSession.CreateUpdateInstaller() installer.Updates = updatesToInstall Set installationResult = installer.Install() 'Output results of install WScript.Echo "Installation Result: " & _ installationResult.ResultCode WScript.Echo "Reboot Required: " & _ installationResult.RebootRequired & vbCRLF WScript.Echo "Listing of updates installed " & _ "and individual installation results:" For I = 0 to updatesToInstall.Count - 1 WScript.Echo I + 1 & "> " & _ updatesToInstall.Item(i).Title & _ ": " & installationResult.GetUpdateResult(i).ResultCode NextEnd If
Set updateSession = CreateObject("Microsoft.Update.Session")Set updateSearcher = updateSession.CreateupdateSearcher()
WScript.Echo "Searching for updates..." & vbCRLF
Set searchResult = _updateSearcher.Search("IsInstalled=0 and Type='Software'")
WScript.Echo "List of applicable items on the machine:"
For I = 0 To searchResult.Updates.Count-1 Set update = searchResult.Updates.Item(I) WScript.Echo I + 1 & "> " & update.TitleNext
If searchResult.Updates.Count = 0 Then WScript.Echo "There are no applicable updates." WScript.QuitEnd If
WScript.Echo vbCRLF & "Would you like to install updates now? (Y/N)"strInput = WScript.StdIn.ReadlineWScript.Echo
If (strInput = "N" or strInput = "n") Then WScript.QuitElseIf (strInput = "Y" or strInput = "y") Then
WScript.Echo vbCRLF & "Creating collection of updates to download:"
Set updatesToDownload = CreateObject("Microsoft.Update.UpdateColl")
For I = 0 to searchResult.Updates.Count-1 Set update = searchResult.Updates.Item(I) WScript.Echo I + 1 & "> adding: " & update.Title updatesToDownload.Add(update) Next
WScript.Echo vbCRLF & "Downloading updates..."
Set downloader = updateSession.CreateUpdateDownloader() downloader.Updates = updatesToDownload downloader.Download()
WScript.Echo vbCRLF & "List of downloaded updates:"
For I = 0 To searchResult.Updates.Count-1 Set update = searchResult.Updates.Item(I) If update.IsDownloaded Then WScript.Echo I + 1 & "> " & update.Title End If Next
Set updatesToInstall = CreateObject("Microsoft.Update.UpdateColl")
WScript.Echo vbCRLF & _ "Creating collection of downloaded updates to install:"
For I = 0 To searchResult.Updates.Count-1 set update = searchResult.Updates.Item(I) If update.IsDownloaded = true Then WScript.Echo I + 1 & "> adding: " & update.Title updatesToInstall.Add(update) End If Next
End If
If (strInput = "N" or strInput = "n") Then WScript.QuitElseIf (strInput = "Y" or strInput = "y") Then WScript.Echo "Installing updates..." Set installer = updateSession.CreateUpdateInstaller() installer.Updates = updatesToInstall Set installationResult = installer.Install() 'Output results of install WScript.Echo "Installation Result: " & _ installationResult.ResultCode WScript.Echo "Reboot Required: " & _ installationResult.RebootRequired & vbCRLF WScript.Echo "Listing of updates installed " & _ "and individual installation results:" For I = 0 to updatesToInstall.Count - 1 WScript.Echo I + 1 & "> " & _ updatesToInstall.Item(i).Title & _ ": " & installationResult.GetUpdateResult(i).ResultCode NextEnd If
Para los que hayáis echado de menos en Hyper-V el comando VHDMount.exe que incorporaba Virtual Server 2005 R2 SP1, aquí va un pequeño truco que os puede facilitar la vida cuando se trabaja con máquinas virtuales con el hypervisor de Windows Server 2008.
Lo he hecho mediante un script de powershell, pero se puede hacer también con VBScript (basta utilizar como base este artículo de The Virtual PC Guy). Se trata de lograr que nos aparezca lo siguiente cuando se hace clic con el botón derecho en un fichero .vhd:
MountVHD.ps1:
Primeramente, el script de powershell que monta, desmonta o compacta un .vhd. Lógicamente, puede usarse también desde la consola de powershell:
$VHDService = get-wmiobject -class "Msvm_ImageManagementService" -namespace "root\virtualization" -computername "." if($args[1] -eq "Mount"){$Result = $VHDService.Mount($args[0])}elseif($args[1] -eq "UnMount"){$Result = $VHDService.UnMount($args[0])}elseif($args[1] -eq "Compact"){$Result = $VHDService.CompactVirtualHardDisk($args[0])}
El script acepta dos parámetros. El primero es el path completo al .vhd y el segundo es la acción a llevar a cabo, que puede ser Mount, UnMount o Compact. Por ejemplo:
NOTA: Para que esto funcione, será necesario tener una política de ejecución en powershell que permita la correcta ejecución de scripts (p.e set-executionpolicy unrestricted).
VHDfile.reg:
Lo segundo es meter las entradas necesarias en el registo para que la UI nos muestre las opciones deseadas al hacer clic con el botón derecho del ratón sobre un .vhd:
Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\.vhd]@="vhdfile"[HKEY_CLASSES_ROOT\vhdfile]@="Virtual Hard Disk"[HKEY_CLASSES_ROOT\vhdfile\shell]@="Mount"[HKEY_CLASSES_ROOT\vhdfile\shell\Mount][HKEY_CLASSES_ROOT\vhdfile\shell\Mount\command]@="powershell mountvhd '%1' Mount"[HKEY_CLASSES_ROOT\vhdfile\shell\UnMount][HKEY_CLASSES_ROOT\vhdfile\shell\Unmount\command]@="powershell mountvhd '%1' UnMount"[HKEY_CLASSES_ROOT\vhdfile\shell\Compact][HKEY_CLASSES_ROOT\vhdfile\shell\Compact\command]@="powershell mountvhd '%1' Compact"
Tras importar este .reg, ya tendremos las opciones Mount, Compact y UnMount disponibles en la interfaz gráfica. Dado que la opción por defecto es "Mount", eso es lo que sucederá si hacemos doble clic sobre un .vhd
Algunas consideraciones importantes:
Si tengo un rato buscaré la manera de incorporar algunas mejoras al script.
Antes de nada es importante mencionar que la única manera soportada de sacar una VM de un host de virtualización para llevarla a otro, o moverla su fichero de configuración a otra localización del sistema de almacenamiento, es mediante la funcionalidad Importar/Exportar de la consola.
Esto funciona de la siguiente manera. Cuando se crea una nueva máquina virtual se genera un fichero .xml que almacena su configuración, y que tiene por nombre un GUID que la representa de manera unívoca (así se pueden crear máquinas virtuales que tengan el mismo nombre sin que haya conflictos). Este fichero se genera en una carpeta llamada "Virtual Machines" dentro del path por defecto que hayamos configurado para ello, o bien dentro del que especifiquemos explícitamente durante la creación de la máquina virtual. Además se genera un "Simbolic Link" a dicho fichero en la carpeta %Allusersprofile%\Application Data\microsoft\Windows\Hyper-V\Virtual Machines, que es lo que realmente lee la pila de gestión de Hyper-V para mostrar dicha VM en la consola. Resumiendo:
Mencionar también que si se borra la máquina virtual desde la consola, todo lo anterior se elimina del sistema, preservándose únicamente el .vhd.
Cambiar la localización de VHD no es demasiado traumático, ya que basta con editar el fichero de configuración con la interfaz gráfica y cambiar su path. Sin embargo, si lo que queremos es que una misma VM este dada de alta en diferentes hosts, o trasladar el fichero de configuración de un path a otro, la cosa cambia. Esto no es algo que se vaya a hacer de manera frecuente, pero en entornos como el nuestro, en los que almacenamos gran parte de las máquinas virtuales en discos externos que vamos pinchando en diferentes equipos puede resultar útil. No obstante, es muy posible que tengamos que modificar posteriormente a mano algunas cosas, como la asignación de las NICs a los switches virtuales y redes definidas en el nuevo host.
Una vez explicado cómo funciona, aquí va un pequeño procedimiento para registrar/desregistrar a mano VMs en los hosts con Hyper-V, y que cada cual lo aplique como quiera. A partir de este momento entramos dentro del campo de lo no soportado.
Cómo "desregistrar" una máquina virtual
Basta con usar un script "desregistrar.cmd" que contenga:
del "%Allusersprofile%\Application Data\microsoft\Windows\Hyper-V\Virtual Machines"\%1.xml
Este script lo copiamos allí donde resida el <GUID unico>.xml, abrimos un CMD, nos situamos en ese path y lo ejecutamos pasándole como parámetro el <GUID unico> (sin el .xml):
desregistrar.cmd <GUID unico>
Cómo registrar una VM
En este caso el script "registra.cmd" será:
mklink "%Allusersprofile%\Application Data\microsoft\Windows\Hyper-V\Virtual Machines"\%1.xml "%cd%"\%1.xmlicacls "%Allusersprofile%\Application Data\microsoft\Windows\Hyper-V\Virtual Machines"\%1.xml /grant "NT VIRTUAL MACHINE\%1":F /L
Nuevamente, lo copiamos allí donde resida el <GUID unico>.xml, abrimos un CMD, nos situamos en ese path y lo ejecutamos pasándole como parámetro el <GUID unico> (sin el .xml):
registrar.cmd <GUID unico>
Con esto, creamos el enlace simbólico al .xml, y le damos permisos de control total a un SID "invisible" que representa a dicha máquina virtual. Hasta donde yo sé, éste último paso no era necesario antes de la RC0 de Hyper-V, pero ahora si no se hace la VM da un error no especificado al arrancar.
SSL se inventó para proteger el tráfico HTTP de miradas indiscretas y malintencionadas. Al igual que pasa con el cada día más utilizado SIP, no es necesario tener demasiados conocimientos ni herramientas muy complejas para saber qué información se está intercambiando simplemente echando una ojeada a las tramas en texto claro.
SSL es un ejemplo clásico de doble cifrado en el que el intercambio de la clave simétrica que se utilizará para cifrar el flujo de datos se protege a su vez con cifrado asimétrico. Aquí está muy bien explicado:
http://support.microsoft.com/kb/257591/en-us
Me ha dado por contar esto por dos razones. La primera es porque SSL es un engorro a la hora de diagnosticar problemas u obtener información acerca del intercambio de datos entre cliente y servidor, ya que el clásico método de capturar el tráfico de red es inútil al estar los datos cifrados. La segunda es porque esto que voy a contar es una de las cosas que una pieza de malware para obtener datos privados y enviarlos a aquel a quien sirve.
Por lo general esto mismo de suele hacer mediante herramientas que usan técnicas de "man in the middle", que falsean el certificado que presenta el servidor al cliente, permitiendo el descifrado y cifrado del flujo de datos en tiempo real y que permiten a la herramienta. Sin embargo, lo que hacen las herramientas que vamos a utilizar es inyectar una dll en el proceso que va a utilizar SSL, de manera que se interceptan las llamadas a EncryptMessage y DecryptMessage (secur32.dll) además de algunas otras de Windows Sockets (ws2_32.dll / wsock32.dll) y se guardan en un log. Esto permite sacar los datos de la conversación cifrada no solamente de Internet Explorer, sino de cualquier otro navegador, aplicación o servicio que usen SSL.
Estas herramientas son STRACE y HTTPREPLAY, desarrolladas por Emmanuel Boersma, y que se pueden descargar gratuitamente de la web de Microsoft. Solo están soportadas para x86 y al instalarlas simplemente se copian los ficheros necesarios en %ProgramFiles%\STRACE y %ProgramFiles%\HTTPREPLAY respectivamente. En ambos casos hay un Readme.txt con las instrucciones detalladas.
Para capturar el tráfico, hay que hacer lo siguiente (dependiendo del entorno, es posible que tengamos que usar STRACE.dll_IE6 en ligar de STRACE.dll_IE7):
Esto nos generará automáticamente un LOG en el escritorio con todo el tráfico en texto claro, bastante incómodo de interpretar. Es aquí donde entra en juego HTTPREPLAY, cuya misión es la de "recrear" el tráfico generado sin que el servidor web esté presente y sin necesidad de tener que montar uno alternativo. Aqui solamente lo vamos a utilizar para echar un vistazo al tráfico almacenado en el log de una manera más amigable:
En este ejemplo he intentado hacer login en Live.com con una cuenta de passport, obviamente falsa:
Simplemente haciendo clic sobre los métodos se ve la información completa de la traza, y lo mismo con el status para ver las respuestas. Por ejemplo, el usuario y la contraseña utilizados en el formulario están en el POST:
Por último, algunos temas relacionados con esto:
Antes de nada, hay que dejar claro que la unica manera efectiva de evitar este tipo de ataques es mediante un desarrollo adecuado de la aplicación web. Sin embargo, al margen del buen hacer de los desarrolladores, el administrador puede y debe también llevar a cabo tareas preventivas y de detección de este tipo de ataques, y configurar el sistema para minimizar su impacto lo más posible.
El principio de defensa en profundidad establece que se debe securizar de manera independiente cada una de las capas de la torre OSI, implementando las contramedidas adecuadas en cada caso. El SQL Injection, como otros ataques similares, sucede a nivel de aplicación y es ahí donde debe ser evitado. Sin embargo, una interpretación libre de ese mismo principio introduce el concepto de "sana desconfianza constructiva" entre los responsables de securizar cada una de las capas. Dicho de otra manera, no debemos contar con la efectividad de las contramedidas que serán implementadas en los niveles superior o inferior, y establecer también en el nuestro todas las que estén en nuestra mano como si la seguridad de todo el sistema dependiera única y exclusivamente de la securización de nuestra capa. Trabajando de esta manera aumenta la probabilidad de tener simultáneamente unos firewalls bien configurados, hosts con el SO y los servicios fortificados, bases de datos bien diseñadas desde el punto de vista de la seguridad, y desarrollos web seguros.
Lo que vamos a utilizar es la funcionalidad de Request Filtering de IIS7 (equivalente a URLScan en IIS6) junto con la herramienta LogParser 2.2. La idea es ser capaces de identificar cuales son las longitudes máximas de URL y consultas que un site/aplicación va a utilizar de manera legítima, y evitar que el servidor web sirva nada que supere esas longitudes. Esto tiene además como efecto colateral que en los casos en que eso suceda, se producirán errores http específicos, que podremos trazar y que se pueden utilizar como un método de detección de intentos de intrusión.
Lo que propongo aquí es una metodología de trabajo sencilla, que luego cada cual puede complicar o refinar lo que quiera. Parto de la base de que existen tres entornos completamente diferentes:
Una vez se ha terminado el desarrollo de la aplicación, se pasa al entorno de preproducción donde se realizará toda la batería de pruebas necesarias para comprobar que cada una de sus características funcionarán correctamente en el entorno de producción. Para el caso que nos ocupa, es importante que dichas pruebas funcionales contemplen la totalidad de las consultas que la aplicación puede llegar a hacer a las bases de datos. La idea es utilizar posteriormente los logs de IIS en busca de los datos que necesitamos para configurar el servidor web de manera que no sirva URLs o consultas de mayor longitud.
Insisto en que esta metodología no es la panacea universal, y esa es la razón por la que titulo el post "minimizando" y no "evitando".
Request Filtering
En la versión de IIS7 incluida en la RTM de Windows Server 2008, la configuración del Request Filtering se lleva a cabo directamente sobre el fichero web.config a nivel de site, aplicación, o carpeta, ya que no existe interfaz gráfica para hacerlo (la sintaxis esta documentada aqui). Por fortuna, al instalar el IIS7 Administration Pack Technical Preview esta carencia se resuelve y podemos configurar cómodamente con el IIS Manager las extensiones de ficheros que no serviremos, los verbos HTTP permitidos, las secuencias de URL denegadas, los segmentos ocultos y las longitudes de determinadas cabeceras.
En nuestro caso estamos interesados en encontrar los valores adecuados para la "Maximum URL lenght" y Maximum query string", aunque es muy posible que queramos afinar también el resto de opciones. Para evitar este tipo de ataques, es frecuente encontrar diccionarios de palabras en la lista de secuencias de URL denegadas, que contemplan la mayor parte de los comandos SQL que se suelen utilizar para construir las sentencias de las consultas.
Formato de los logs de IIS
Por defecto IIS7 guarda sus logs en formato W3C, y podemos elegir qué información queremos almacenar en ellos:
Los campos del log que nos interesan a nosotros son el URI Stem (cs-uri-stem) y el URI Query (cs-uri-query) del log de IIS que corresponda a la fecha en la que se han realizado las pruebas funcionales de la aplicación.
LogParser 2.2
Como dice en su sitio de descarga, esta es una herramienta muy potente que da acceso universal a datos almacenados en ficheros de texto con diferentes formados (CSV, XML, Logs) y a fuentes de datos del sistema operativo como los logs de eventos, el registro, el sistema de archivos o el directorio activo. Lo curioso es que accedemos a ellos como si estuviésemos haciendo consultas a una base de datos, independientemente de cual sea su origen, y podemos presentar los resultados de diferentes maneras. Lógicamente, utilizarla no es precisamente trivial. De hecho en el IIS7 Administration Pack Technical Preview se ha incluido una nueva funcionalidad, "IIS Logs", basada en algunas de las cosas que se suele hacer con esta herramienta.
LogParser se suele utilizar en ocasiones como herramienta de análisis forense en IIS. En este artículo de Securityfocus se explica cómo hacerlo, y de hecho basta retocar un poco alguna de las consultas que aparecen citadas en él para obtener la información que andamos buscando:
Para sacar la máxima longitud de URL, asi como el número de veces en los que cada URL se ha solicitado:
logparser "SELECT cs-uri-stem, Count(*) As Total, STRLEN(cs-uri-stem) as Longitud FROM C:\inetpub\logs\LogFiles\W3SVC2\u_ex080403.log GROUP BY cs-uri-stem ORDER BY Longitud DESC" -rtp:100
y para la máxima longitud de query, asi como el número de veces que se ha realizado cada consulta:
logparser "SELECT cs-uri-query, Count(*) As Total, STRLEN(cs-uri-query) as Longitud FROM C:\inetpub\logs\LogFiles\W3SVC2\u_ex080403.log GROUP BY cs-uri-query ORDER BY Longitud DESC" -rtp:100
Lo único que hay que variar en los comandos es el path al log que nos interesa. Un ejemplo de los resultados que se obtienen son los siguientes (he utilizado un site con Mediawiki al que he hecho un par de consultas rápidas)
Según esto los datos que tendríamos que utilizar serían 50 para la URL y 84 para la query (no pongáis esto para mediawiki, que os la cargáis seguro), con lo que el fichero web.config quedaría, al margen de las otras opciones de filtrado que queramos introducir:
<configuration> <system.webServer> <security> <requestFiltering> <requestLimits maxAllowedContentLength="30000000" maxUrl="30" maxQueryString="25" /> </requestFiltering> </security> </system.webServer></configuration>
<configuration> <system.webServer> <security> <requestFiltering>
<requestLimits maxAllowedContentLength="30000000" maxUrl="30" maxQueryString="25" />
</requestFiltering> </security> </system.webServer></configuration>
Comprobando si el filtrado esta sirviéndonos o no
Como decía más arriba, el filtrado nos va a dejar errores HTTP personalizados, en particular el 404.14 para las URLs y el 404.15 para las consultas (ver la tabla del final del ya citado How to Use Request Filtering). Nuevamente podemos usar LogParser para buscar en todos los logs ocurrencias de dichos errores y poderlos analizar con detalle para ver si son intentos de ataque o falsos positivos:
logparser "SELECT sc-status, sc-substatus, cs-uri-stem, cs-uri-query, Count(*) As Total FROM C:\inetpub\logs\LogFiles\W3SVC2\u_ex*.log WHERE sc-status='404' and (sc-substatus='14' or sc-substatus='15') GROUP BY sc-status, sc-substatus, cs-uri-stem, cs-uri-query ORDER BY sc-substatus DESC" -rtp:100
Seguramente hay otros muchos métodos, herramientas, etc. pero esto lo usé para preparar una demo de seguridad en IIS7, y al menos quería dejarlo documentado.
Muchas gracias a Maligno por haber inspirado este post con sus comillas y sus asteriscos, y a Nacho Alonso por echarme una mano con las queries SQL, como ha hecho siempre con otras muchas cosas (este tipo es de los que si que saben, y mucho, y además lo saben contar).
Esta es una vieja pregunta, que reaparece de vez en cuando. Esta vez, viene por correo de parte de Daniel
Se pretende que uno, un grupo, o todos los usuarios de un dominio no puedan iniciar sesión en él más que una vez de manera concurrente, es decir, desde varios equipos a la vez.
Implementar esto tanto en el lado del servidor como en el del cliente puede parecer sobre el papel una cosa sencilla. Un atributo asociado al objeto del usuario que llevara la cuenta de los inicios y cierres de sesión del usuario y una política que lo leyera y que especificara un cierto umbral. Sin embargo esto sería complicado hacerlo funcionar de manera correcta en un entorno mediano o grande, porque nos encontraríamos con algo similar al clásico problema de la sincronización de cambios de contraseñas, GPOs, etc. entre los diferentes controladores de dominio (os recomiendo leer los apartados "Urgent Replication" y "Replication of password changes" del artículo "How the Active Directory Replication Model Works"). Un usuario podría iniciar sesión desde dos sitios distintos si es autenticado por dos DCs diferentes que todavía no hubieran replicado la información almacenada en ese hipotético atributo. Por tanto, hay que hacer algo para centralizar esa información, cosa que va un poco en contra de la filosofía de entorno distribuido de Directorio Activo.
Estas soluciones pueden funcionar bien, sobre todo en entornos con pocos DCs
1.- Usar una carpeta de red compartida y un login script. La idea es crearle a cada usuario una carpeta compartida, limitada a una única conexión concurrente, y hacer un "net use" a ella en el login script. Si el usuario inicia sesión una segunda vez, el comando fallará, se captura el error, y se fuerza un logoff. Todo esto se detalla aquí:
How to Use a Network Share to Limit a User's Concurrent Connections in Windows 2000
2.- Utilizar la herramienta Cconnect.exe del Kit de Recursos de Windows 2000. Sustituye al script en el lado cliente y en lugar de la carpeta compartida de red se utiliza una base de datos SQL. Es menos cutre que lo anterior, pero más complicado y un pelín obsoleto.
Limiting a user's concurrent connections in Windows Server 2003, Windows 2000, and Windows NT 4.0
3.- Puestos a ensuciarse las manos, la mejor solución es usar LimitLogin.exe, que utiliza scripts de inicio y cierre de sesión en VBS, un servicio Web que se encarga de recibir la información y de leerla y almacenarla en una partición de datos del Directorio Activo. Esta es la arquitectura, sacada del artículo "Utility Spotlight Limit Login Attempts With LimitLogin" publicado en la TechNet Magazine
Si a alguien se le ocurre alguna otra cosa, cualquier idea es bienvenida
Estos de M$, siempre con lo mismo...
http://www.aeat.es/AEAT/Contenidos_Comunes/La_Agencia_Tributaria/Descarga_Programas/Descarga/100/2007/v.1.00/Descarga_unica/s1007100.exe
Por seguir una vieja tradición, pero renovando los medios.
El próximo 16 de abril, en nuestras oficinas de Pozuelo de Alarcón (Madrid) hay un evento en el que Rafal Lukawiecky hablará sobre Datamining en un evento titulado Aprenda a que el Data Mining se ponga a su servicio
Rafal Lukawiecky es un excelente ponente con un estilo de presentación francamente peculiar, y además de un excelente dominio de los temas que trata. Trabaja para Project Botticelli Ltd y es ponente habitual en el TechEd en en el IT Forum. De verdad que merece la pena verle y escucharle. Esta es la agenda del evento:
09:30 Registro10:00 Inauguración e introducción(20 min)10:20 Introducción al Data Mining(80 min)11:40 Coffe break(20 min)12:00 Cómo trabajar con el Data Mining(75 min)13:15 Uso del Data Mining en tus sistemas de TI (Parte 1)(75 min)14:30 Comida(60 min)15:30 Uso del Data Mining en tus sistemas de TI (Parte 2) (60 min)16:30 Sesión de preguntas y respuestas (30 min)
El evento es en inglés pero hay servicios de traducción. Os podéis registrar gratuitamente aqui:
Nos vemos alli. Saludos
He decidido volver a montar la demo de System Center Essentials que llevamos al TechNet Technology Tour sobre una máquina virtual con Windows Server 2008 x64, de cara a una webcast que haremos próximamente sobre este producto.
System Center Essentials 2007 Service Pack 1 se puede instalar ya sobre Windows Server 2008, tanto en x86 como en x64. La instalación es francamente sencilla, salvo por un detalle que me ha tenido atascado unas cuantas horas.
El problema es la instalación y configuración de los Reporting Services de SQL Server 2005 SP2 sobre Windows Server 2008. Tras haber instalado los prerequisitos del sistema operativo en Windows Server 2008 (el Framework 3.0 e IIS7 con todas las opciones de compatibilidad de IIS6) y SQL Server 2005 Enterprise x64 con SP2 (vale el Express SP2), el asistente de instalación fallaba al comprobar la instancia de los Reporting Services, incluso después de haberla configurado mediante su herramienta de configuración. En el log aparece como causa un error 401.3 muy feo cuando se intenta acceder al servicio web "ReportsServer". El error se pone patente explorando directamente los directorios virtuales "Reports" y "ReportServer" desde la consola de IIS
La solución esta aqui, justo al final del artículo
938245 How to install and how to configure SQL Server 2005 Reporting Services on a computer that is running Windows Server 2008http://support.microsoft.com/default.aspx?scid=kb;EN-US;938245
Una vez resuelto este problema, puede salir un acceso denegado, también al intentar acceder los Reporting Services. Se resuelve asignando permisos de lectura y ejecución a "Network Service" y a la cuenta de servicios de SQL en las carpetas "ReportManager" and "ReportServer" que se encuentran en la carpeta MSSQL.* corresponda a su instancia (por ejemplo, “%ProgramFiles%\Microsoft SQL Server\MSSQL\Reporting Services)
Escribo esto porque seguro que tendré que volverlo a montar, y pasado mañana se me habrá olvidado. Espero tambien que le ayude a alguién.
Esto suele ser un problema común en escenarios de virtualización, en la que las NICs cambian frecuentemente, o de entornos en los que se mueven instalaciones del sistema operativo a hardware "casi" idéntico. Por lo general, lo que el usuario nota en estos casos es que su "Local Area Connection" desaparece creándose en su lugar la "Local Area Connection X" donde X va creciendo en número
Método 1 (elegante y soportado por KB269155)
Método 2 (a puñete y a lo bruto, para muy frikis, no recomendado, no soportado, y expuesto aqui por cuestiones meramente informativas o por si un Server Core se cruza en tu camino)
Una vez hecho esto, ya podemos renombrar nuestra conexión de red con el nombre que queramos y ponerle la vieja IP sin que nos salga el cuadro de diálogo de advertencia de dirección duplicada.
Con esto de la aprobación de OpenXML como nuevo estandar ISO (ISO/IEC29500) se ha vuelto a generar un revuelo en la blogosfera similar al que acontece cada vez que Microsoft lanza algun producto destinado al mercado de consumo, como una versión de Windows u Office. Revuelo en el que, como sucede desde que al género "homo" le da por hacer algun tipo de avance tecnológico (nótese que digo avance tecnológico y no descubrimiento ciéntífico), cada cual participa según lo que se juegue en la película. Desgraciadamente en la era de Internet esto sucede de manera extraordinaria, tanto en la cantidad de jugadores involucrados como en el tiempo en el que ocurre. Y digo desgraciadamente porque esto produce a nuestro alrededor un buen número de árboles gordos convenientemente colocados que te impiden ver el bosque, con el peligro de estarte privando de manera inconsciente de la posibilidad de tener un criterio propio.
Esta mañana me he puesto tranquilamente a currar en mi rinconcillo y me he metido mi dosis diaria de Joaquin Sabina. Y no he podido evitar acordarme al escuchar estas viejas estrofas de todos esos bloggers y agoreros digitales que engordan sus fama y sus bolsillos "creando opinión" según ellos creen que van a tener mayor "impacto" o indice de audiencia:
Un díalos enanos se rebelaráncontra Gulliver.Todos los hombres de corazón diminutoarmados con palos y con hocesasaltarán al único gigantecon sus pequeños rencores, con su bilis,con su rabia de enanos afeitados y miopes.Pobre de tí, Gulliver, pobre de tí,el día que todos los enanosunan sus herramientas y su odio,sus costumbres, sus vicios, sus carteras,sus horarios. No podrán, no podrán,no podrán perdonarte que seas alto.Para ellos la generosidad no es más que un lujo que no pueden pagarse,viven alimentados por la envidia que los habita en forma de costumbre.Míralos revolverse recelosos tras sus gafas de concha.Te acusarán, te acusarán, te acusarán:de ser el tuerto en el país de los ciegos,de ser quien habla en el país de los mudos,de ser el loco en el país de los cuerdos,de andar en el país de los cansados,de ser sabio en el país de los necios,de ser malo en el país de los buenos,de divertirte en el país de los serios,de estar libre en el país de los presos,de estar vivo en el país de los enanos,de ser la voz que clama en el desierto,de ser la voz que clama en el desierto
Título: GulliverAño: 1980Letra: Joaquín SabinaMúsica: Joaquín SabinaDisco: Malas Compañías (1980)
Ahora suena "Yo, mi, me contigo". No seas enano. Piensa por ti mismo.
Esta es la presentación de la sesión de seguridad en IIS7 del Asegura@IT II que se está celebrando hoy en Barcelona:
En otro post os pondré algo más de información acerca de alguna de las demos que voy a hacer. Mientras tanto, en IIS.net hay algunas descargas indispensables para la versión final de IIS7 incluida en la RTM de Windows Server 2008.
Hoy Jose estaba liado preparando esta webcast para mañana. Os podéis apuntar aqui:
Webcast TechNet: Novedades de Windows Vista con SP1 (Wed, 02 Apr 2008 15:00:00 GMT)
para ver el evento grabado bajo demanda, esta será la URL donde registrarse una vez terminada la difusion en directo