2012-03-06 6 views
5

Tengo problemas para configurar el descriptor de seguridad al crear un NamedPipe. Quiero que la tubería creada en el servicio de Windows (alta integridad) se abra desde procesos de integridad media y baja.Descriptor de seguridad de tubería de baja integridad a media/alta integridad

Estoy trabajando en Windows 7 x64. No entiendo muy bien lo que estoy haciendo aquí, pero aquí está el código que uso para crear un descriptor de seguridad para las tuberías que creo. Siguiente código no me deja tubos abiertos creados tanto en alta y media leve integridad de los procesos de baja integridad:



    PSID psidWorldSid = NULL, pAdminSID = NULL, pLowSID = NULL, pHighSID = NULL; 
    WCHAR wszIntegritySid[] = L"S-1-16-4096"; 
    WCHAR wszSystemSid[] = L"S-1-16-16384"; 
    PACL pACL = NULL; 
    PSECURITY_DESCRIPTOR pSD = NULL; 
    SECURITY_ATTRIBUTES sa; 
    SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; 
    SID_IDENTIFIER_AUTHORITY siaWorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY; 
    EXPLICIT_ACCESS ea[4]; 

    // Create a security descriptor for the log file that allows 
    // access from both the privileged service and the non-privileged 
    // user mode programs 

    AllocateAndInitializeSid(&siaWorldSidAuthority, 1, 
     SECURITY_WORLD_RID, 
     0, 0, 0, 0, 0, 0, 0, 
     &psidWorldSid); 

    ZeroMemory(&ea, sizeof(ea)); 
    ea[0].grfAccessPermissions = FILE_ALL_ACCESS | GENERIC_WRITE | GENERIC_READ; 
    ea[0].grfAccessMode = SET_ACCESS; 
    ea[0].grfInheritance= NO_INHERITANCE; 
    ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; 
    ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; 
    ea[0].Trustee.ptstrName = (LPTSTR) psidWorldSid; 

    // Create a SID for the BUILTIN\Administrators group. 
    AllocateAndInitializeSid(&SIDAuthNT, 2, 
     SECURITY_BUILTIN_DOMAIN_RID, 
     DOMAIN_ALIAS_RID_ADMINS, 
     0, 0, 0, 0, 0, 0, 
     &pAdminSID); 

    // Initialize an EXPLICIT_ACCESS structure for an ACE. 
    // The ACE will allow the Administrators group full access to 
    // the key. 
    ea[1].grfAccessPermissions = FILE_ALL_ACCESS | GENERIC_WRITE | GENERIC_READ; 
    ea[1].grfAccessMode = SET_ACCESS; 
    ea[1].grfInheritance= NO_INHERITANCE; 
    ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; 
    ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; 
    ea[1].Trustee.ptstrName = (LPTSTR) pAdminSID; 

    AllocateAndInitializeSid(&siaWorldSidAuthority, 1, 
     SECURITY_MANDATORY_LOW_RID, 
     0, 
     0, 0, 0, 0, 0, 0, 
     &pLowSID); 

    ea[2].grfAccessPermissions = FILE_ALL_ACCESS | GENERIC_WRITE | GENERIC_READ; 
    ea[2].grfAccessMode = SET_ACCESS; 
    ea[2].grfInheritance= NO_INHERITANCE; 
    ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID; 
    ea[2].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; 
    ea[2].Trustee.ptstrName = (LPTSTR) pLowSID; 

    AllocateAndInitializeSid(&siaWorldSidAuthority, 1, 
     SECURITY_MANDATORY_HIGH_RID, 
     0, 
     0, 0, 0, 0, 0, 0, 
     &pHighSID); 

    ea[3].grfAccessPermissions = FILE_ALL_ACCESS | GENERIC_WRITE | GENERIC_READ; 
    ea[3].grfAccessMode = SET_ACCESS; 
    ea[3].grfInheritance= NO_INHERITANCE; 
    ea[3].Trustee.TrusteeForm = TRUSTEE_IS_SID; 
    ea[3].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; 
    ea[3].Trustee.ptstrName = (LPTSTR) pHighSID; 

    SetEntriesInAcl(4, ea, NULL, &pACL); 

    pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); 
    InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); 
    SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE); 
    ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); 


    sa.nLength    = sizeof(SECURITY_ATTRIBUTES); 
    sa.lpSecurityDescriptor = pSD; 
    sa.bInheritHandle  = FALSE; 

    m_hPipe = CreateNamedPipeA(
       m_szName.c_str(), 
       PIPE_ACCESS_DUPLEX, 
       PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | BlockFlag, 
       PIPE_UNLIMITED_INSTANCES, 
       BUFFER_SIZE, 
       BUFFER_SIZE, 
       NMPWAIT_USE_DEFAULT_WAIT, 
       &sa 
       ); 

    if (psidWorldSid) 
     FreeSid(psidWorldSid); 
    if (pAdminSID) 
     FreeSid(pAdminSID); 
    if (pLowSID) 
     FreeSid(pLowSID); 
    if (pHighSID) 
     FreeSid(pHighSID); 
    if (pACL) 
     LocalFree(pACL); 
    if (pSD) 
     LocalFree(pSD); 

