Zone.Identifier y ADS en Windows: por qué el mismo SHA-256 no siempre significa la misma evidencia

Este fin de semana he estado investigando sobre Zone.Identifier, uno de los flujos alternativos (lo que conocemos como ADS - Alternate Data Stream) de NTFS más habituales en una investigación de archivos descargados. La idea parecía sencilla: crear un archivo, modificar su Zone.Identifier y comprobar qué ocurría con el hash.


Pero al reproducirlo surgió una pregunta bastante razonable: si el flujo alternativo está asociado al archivo, ¿por qué puedo modificarlo sin cambiar el SHA-256 del fichero?

La respuesta merece un artículo propio, porque afecta tanto a cómo adquirimos evidencias como a lo que podemos afirmar después en un informe forense. Vamos a verlo desde el principio, con un laboratorio sintético y, esta vez, con resultados obtenidos en Windows 11.

1. Antes de hablar de MOTW (Mark of the Web): ¿qué estamos llamando «archivo»?

En NTFS, el contenido que normalmente abrimos al hacer doble clic en un fichero reside en un flujo de datos sin nombre (unnamed data stream). También se conoce como flujo principal y se representa como ::$DATA.

Pero NTFS permite que ese mismo archivo tenga otros flujos de datos con nombre, los Alternate Data Streams o ADS. Por ejemplo:

muestra.txt Flujo principal (::$DATA)
muestra.txt:Zone.Identifier ADS (:Zone.Identifier:$DATA)

No son dos archivos independientes que casualmente se llaman parecido. Son dos flujos de datos asociados a una misma entrada de archivo NTFS. Cada flujo tiene su propio contenido y tamaño. Microsoft documenta que no poseen marcas temporales independientes: las fechas pertenecen al archivo y pueden verse afectadas por operaciones sobre cualquiera de sus flujos.

Esto también aclara una confusión frecuente: cuando calculamos el SHA-256 de muestra.txt con Get-FileHash, estamos calculando el hash de los bytes que devuelve la lectura normal del archivo, es decir, del flujo principal. No estamos obteniendo automáticamente un hash de todos sus ADS, atributos NTFS o metadatos.

No hay ningún problema con SHA-256: simplemente estamos hasheando menos información de la que a veces creemos.

2. ¿Qué guarda Zone.Identifier?

Zone.Identifier es un ADS utilizado por aplicaciones compatibles con los mecanismos de zonas de seguridad de Windows. Suele asociarse al Mark of the Web (MOTW), que puede influir en las advertencias y restricciones aplicadas al abrir ciertos contenidos.

Puede tener una estructura parecida a esta:

[ZoneTransfer]
ZoneId=3
HostUrl=https://example.invalid/primera-version.txt

Este ejemplo no representa una descarga. Lo vamos a crear manualmente con PowerShell para comprobar cómo se comporta NTFS.

El valor ZoneId=3 corresponde a la zona de Internet. En determinadas circunstancias también encontraremos campos como HostUrl o ReferrerUrl, pero su presencia depende del programa y del flujo de trabajo que generó la marca. No todos los archivos descargados tienen por qué conservarla.

Y algo muy importante desde el punto de vista forense: que aparezca una URL en HostUrl no demuestra por sí solo que el archivo se descargara desde esa dirección. Como veremos, cualquier usuario con permisos suficientes puede modificar el contenido de ese ADS.

3. Primer paso: identificar y leer los flujos

En un volumen NTFS, podemos comprobar qué flujos tiene un archivo mediante PowerShell:

Get-Item -LiteralPath 'C:\Analisis\muestra.txt' -Stream * |
Select-Object Stream, Length

Para leer un flujo Zone.Identifier existente:

Get-Content -LiteralPath 'C:\Analisis\muestra.txt' -Stream 'Zone.Identifier'

También podemos utilizar dir /r desde cmd.exe para enumerar flujos. Enumerar no equivale a preservar: si luego copiamos únicamente el contenido principal, podemos perder el ADS.

La ausencia de Zone.Identifier tampoco demuestra que el archivo sea local. La aplicación pudo no crearlo, el flujo pudo eliminarse o pudo perderse durante alguna transferencia.

4. Laboratorio: modificar el ADS y verificar ambos hashes

Entorno validado por el autor: Windows 11, ejecutando los comandos de PowerShell sobre un archivo de prueba en NTFS. Los hashes de la tabla final proceden de esa ejecución, no de una evidencia real ni de una descarga. El script complementario incluye una variante para PowerShell 7, pero esa variante no forma parte de la prueba empírica citada aquí.

