De cómo protegerse contra Cryptolocker y demás ransomware - Parte 2

Hace unos días el DHS americano y el CCIRC canadiense emitieron una alerta ante la proliferación del ransomware, con el objetivo de que las personas y las empresas sean conscientes del riesgo que implica este tipo de malware.
En las últimas semanas ha estado especialmente activo Locky con varias variantes y campañas que han conseguido un gran número de infecciones.
Además los ataques son cada vez más dirigidos y ya hay ransomware como Samsam que se aprovecha de vulnerabilidades en servidores Jboss mediante Jexboss para afectar específicamente a empresas. Como podéis ver, con todo este panorama es capital emprender acciones defensivas contra este tipo de malware.

 
En la primera parte de esta serie, hablábamos que para protegerse del ransomware lo mejor era, a parte del sentido común, hacer regularmente backup y guardarlo de forma offline o al menos no directamente accesible por el equipo que pudiera infectarse. También hablamos de crear un fichero trampa, en adelante canary file, y monitorizarlo continuamente para disparar alguna acción para impedir que el ransomware siga cifrando archivos, por ejemplo desmontando un volumen de VeraCrypt (un fork de Truecrypt).

Más sobre "Canary files"

Recientemente en el blog de Free Forencics también vimos varios métodos interesantes usando canary files.

Por ejemplo, el siguiente script en Powershell crea un canary file, activa la monitorización del fichero para detectar intentos de escritura (LastWrite) y si detecta algún cambio desconecta automáticamente la unidad de red y envía un coreo un correo:
$DirPath = "C:\Temp\"
$FName = "Redemptio*.docx"
$FilePath = Join-Path -Path $Dirpath -ChildPath $FName

function DriveUnMapper {
$MappedDrives = Get-WmiObject -Class Win32_MappedLogicalDisk
ForEach($Drive in $MappedDrives){
net use $Drive.name /delete
  }
}

function CreateWatcher {
$global:FSWatcherObj = New-Object IO.FileSystemWatcher $DirPath, $FName -Property @{
IncludeSubdirectories = $false;
EnableRaisingEvents = $true;
NotifyFilter = [IO.NotifyFilters]'LastWrite'
  }
} 
function RegisterWatcher {
Register-ObjectEvent $FSWatcherObj Changed -SourceIdentifier FileChanged -Action {
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
Write-Host "The file '$name' was $changeType at $timeStamp" -fore red
$logdata = "$(Get-Date), $changeType, $FilePath, was altered! Disconnecting Drives"
Add-content "C:\Users\user\Desktop\Redemptio.bla" -value $logdata
$smtp = New-Object Net.Mail.SmtpClient("smtp.yoursite.notreal")
$smtp.Send("SecurityNerds@yoursite.notreal","Management@yoursite.notreal","Ransomware File Canary has been written to on " + $env:computername,"Information on the Event:" + $logdata + "Disconnecting network drives.")
DriveUnMapper
  }
} 
function CreateCanary {
New-Item C:\Temp\Redemptio-canary.docx -ItemType File -value "Redemptio canary file - do not write to file"
}
CreateCanary
CreateWatcher
RegisterWatcher

Lo malo del script anterior es que no está deteniendo en sí mismo el proceso del malware, sólo cerrando "puertas" para que no cifre algunos archivos. Por eso es buena idea matar el proceso malicioso en el mismo momento que intenta escribir el canary file. El siguiente ejemplo en C# ilustra la forma de realizarlo en conjunción con la auditoría de objetos y reglas (monitorizando los eventos de seguridad):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading; 
class Redemptio
{
   static AutoResetEvent signal;
   public static void Main()
       public static void Main()
    {
        signal = new AutoResetEvent(false);
        EventLog myNewLog = new EventLog("Security", ".", "Microsoft Windows security auditing.");
        myNewLog.EntryWritten += new EntryWrittenEventHandler(MyOnEntryWritten);
        myNewLog.EnableRaisingEvents = true;
        signal.WaitOne();

    }
 
    public static void MyOnEntryWritten(object source, EntryWrittenEventArgs e)
    {
        string proc = "spiderham";
        string src = "Microsoft-Windows-Security-Auditing";
        bool a = e.Entry.Source.Contains(src);
        bool b = e.Entry.Message.Contains(proc);
        if ((a) && (b))
        {
            Console.WriteLine("Current message entry is: '"
   + e.Entry.MachineName + e.Entry.TimeWritten + e.Entry.Source + e.Entry.Data[0] + "'");
   string str1 = "Process ID:";
   string str2 = "Process Name:";
   int startindex = e.Entry.Message.IndexOf(str1);
   int endindex = e.Entry.Message.LastIndexOf(str2);
   int length = endindex - startindex;
   string fullLine = e.Entry.Message.Substring(startindex, length).Replace(" ", string.Empty);
   Console.WriteLine(fullLine);
   string[] result;
   result = fullLine.Split();
   Console.WriteLine(result[0]);
   Console.WriteLine(result[1]);
   Console.WriteLine(result[2]);
   string strpid = Convert.ToString(result[2]).Remove(0, 2);
   int pid = Convert.ToInt32(strpid, 16);
   Console.WriteLine("Killing Process ID: " + pid);
   Process evilproc = Process.GetProcessById(pid);
   Thread.Sleep(5000);
   evilproc.Kill();
   Console.WriteLine("Process ID: " + pid + " killed.");
        }
    }
}

