jueves, 5 de marzo de 2015

Clonar una máquina virtual en Vmware por Powercli-tarea programada, borrar la original y arrancar la copiada. Perfecta para Honeypot.

Estimados amigos de Inseguros.

En el episodio de hoy vamos a trabajar un poco con Powercli, el interface de comandos para manejar sistemas VMWare integrado en Powershell. Es decir, podemos ejecutarlo desde un sistema Windows, por ejemplo, una tarea programada.


En esta web hemos hablado muchas de sistemas Honeypots, sistemas "virtuales" que permiten obtener información de ataques, despistar atacantes y demás gestiones.

Uno de los retos es mantener el Honeypot seguro. Imagina que tienes una máquina virtual con Honeyd o cualquier otro Honeypot expuesto a Internet para recolectar tráfico. Imagina que por cualquier casualidad el atacante detecta el servicio Honeypot y desiste en explotar el servicio "honey" que le ofrecemos, y decide atacar el sistema Honeypot real, y lo consigue !!!

Vamos a imaginar otro escenario, un web server sin base de datos, que se conecta a una externa, y que queremos "restaurar" a su estado inicial, para prevenir el acceso en el caso de haber sido comprometido. Esta claro que no vamos a solucionar el origen de la vulnerabilidad, pero podemos dejar el sistema como al inicio,por ejemplo, todas las noches.

La cuestión es:
Apagar clonada
Borrar clonada
Plantilla->Clonar> Encender clonada

Lo primero que vamos a hacer es instalar Powercli en un sistema Windows, en mi caso, un server.

Una vez ejecutado el instalador, sin ninguna opción, creamos un fichero PS1 que contendrá la función de copia, y la llamada a nuestro servidor Esxi para ejecutarlo con nuestros parámetros. Tengo que hacer énfasis en que esta solución es válida para equipos gratuitos, sin Vcenter. Powercli tiene un comando directo Clone para realizar esta función, pero no siempre tenemos una versión de pago Vcenter.

Hay que tener en cuenta que la máquina debe estar apagada. Es el precio que tenemos que pagar por usar la versión gratuita. Para este enfoque, nos es válido ya que usaremos siempre una máquina virtual apagada como "maestra", como plantilla.

El script original es del señor Luc Dekens. En negrita resaltaré las partes mias.