Advertencia: utiliza exclusivamente los archivos que crearemos en %TEMP%. No modifiques ni desbloquees evidencias originales.

4.1. Crear el fichero y su flujo alternativo

$lab = Join-Path $env:TEMP 'DFIRSpain-ADS-Lab'
New-Item -ItemType Directory -Path $lab -Force | Out-Null
$file = Join-Path $lab 'muestra.txt'
Set-Content -LiteralPath $file -Value 'Documento sintetico de laboratorio' -Encoding ASCII
Set-Content -LiteralPath $file -Stream 'Zone.Identifier' -Encoding ASCII -Value @(
'[ZoneTransfer]'
'ZoneId=3'
'HostUrl=https://example.invalid/primera-version.txt'
)
Get-Item -LiteralPath $file -Stream * | Select-Object Stream, Length
Get-Content -LiteralPath $file -Stream 'Zone.Identifier'

En la prueba, PowerShell enumeró dos flujos:

Stream Length
------ ------
:$DATA 36
Zone.Identifier 79

El primero almacena los 36 bytes del contenido de muestra.txt. El segundo contiene los 79 bytes de nuestra marca ficticia. Son tamaños distintos porque son datos distintos, aunque pertenezcan al mismo archivo NTFS.

4.2. Calcular el hash del flujo principal

$hashPrincipal = (Get-FileHash -LiteralPath $file -Algorithm SHA256).Hash
$hashPrincipal

Al modificar únicamente HostUrl dentro del ADS, el SHA-256 del contenido principal siguió siendo:

D70192805806D4C0A6FC79563354B7C20BF425BC657327415DCD81E4D58F4E82

Hasta aquí hemos verificado que el flujo principal no ha cambiado. Aún no hemos comprobado si el ADS cambió a nivel de bytes. Para hacerlo necesitamos calcular su hash por separado.

4.3. Calcular el SHA-256 del ADS correctamente

Aquí apareció una dificultad práctica durante la preparación del laboratorio: intentar pasar muestra.txt:Zone.Identifier directamente a Get-FileHash -LiteralPath o abrirlo mediante System.IO.File.Open() produjo errores de formato de ruta en el entorno utilizado.

La solución validada fue leer los bytes del ADS, sin convertirlos a una representación textual, y calcular su SHA-256:

