2017-05-09 1 views
0

C를 사용하면 프로세스와 하위 프로세스 사이에 파이프 연결을 설정하려고 시도하는 반면 하위 프로세스에는 하위 (필수) 수준 (낮음, 상위 프로세스가 높음)이 있습니다. SetSecurityInfo에서 액세스가 거부됨을 반환합니다.

나는 다음과 같은 프로그램을 작성 (이것은 단순화 된 버전이있는 경우입니다)하지만, 실패 :

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; 
} 

참고 : 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 
} 

내가 https://msdn.microsoft.com/en-us/library/windows/desktop/aa379588(v=vs.85).aspx과 말을 따라 To set the SACL of an object, the caller must have the SE_SECURITY_NAME privilege enabled.한다 : CreatePipe 대신 CreateFile을 사용하여 파일을 실행하려고하면 동일한 결과가 발생합니다. 또한 파일로 처리하려고하면 SetSecurityInfoSetNamedSecurityInfoW으로 바꾸고 파일의 전체 경로를 지정하면 잘 작동합니다.

누구나 어떻게 작동하는지 아이디어가 있습니까? 감사!

+1

RbMm이 답변에서 설명하는 것처럼 보안 설명자를 변경하면 실제로 여기에서 해결하려고하는 모든 문제에 어떤 영향도 미치지 않습니다. 일단 자신이 그것을 확신하게되면 실제 문제에 초점을 맞춘 또 다른 질문을 게시하는 것이 좋습니다. –

답변

2

즉각적인 문제의 원인을 해결하기 전에 몇 가지 메모를 작성하십시오.

먼저 보안 설명자를 전혀 변경할 필요가 없으므로 궁극적 인 목표를 달성하는 데 도움이되지 않습니다. 보안 설명자는 개체에 대한 핸들을 열려고 시도 할 때만 선택됩니다. 이미 핸들이있는 경우 보안 설명자가 아무런 영향을 미치지 않습니다. 이름없는 파이프를 만들므로 파이프 이름이 아닌 핸들을 자식에게 전달해야하므로 ChangeMandatoryLabelHandle 함수가 전혀 필요하지 않습니다.

두 번째로 LABEL_SECURITY_INFORMATION을 설정할 때 SE_SECURITY_NAME 권한이 필요하지 않습니다. 필수 라벨은 SACL의 나머지 부분과 논리적으로 구별되며 특수한 경우로 취급됩니다.

셋째, "S:(ML;;LW;;;NW)"은 유효하지 않습니다.

내가 ConvertStringSecurityDescriptorToSecurityDescriptorW에서 사용하려고 및 오류 1336있어, 액세스 제어 목록 (ACL) 구조가 올바르지 않습니다.

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(); 
} 

그러나 다시, 당신은 (거의)이 있음을 이해할 필요가 결코 만드는 어떤 의미 : 대신, 낮은 라벨을 가져 DACL에 보안 설명을 만들려면 다음 코드를 사용하여 더 나은 여전히 ​​"D:NO_ACCESS_CONTROLS:(ML;;;;;LW)" 사용하거나 이름이없는 오브젝트의 시큐러티 기술자 보안 설명자는 개체를 열 때만 선택되며 사용자 모드에서는 이름이없는 개체를 열 수 없습니다.

(우리가 ObOpenObjectByPointer를 사용하여 포인터 객체를 열 수 커널 모드에서.) 이전 버전의 Windows에서

(CreatePipe 실제로 임의의 이름을 가진 파이프를 만들었지 만 정말 윈도우 7 관에서 시작 이름이있다, 그래서 CreateFile에 또는 이와 유사한 방법으로 열 수 없습니다.) 어떤 경우

, 그것은 이러한 맥락에서 CreatePipe를 사용하는 것이 나쁜 선택이었다 내 의견이다. 이 함수는 잘 설계되지 않았고 매개 변수가 너무 적습니다.양방향 파이프를 작성하거나 비동기 모드로 파이프를 여는 옵션은 없습니다. CreateNamedPipeWCreateFileW을 사용하는 것이 더 좋습니다.

(또는 이후 윈도우 7에서, 당신은 이름 파이프를 생성하고 열 ZwCreateNamedPipeFileZwOpenFile를 사용할 수 있습니다.)


근접 문제를 코드에 게시 된이 그 SetSecurityInfoSetKernelObjectSecurityCreatePipe에 의해 반환 된 핸들을 사용하여 호출하면 ERROR_ACCESS_DENIED이 반환됩니다.

설정하는 데 필요한 오른쪽 : WRITE_OWNER CreatePipe 이후

는 당신에게 핸들이 열려있는 액세스 권한을 선택할 수있는 옵션을 제공하지 않습니다 LABEL_SECURITY_INFORMATION에 대한 문서에 설명 된대로 때문이다 함께, 당신은이 일을 할 수있는 방법이 없습니다. CreateNamedPipe을 사용하는 경우 WRITE_OWNERdwOpenMode으로 설정할 수 있습니다.

그러나 특수 보안 설명자를 사용하여 개체를 만들려면 개체를 만들 때 해당 보안 설명자를 제공하는 것이 좋습니다. 기본 보안 설명자를 사용하여 개체를 만든 다음이를 변경하는 것은 중요하지 않습니다. 왜 두 가지 작업에서 하나의 작업을 수행 할 수 있습니까? 이 경우 구조체 (CreatePipe 또는 )에 전달 CreateNamedPipe은 보안 설명자를 지정하는 데 사용할 수 있습니다. 이전에 언급했듯이 실제 유용하지는 않지만 직접적인 문제를 해결하는 다른 방법을 제공합니다.

관련 문제