add-pssnapin VMware.VimAutomation.Core #para poder ejecutar powercli con un doble click, o una tarea programada.
function Clone-MasterVM {
<# 
.SYNOPSIS  Clone a VM without using vCenter  
.DESCRIPTION The function will clone a VM to a
  specified datastore. Optionally the new VM will be
  registered and powered on.
.NOTES  Author:  Luc Dekens 
.PARAMETER MasterName
  The name of the VM that will be cloned
.PARAMETER CloneName
  The name of the VM that is cloned
.PARAMETER DatastoreName
  The name of the datastore where the clone will be
  stored
.PARAMETER Register
  Register the clone on the vSphere server
.PARAMETER PowerOn
  Power on the clone. Can only be used when the Register
  switch is selected.
.EXAMPLE
  PS> Clone-MasterVM -MasterName M1 -CloneName Srv1 -DatastoreName DS1
#>

  param(
  [string]$MasterName,
  [string]$CloneName,
  [string]$DatastoreName,
  [switch]$Register,
  [switch]$PowerOn
  )
   
  $vm = Get-VM -Name $MasterName
  if($vm.ExtensionData.Snapshot -or $vm.PowerState -eq "PoweredOn"){
    Write-Error "The VM should be powered off and have no snapshots"
    return
  }
   
  $si = Get-View ServiceInstance
  $vdkMgr = Get-View $si.Content.virtualDiskManager
  $fileMgr = Get-View $si.Content.FileManager
   
  $dcMoRef = (Get-Datacenter -VM $vm).ExtensionData.MoRef
  $srcDSName = $vm.ExtensionData.Config.Files.VmPathName.Split(']')[0].Trim('[')
  $srcDS = Get-Datastore -Name $srcDSName
  $srcDSBrowser = Get-View $srcDS.ExtensionData.Browser
  $tgtDS = Get-Datastore -Name $DatastoreName
  $spec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
   
  # Create folder for new VM
  $fileMgr.MakeDirectory("[$DatastoreName] $CloneName",$dcMoRef,$false)

  # Copy vDisks
  $spec.Query = New-Object VMware.Vim.VmDiskFileQuery
  $qResult = $srcDSBrowser.SearchDatastore("[$srcDSName] $MasterName",$spec)
  if($qResult.File){
    $qResult.File | %{
      $srcPath = "$($qResult.FolderPath)/$($_.Path)"
      $tgtPath = $srcPath.Replace($srcDSName,$DatastoreName).Replace($MasterName,$CloneName)
      $hd = $vm.ExtensionData.Config.Hardware.Device |
        where {$_ -is [VMware.Vim.VirtualDisk] -and $_.Backing.FileName -eq $srcPath}
      $controller = $vm.ExtensionData.Config.Hardware.Device |
        where {$_.Key -eq $hd.ControllerKey}
      $vDiskSpec = New-Object VMware.Vim.VirtualDiskSpec
      $vDiskSpec.adapterType = &{
        if($controller -is [VMware.Vim.VirtualLsiLogicController] -or
          $controller -is [VMware.Vim.VirtualLsiLogicSASController] -or
          $controller -is [VMware.Vim.ParaVirtualSCSIController]){
          [VMware.Vim.VirtualDiskAdapterType]::lsiLogic
        }
        elseif($controller -is [VMware.Vim.VirtualBusLogicController]){
          [VMware.Vim.VirtualDiskAdapterType]::busLogic
        }
        else{
          [VMware.Vim.VirtualDiskAdapterType]::ide
        }
      }
      $vDiskSpec.diskType = &{
        if($hd.Backing.eagerlyScrub){[VMware.Vim.VirtualDiskType]::eagerZeroedThick}
        elseif($hd.Backing.thinProvisioned){[VMware.Vim.VirtualDiskType]::thin}
        else{[VMware.Vim.VirtualDiskType]::thick}}
      $vdkMgr.CopyVirtualDisk($srcPath,$dcMoRef,$tgtPath,$dcMoRef,$vDiskSpec,$null)
    }
  }

  # Copy other VM files
  $dsDestination = New-PSDrive -Location $tgtDS -Name dest -PSProvider VimDatastore -Root '\'
  Get-ChildItem -Path "vmstore:\ha-datacenter\$srcDSName\$MasterName" |
  where {"vmdk","log","vmsd" -notcontains $_.Name.Split('.')[1]} | %{
  # The copy is done in a foreach loop, to bypass a Copy-DatastoreItem bug with pipeline
  Copy-DatastoreItem -Item $_ `
     -Destination ("dest:\$CloneName\" + $_.Name.Replace($MasterName,$CloneName)) -Confirm:$false
  }

  # Update VMX file
  Copy-DatastoreItem -Item "dest:\$CloneName\$($CloneName).vmx" -Destination $env:Temp\t.vmx
  $text = Get-Content -Path $env:Temp\t.vmx | %{$_.Replace($MasterName,$CloneName)}
  $text | Set-Content -Path $env:Temp\t.vmx
  Copy-DatastoreItem -Item $env:Temp\t.vmx -Destination "dest:\$CloneName\$($CloneName).vmx" -Confirm:$false

  # Update VMXF file
  Copy-DatastoreItem -Item "dest:\$CloneName\$($CloneName).vmxf" -Destination $env:Temp\t.vmxf
  $text = Get-Content -Path $env:Temp\t.vmxf | %{$_.Replace($MasterName,$CloneName)}
  $text | Set-Content -Path $env:Temp\t.vmxf
  Copy-DatastoreItem -Item $env:Temp\t.vmxf -Destination "dest:\$CloneName\$($CloneName).vmxf" -Confirm:$false
   
  if($Register){
    New-VM -VMFilePath "[$DatastoreName] $CloneName\$($CloneName).vmx" | Out-Null
    if($PowerOn){
      Start-VM -VM $CloneName -ErrorAction SilentlyContinue
      Get-VMQuestion -VM $CloneName | Set-VMQuestion -DefaultOption -Confirm:$false
    }
  }

  Remove-PSDrive -Name dest -Confirm:$false
}
Connect-VIServer -Server ip-server-esxi -User usuario -Password contraseña
Stop-VM -VM "nombre de la clonada" -Kill -Confirm:$false
Remove-VM "nombre de la clonada" -DeletePermanently -Confirm:$false
Clone-MasterVM -MasterName "nombre de la original"  -CloneName "nombre de la clonada" -DatastoreName "nombre del datastore" -Register -PowerON

Empezamos a ver la copia del fichero del disco duro en el Esxi.


Para realizar la tarea programada realizamos los pasos normales de programación y seguridad pero indicamos que ejecute: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe   y usamos como parámetro de ejecución -psc “C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\vim.psc1″ -noe -c “.\”C:\clone.ps1\””

Espero que os haya gustado el artículo, tanto si piensas implementar algo parecido para tus honeypots, o simplemente para presentarte y animarte a usar Powercli para tus operaciones con Vmware sin necesidad de Vcenter o componentes de terceros.

Gracias por leerme !!!