Mediante el siguiente ejemplo (volvemos a powershell) podemos instalar las reglas para un directorio entero (canary directory) y todos los archivos contenidos en esta carpeta:

$AuditUser = "Everyone"
$AuditRules = "WriteData"
$InheritType = "ContainerInherit,ObjectInherit"
$AuditType = "Success"
$AccessRule = New-Object System.Security.AccessControl.FileSystemAuditRule(
    $AuditUser,
    $AuditRules,
    "None",
    "None",
    $AuditType
    )

$HoneyPot = Get-ChildItem 'C:\$'
ForEach($FileCanary in $HoneyPot){
$ACL = Get-Acl $FileCanary.FullName
$ACL.SetAuditRule($AccessRule),$FileCanary.FullName
$ACL | Set-Acl $FileCanary.FullName
}

Todo lo que hemos visto hasta ahora es crear ficheros y directorios trampas (los llamados honey o canary files & directories) para alertar, desmontar unidades o matar procesos. El problema es que, dependiendo dónde los situemos y cuál sea el orden que sigue el malware para listar y cifrar los archivos podemos encontrarnos que cuando queramos reaccionar ya habremos perdido un número considerable de ficheros...


Recursive loops

Existe otro método para ralentizar el ransomware y así tener una mayor capacidad de reacción. Se trata de crear bucles recursivos a nivel de directorios para que el proceso no salga o al menos esté un buen tiempo "entretenido" en ese agujero. Por eso a esta técnica también se le llama "ransomware sinkholing".

Puede hacerse fácilmente mediante NTFS junctions o uniones NTFS, el equivalente a un enlace simbólico de Unix en Windows. Por ejemplo os sonará desde Vista la típica unión NTFS desde C:\Documents and Settings a C:\Users para legacy software. No debe confundirse con el clásico acceso directo .lnk de Windows. Como reza la Wiki "El acceso directo nos envía al directorio de destino mientras que el enlace simbólico nos muestra el contenido del directorio de destino como si estuvieran en este...".

La forma de hacer el bucle con ésto es crear un "NTFS junction" a un directorio que actúa como un alias de ese directorio.


Por ejemplo creamos el directorio "!" con el canary file "prueba.txt" y luego la unión "$" apuntando al mismo directorio. Al ejecutar un dir el fichero de prueba aparecerá listado 32 veces, podéis comprobarlo vosotros mismos:


Esto es debido a que, para evitar desbordamientos de buffer, tanto el símbolo del sistema como el explorador de Windows detienen su recursividad cuando la profundidad de directorio alcanza 32 o la ruta de acceso supera los 256 caracteres, lo que ocurra primero.

Pero, ¿qué pasa si creamos otra unión en el mismo directorio simplemente añadiendo un carácter adicional?

D:\laboratorio>mklink /J $$ d:\laboratorio\
Unión creada para $$ <<===>> d:\laboratorio\



Como veis el crecimiento es exponencial, es decir, 2^32 que serían 4.294.967.296 instancias del fichero prueba.txt. Evidentemente si el proceso de cifrado del ransomware entra en este sinkhole es probable que no pueda salir. Incluso podríamos configurar un trigger para que nos avisara si se detecta el uso elevado de la CPU durante un intervalo prolongado de tiempo. Siguiendo con Powershell:


$cpuutil=(get-counter -Counter "\Processor(_Total)\% Processor Time" -SampleInterval 1 -MaxSamples 5 |
    select -ExpandProperty countersamples | select -ExpandProperty cookedvalue | Measure-Object -Average).average

If ($cpuutil -ge 90)
{Restart-Service MyService1, "My Service2", MyService3}
Else
{Exit}
 
No obstante, tener en cuenta que si se utilizan estos bucles recursivos es necesario excluir los directorios del indexado de Windows y del análisis del antivirus, o ignorar los objetos con el flag "Reparse Point". En cualquier caso es conveniente implementarlo en un entorno de pruebas primero.

Cryptostalker

Sean Williams, un desarrollador de San Francisco, creó un proyecto muy interesante llamado
randumb que contenía un ejemplo al que bautizó como Cryptostalker y que, básicamente, monitoriza la creación o escritura de archivos en el sistema con datos aleatorios por medio de un análisis mediante frecuencia y asimetría (histograma). Si los archivos contienen datos aleatorios puede ser una señal de la actividad de un proceso de cifrado de un ransomware, por lo que la herramienta es ideal para alertar al usuario de forma temprana.

Además recientemente ha sido portado a Go sustituyendo inotify por fsnotify de Google para las notificaciones. Funciona perfectamente en Linux y OSX aunque está pendiente probarlo más en Windows. Su nuevo repositorio es:

https://github.com/unixist/cryptostalker

Referencias:
- Estados Unidos y Canadá emiten alerta por el ransomware
- El ransomware Locky y su gran número de variantes
- Los hackers afinan sus ataques ransomware dirigiéndolos a servidores
- De cómo protegerse contra Cryptolocker y demás ransomware
- Proactively Reacting to Ransomware
- A Deeper Explanation of How Ransomware Sinkholes Work
- Junction NTFS
- NTFS reparse point
- Researcher Creates Tool that Can Help Detect Crypto-Ransomware
- Cryptostalker example

Comentarios