# Windows PowerShell 5.1
[byte[]]$bytesADS = Get-Content -LiteralPath $file `
-Stream 'Zone.Identifier' -Encoding Byte -ReadCount 0
$sha256 = [System.Security.Cryptography.SHA256]::Create()
try {
$hashADS = [BitConverter]::ToString(
$sha256.ComputeHash($bytesADS)
).Replace('-', '')
$hashADS
}
finally {
$sha256.Dispose()
}

En PowerShell 7 la lectura binaria correspondiente utiliza -AsByteStream -ReadCount 0 en lugar de -Encoding Byte. Para el laboratorio descargable he incluido ambas rutas según la versión de PowerShell.

¿Y por qué leer bytes directamente? Porque si transformamos el ADS en texto y luego volvemos a codificarlo, podríamos estar calculando el hash de una representación distinta, especialmente si hay BOM, finales de línea o caracteres no ASCII.

4.4. Modificar el ADS y comparar

En la ejecución de verificación, el ADS ya contenía una segunda URL ficticia. Se tomó su hash como valor de referencia, después se modificó únicamente HostUrl a una versión final y se volvió a calcular cada SHA-256.

El resultado real fue:

ElementoSHA-256 antesSHA-256 después¿Coinciden?
Flujo principalD70192805806D4C0A6FC79563354B7C20BF425BC657327415DCD81E4D58F4E82D70192805806D4C0A6FC79563354B7C20BF425BC657327415DCD81E4D58F4E82Sí
Zone.Identifier330553AA9261A648ADE6EF8C0A91EE5EAEFB3460C4483EBC1720086950FAB6EF0326EC20E4ED919855B47BB055BF50CF7BC5AC780882EB56CF907EF71CDB2FC1No

La tabla recoge dos estados concretos del laboratorio y sus hashes. Si ejecutas desde cero el script complementario, las URL de ejemplo y, por tanto, los hashes del ADS pueden diferir de estos valores. Lo relevante es el resultado de la comparación:

  • El flujo principal no ha cambiado, por lo que conserva exactamente el mismo hash.
  • El ADS sí ha cambiado, y su hash es diferente.

La modificación del ADS también puede afectar a los metadatos temporales del archivo. La prueba no demuestra que todos los demás atributos NTFS permanezcan idénticos; demuestra únicamente lo indicado para esos dos contenidos.

5. ¿Qué significa esto para una adquisición forense?

Supongamos que encontramos un ejecutable con un Zone.Identifier interesante. Lo copiamos al directorio de trabajo, calculamos el SHA-256 y dejamos constancia del hash en el informe.

Si durante la copia se pierde el ADS, el SHA-256 del ejecutable puede seguir coincidiendo con el original. El hash ha hecho bien su trabajo: ha verificado los bytes del flujo principal. Lo que no hemos comprobado es que hayamos conservado el resto de la información asociada al archivo.

El comportamiento depende del método de adquisición, la herramienta utilizada, el formato de almacenamiento y el sistema de archivos de destino. No toda copia pierde ADS ni toda copia los conserva. Una imagen forense del volumen permite preservar más contexto que una exportación aislada del flujo principal, siempre que la adquisición sea íntegra y se analice adecuadamente.

En una investigación documentaría, como mínimo:

  1. El origen y el método de adquisición, indicando si se preserva el sistema de archivos o se extraen únicamente archivos.
  2. La enumeración de flujos existentes para los archivos relevantes.
  3. La conservación del contenido de los ADS junto con su nombre y vinculación al archivo original, cuando corresponda.
  4. Los hashes por separado del flujo principal y de los flujos relevantes, además de los controles de integridad del contenedor o imagen forense.
  5. Las limitaciones conocidas de la herramienta y del destino utilizado para almacenar la copia.

Esta es también una buena razón para no ejecutar Unblock-File sobre evidencias originales: ese comando puede eliminar el flujo Zone.Identifier.

6. ¿Podemos afirmar que el archivo se descargó de HostUrl?

No solo con Zone.Identifier.

La marca puede ser una pista de procedencia, pero no constituye por sí misma una prueba concluyente. Nuestro propio laboratorio acaba de demostrar que podemos fabricar y modificar su contenido sin necesidad de descargar ningún archivo.

En un caso real contrastaría esa información con los registros de descargas del navegador, eventos de creación de archivo, telemetría de red disponible y otros artefactos relacionados con ejecución o acceso al fichero.

Si Sysmon estaba instalado y configurado para recogerlo, su Event ID 15 (FileCreateStreamHash) puede aportar información sobre la creación de flujos alternativos, incluido Zone.Identifier. No debe interpretarse como un registro completo de todas las modificaciones posteriores de un ADS ni como prueba automática de descarga o ejecución.

Un HostUrl resulta especialmente útil cuando encaja con otras evidencias independientes. Si no encaja, merece investigar esa discrepancia antes de atribuirle una causa.

7. Tres conclusiones que conviene evitar

«Tiene ZoneId=3, así que alguien lo descargó de Internet». La zona puede ser coherente con una descarga, pero la marca también puede crearse manualmente y la actividad debe corroborarse.

«No tiene Zone.Identifier, por lo tanto no vino de Internet». Su ausencia puede explicarse por el comportamiento de la aplicación, políticas del sistema o la pérdida/eliminación del flujo.

«El SHA-256 coincide, así que hemos preservado el archivo NTFS completo». Solo sabemos que coincide el contenido cubierto por ese hash. No acredita la conservación de todos los ADS o metadatos NTFS.

Conclusión

Lo que empezó como una prueba sencilla con muestra.txt terminó siendo una buena lección sobre adquisición e integridad.

Los ADS son parte del modelo de almacenamiento de NTFS. Zone.Identifier es uno de los más conocidos y puede aportar contexto sobre la procedencia de archivos, pero su contenido es modificable y debe interpretarse con prudencia.

La conclusión principal del laboratorio no es que SHA-256 falle. Es otra: antes de dar por íntegra una evidencia, debemos definir con precisión qué estamos verificando.

Una cosa es garantizar la igualdad del flujo principal; otra, haber preservado el archivo y todo el contexto del sistema de archivos que necesitamos para investigarlo.

Y esa diferencia, cuando estamos reconstruyendo un incidente, puede ser bastante importante.

Referencias




Publicar un comentario

0 Comentarios