Parece que funciona casi bien cuando se crea un descriptor de seguridad de la cadena:

ConvertStringSecurityDescriptorToSecurityDescriptorW(L"S:(ML;;NW;;;LW)", SDDL_REVISION_1, &pSD, NULL);

Cuando creo un descriptor de seguridad a partir de la cadena como se indicó anteriormente, al menos puedo abrir las tuberías creadas con permisos de integridad medios de procesos de baja integridad.

Gracias por cualquier sugerencia.

Saludos, Kuba

+0

Deberías aceptar la respuesta de Chris. –

Respuesta

5

El código que muestre parece estar creando un descriptor de seguridad y la creación de su lista de control de acceso discrecional (DACL). La DACL no tiene nada que ver con el mecanismo de control de integridad.

Para que los procesos de baja integridad abran un identificador a través del cual escribir en la tubería con nombre, el objeto de tubería con nombre debe marcarse Integridad baja en su Etiqueta de integridad obligatoria. Esta etiqueta vive en la Lista de control de acceso del sistema (SACL), no en la DACL. Eso es lo que significa el prefijo S:(... en la representación de cadena SDDL del descriptor de seguridad que usó para crear la SD a través del ConvertStringSecurityDescriptorToSecurityDescriptorW.

Si desea hacer esto a mano larga sin partir de la representación SDDL, debe crear una ACE del tipo correcto, SYSTEM_MANDATORY_LABEL_ACE, inicializada con el SID para baja integridad (S-1-16-4096) y una política de integridad apropiada (por ejemplo, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP), y luego colóquela en el SACL a través del .

+0

Hola Chris. Leí información en MSDN sobre este problema: http://msdn.microsoft.com/en-us/library/bb625960.aspx. Me parece que establecí una integridad baja en la tubería correctamente con "S: (ML ;; NW ;;; LW)", ya que es lo mismo que presentan en el ejemplo de MSDN. Sé que con esto estoy perdiendo seguridad. ¿Tal vez sería mejor realizar un proxy/túnel de todas las conexiones desde procesos de baja integridad a través de procesos de integridad del medio antes de enviarlos a los de alta integridad? – blackd0t

+1

Sí, si lo hace usando SDDL, 'S: (ML ;; NW ;; LW)' es correcto y está haciendo exactamente lo que describí: 'S:' dice que está configurando el SACL, 'ML' indica una SYSTEM_MANDATORY_LABEL_ACE, 'NW' es la política de integridad sin escritura, y' LW' dice que lo está habilitando para llamadas de Integridad baja. Solo está "perdiendo seguridad" de una manera muy controlada ... los procesos de baja integridad están habilitados para escribir datos en su pipa cuando por defecto no podrían hacerlo. Eso no es un problema (en realidad es solo lo que intenta lograr) siempre y cuando su servidor de tuberías valide y trate con cuidado todos los datos entrantes. –

+1

@ChrisDickson: ¿Puede proporcionar alguna fuente sobre cómo agregar ese SYSTEM_MANDATORY_LABEL_ACE. ¿Cómo puedo cambiar la seguridad si la tubería ya existe? ¿Cómo puedo abrir ese identificador, para que tenga los derechos de ACCESS_SYSTEM_SECURITY que se requieren al cambiar cualquier ACE de SACL? – bkausbk

3

Pude resolver el problema. Como Chris señaló, la tubería se creó correctamente con permisos de baja integridad, aunque me perdí la parte donde la hice disponible para los usuarios.

resolví esto estableciendo SDDL así: S:(ML;;NW;;;LW)D:(A;;0x12019f;;;WD) Esto establecerá permisos para Everyone de usuario que le permite abrir, escribir, leer la tubería. Lo he revisado y ahora se puede acceder a la tubería de forma global desde cualquier nivel de integridad y desde cualquier cuenta.

Mejor manera sería configurar 0x12019b permisos para "Todos", ya que dará a todos los usuarios acceso a la tubería sin permisos para agregar nuevas instancias a la tubería. Entonces tendría que agregar permisos 0x12019f solo para el usuario que crea los tubos, pero no tenía idea de cómo obtener el ID del usuario actual.

En mi situación, encaja muy bien ya que solo informo datos de otros procesos para su análisis por el servicio del sistema, pero si usa pipes para controlar el servicio del sistema puede que no desee configurar el descriptor de seguridad de otra manera. Es muy importante tener cuidado con cualquier desbordamiento de almacenamiento intermedio/almacenamiento dinámico al enviar datos al servicio del sistema a través de las conexiones, ya que puede causar un error de seguridad que deja una vulnerabilidad que podría permitir la escalada de privilegios locales.

Espero que esta pregunta ayude a otra persona.

Roger, fuera!

Cuestiones relacionadas