2017-05-09 3 views
0

Mit C versuche ich, eine Verbindung zwischen einem Prozess und einem untergeordneten Prozess herzustellen, während der untergeordnete Prozess eine niedrigere obligatorische (Integrität) Ebene (niedrig, während der übergeordnete Prozess ist hoch).SetSecurityInfo gibt Zugriff verweigert

ich das folgende Programm geschrieben (es ist eine vereinfachte Version, wenn es), aber es funktioniert nicht mit: ERROR_ACCESS_DENIED (0x5)

INT wmain(IN SIZE_T nArgc, IN PWSTR *pArgv) 
{ 
    SECURITY_ATTRIBUTES securityArrtibutes = { 0 }; 
    HANDLE hPipeRead = NULL; 
    HANDLE hPipeWrite = NULL; 

    tSecurityArrtibutes.nLength = sizeof(tSecurityArrtibutes); 
    tSecurityArrtibutes.bInheritHandle = TRUE; 

    SetSeSecurityNamePrivilege(); 
    CreatePipe(&hPipeRead, &hPipeWrite, &securityArrtibutes, 0); 
    ChangeMandatoryLabelHandle(hPipeRead); 
} 

VOID ChangeMandatoryLabelHandle(HANDLE hObject) 
{ 
    BOOL bRetval = FALSE; 
    DWORD dwError = 0; 
    PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL; 
    PACL ptSacl = NULL; 
    BOOL bSaclPresent = FALSE; 
    BOOL bSaclDefaulted = FALSE; 
    PWSTR pSDDL = NULL; 

    SDDL = L"S:(ML;;LW;;;NW)"; 

    bRetval = ConvertStringSecurityDescriptorToSecurityDescriptorW(pSDDL, SDDL_REVISION_1, &pSecurityDescriptor, NULL); 
    if (FALSE == bRetval) 
     ... // Handle failure 

    bRetval = GetSecurityDescriptorSacl(pSecurityDescriptor, &bSaclPresent, &ptSacl, &bSaclDefaulted); 
    if (FALSE == bRetval) 
     ... // Handle failure 

    // getting ERROR_ACCESS_DENIED (0x5) 
    dwErr = SetSecurityInfo(hObject, SE_KERNEL_OBJECT, LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, ptSacl); 
    if (ERROR_SUCCESS != dwErr) 
     ... // Handle failure 

    ... // Cleanup 
} 

Ich folgte https://msdn.microsoft.com/en-us/library/windows/desktop/aa379588(v=vs.85).aspx und die Bemerkung, dass To set the SACL of an object, the caller must have the SE_SECURITY_NAME privilege enabled.:

BOOL SetSeSecurityNamePrivilege() 
{ 
    HANDLE hToken; 
    TOKEN_PRIVILEGES tp; 
    LUID luid; 

    if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_IMPERSONATE, &hToken) 
     return FALSE 

    if (!LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &luid)) 
     return FALSE; 

    tp.PrivilegeCount = 1; 
    tp.Privileges[0].Luid = luid; 
    if (bEnablePrivilege) 
     tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
    else 
     tp.Privileges[0].Attributes = 0; 

    if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) 
     return FALSE; 

    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) 
     return FALSE; 

    return TRUE; 
} 

note: Ich bekomme das gleiche Ergebnis, wenn ich versuche, es mit Dateien auszuführen, mit CreateFile anstelle von CreatePipe. Zusätzlich, wenn ich versuche, das mit Dateien zu tun, und ich SetSecurityInfo durch SetNamedSecurityInfoW ersetzen, und geben Sie den vollständigen Pfad der Datei, es funktioniert super.

Hat jemand eine Idee, wie es funktioniert? Vielen Dank!

+1

Wie RbMm in seiner Antwort erklärt, hat die Änderung der Sicherheitsbeschreibung wahrscheinlich keine Auswirkungen auf das Problem, das Sie hier eigentlich lösen wollen. Sobald Sie sich davon überzeugt haben, schlage ich vor, dass Sie eine weitere Frage stellen, die sich auf Ihr tatsächliches Problem konzentriert. –

Antwort

2

Einige Anmerkungen, bevor Sie die Ursache Ihres unmittelbaren Problems ansprechen.

In erster Linie müssen Sie die Sicherheitsbeschreibung überhaupt nicht ändern, und dies wird Ihnen wahrscheinlich nicht helfen, Ihr endgültiges Ziel zu erreichen. Die Sicherheitsbeschreibung wird nur überprüft, wenn Sie versuchen, ein Handle für ein Objekt zu öffnen. Wenn Sie bereits ein Handle haben, hat die Sicherheitsbeschreibung keine Auswirkung. Da Sie eine unbenannte Pipe erstellen, müssen Sie das Handle, nicht den Pipe-Namen an das untergeordnete übergeben, so dass Sie die ChangeMandatoryLabelHandle Funktion überhaupt nicht benötigen.

