SetSecurityInfo返回拒绝访问
使用C,我试图在进程与其子进程之间建立管道连接,而子进程的强制(完整性)级别较低(较低,而父进程较高) 我编写了以下程序(如果是简化版的话),但失败了:SetSecurityInfo返回拒绝访问,c,windows,security,winapi,ipc,C,Windows,Security,Winapi,Ipc,使用C,我试图在进程与其子进程之间建立管道连接,而子进程的强制(完整性)级别较低(较低,而父进程较高) 我编写了以下程序(如果是简化版的话),但失败了:ERROR\u ACCESS\u DENIED(0x5) 我跟着他说 要设置对象的SACL,调用者必须启用SE_SECURITY_NAME权限。: BOOL SetSeSecurityNamePrivilege() { HANDLE hToken; TOKEN_PRIVILEGES tp; LUID luid;
ERROR\u ACCESS\u DENIED(0x5)
我跟着他说
要设置对象的SACL,调用者必须启用SE_SECURITY_NAME权限。
:
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;
}
注意:当我尝试使用文件执行它时,我会得到相同的结果,使用CreateFile
而不是CreatePipe
。
此外,如果我尝试使用文件来实现这一点,并将SetSecurityInfo
替换为setnamedsecurityinfo
,并为其提供文件的完整路径,则效果非常好
有人知道如何让它工作吗?谢谢 在解决眼前问题的原因之前,请注意几点 首先,您根本不需要更改安全描述符,这样做不太可能帮助您实现最终目标。仅当您尝试打开对象的句柄时,才会检查安全描述符;如果已经有句柄,则安全描述符无效。由于要创建未命名的管道,因此必须将句柄而不是管道名称传递给子级,因此根本不需要ChangeMandatoryLabelHandle函数 其次,在设置
标签安全信息时,不需要SE\u SECURITY\u NAME
权限。强制标签在逻辑上不同于SACL的其余部分,并被视为特例
第三,您的“S:(ML;;LW;;;NW)
无效
我试图在ConvertStringSecurityDescriptorSecurityDescriptorW中使用它,但出现错误1336,访问控制列表(ACL)结构无效。相反,使用“D:NO_ACCESS_CONTROLS:(ML;;;LW)”
或更好地使用以下代码创建具有低标签且无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();
}
但是,您需要再次了解,为未命名对象创建安全描述符(几乎)没有任何意义。只有在打开对象时才会检查安全描述符,并且(在用户模式下)无法打开没有名称的对象
(从内核模式,我们可以使用指针打开对象。)
(在旧版本的Windows中,CreatePipe实际上创建了一个具有随机名称的管道,但从Windows 7开始,该管道实际上未命名,因此无法使用CreateFile或任何类似方法打开。)
无论如何,我认为在这种情况下使用CreatePipe是一个错误的选择。此功能设计不完善,参数太少。没有创建双向管道或以异步模式打开管道的选项。我认为最好使用CreateNamedPipeW和CreateFileW
(或者,从Windows 7开始,可以使用ZwCreateNamedPipeFile和ZwOpenFile创建和打开未命名管道。)
发布的代码最接近的问题是,当使用返回的句柄调用时,返回错误\u ACCESS\u DENIED。这是因为,如文档中所述:
需要设置的权限:写入所有者
由于没有为您提供选择打开句柄时使用的访问权限的选项,因此您无法执行此操作。如果改为使用,则可以在dwOpenMode中设置WRITE_所有者
但是,您应该注意,如果希望创建具有特殊安全描述符的对象,最好在创建对象时提供该安全描述符。使用默认安全描述符创建对象,然后更改它是没有意义的;为什么在两次手术中你能做一次?在这种情况下,可以使用传递给CreatePipe或CreateNamedPipe的SECURITY\u属性
结构来指定安全描述符,从而提供解决当前问题的另一种方法,尽管如前所述,这实际上是没有用的。在解决眼前问题的原因之前,请注意几点
首先,您根本不需要更改安全描述符,这样做不太可能帮助您实现最终目标。仅当您尝试打开对象的句柄时,才会检查安全描述符;如果已经有句柄,则安全描述符无效。由于要创建未命名的管道,因此必须将句柄而不是管道名称传递给子级,因此根本不需要ChangeMandatoryLabelHandle函数
其次,在设置标签安全信息时,不需要SE\u SECURITY\u NAME
权限。强制标签在逻辑上不同于SACL的其余部分,并被视为特例
第三,您的“S:(ML;;LW;;;NW)
无效
我试图在ConvertStringSecurityDescriptorSecurityDescriptorW中使用它,但出现错误1336,访问控制列表(ACL)结构无效。相反,使用“D:NO_ACCESS_CONTROLS:(ML;;;LW)”
或更好地使用以下代码创建具有低标签且无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();
}
但是,您需要再次了解,为未命名对象创建安全描述符(几乎)没有任何意义。只有在打开对象时才会检查安全描述符,并且(在用户模式下)无法打开没有名称的对象
(从内核模式,我们可以使用指针打开对象。)
(在旧版本的Windows中,CreatePipe实际上创建了一个具有随机名称的管道,但从Windows 7开始,该管道实际上未命名,因此无法使用CreateFile或任何类似方法打开。)
无论如何,我认为在这种情况下使用CreatePipe是一个错误的选择。此功能设计不完善,p太少