Zweitens ist das SE_SECURITY_NAME Privileg nicht erforderlich, wenn LABEL_SECURITY_INFORMATION eingestellt wird. Das obligatorische Label unterscheidet sich logisch vom Rest der SACL und wird als Sonderfall behandelt.

Drittens ist Ihre "S:(ML;;LW;;;NW)" ungültig.

Ich habe versucht, es zu benutzen, in ConvertStringSecurityDescriptorToSecurityDescriptorW und bekam Fehler 1336 Die Zugriffssteuerungsliste (ACL) Struktur ist ungültig. Verwenden Sie stattdessen "D:NO_ACCESS_CONTROLS:(ML;;;;;LW)" oder besser noch den folgenden Code verwenden, um eine Sicherheitsbeschreibung mit einem niedrigen Label zu erstellen und ohne DACL:

ULONG cb = MAX_SID_SIZE; 
PSID LowLabelSid = (PSID)alloca(MAX_SID_SIZE); 

ULONG dwError = NOERROR; 

if (CreateWellKnownSid(WinLowLabelSid, 0, LowLabelSid, &cb)) 
{ 
    PACL Sacl = (PACL)alloca(cb += sizeof(ACL) + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK)); 

    if (InitializeAcl(Sacl, cb, ACL_REVISION) && 
     AddMandatoryAce(Sacl, ACL_REVISION, 0, 0, LowLabelSid)) 
    { 
     SECURITY_DESCRIPTOR sd; 
     InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); 
     SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); 
     SetSecurityDescriptorSacl(&sd, TRUE, Sacl, FALSE); 

     SECURITY_ATTRIBUTES sa = { sizeof(sa), &sd, TRUE }; 

     // todo something here 
    } 
    else 
    { 
     dwError = GetLastError(); 
    } 
} 
else 
{ 
    dwError = GetLastError(); 
} 

Aber auch hier müssen Sie verstehen, dass es (fast) nie ein Sinn zu schaffen eine Sicherheitsbeschreibung für ein unbenanntes Objekt. Die Sicherheitsbeschreibung wird nur beim Öffnen eines Objekts überprüft und (im Benutzermodus) können Sie kein Objekt öffnen, das keinen Namen hat.

(von Kernel-Modus uns ein Objekt durch den Zeiger mit ObOpenObjectByPointer öffnen können.)

(In älteren Versionen von Windows, CreatePipe tatsächlich ein Rohr mit einem zufälligen Namen erstellt, jedoch ausgehend von Windows 7 das Rohr wirklich unbenannt ist, werden sie mit Create oder einem ähnlichen Verfahren.)

in jedem Fall ist es meiner Meinung nach so nicht geöffnet, dass CreatePipe in diesem Zusammenhang eine schlechte Wahl war verwenden. Diese Funktion ist nicht gut entworfen und hat zu wenige Parameter.Es gibt keine Option zum Erstellen einer bidirektionalen Pipe oder zum Öffnen der Pipe im asynchronen Modus. Ich denke, es ist besser zu verwenden CreateNamedPipeW und CreateFileW.

(Alternativ von Windows 7 ab, Sie ZwCreateNamedPipeFile und ZwOpenFile ein unbenannte Rohr erstellen und öffnen können.)


Das nächste Problem mit dem Code wie geschrieben ist, dass SetSecurityInfo und SetKernelObjectSecurity zurückgeben ERROR_ACCESS_DENIED wenn mit dem von CreatePipe zurückgegebenen Handle aufgerufen. Dies liegt daran, wie für LABEL_SECURITY_INFORMATION in der Dokumentation beschrieben:

Rechte setzen erforderlich: WRITE_OWNER

Da CreatePipe hat man nicht die Möglichkeit geben, die Zugriffsrechte zu wählen, die die Griffe geöffnet werden mit, Sie haben keine Möglichkeit, dies zu tun. Wenn Sie stattdessen verwenden, können Sie WRITE_OWNER in dwOpenMode setzen.

Sie sollten jedoch beachten, dass wenn Sie ein Objekt mit einer speziellen Sicherheitsbeschreibung erstellen möchten, es vorzuziehen ist, diese Sicherheitsbeschreibung anzugeben, wenn das Objekt erstellt wird. Es hat keinen Sinn, das Objekt mit einer Standardsicherheitsbeschreibung zu erstellen und dann zu ändern. Warum in zwei Operationen, was kannst du in einem tun? In diesem Fall passieren die SECURITY_ATTRIBUTES Struktur Sie CreatePipe oder CreateNamedPipe verwendet werden kann, die Sicherheitsbeschreibung angeben und bietet einen anderen Weg, um Ihre unmittelbare Problem der Adressierung, obwohl, wie zuvor nicht erwähnt wird in der Tat nützlich sein.