Windows命名管道访问控制

Windows命名管道访问控制,windows,ipc,named-pipes,nonblocking,Windows,Ipc,Named Pipes,Nonblocking,我的进程(服务器)通过CreateProcess创建一个子进程(客户端),我在这些进程之间执行IPC。我从匿名管道开始,但很快我发现它不支持所解释的重叠操作 所以,命名管道是我的第二选择。我的困惑是:如果我创建了一个命名管道,是否可以将此管道的访问权限仅限于我以前调用CreateProcess创建的子进程?因此,即使另一个进程获得管道的名称,它仍然无法读取或写入管道 我的IPC使用仅限于本地计算机和单一平台(Windows) 顺便说一句,我可以更改这些进程的两个代码。异步(重叠)操作当然完全受匿

我的进程(服务器)通过
CreateProcess
创建一个子进程(客户端),我在这些进程之间执行IPC。我从匿名管道开始,但很快我发现它不支持所解释的重叠操作

所以,命名管道是我的第二选择。我的困惑是:如果我创建了一个命名管道,是否可以将此管道的访问权限仅限于我以前调用
CreateProcess
创建的子进程?因此,即使另一个进程获得管道的名称,它仍然无法读取或写入管道

我的IPC使用仅限于本地计算机和单一平台(Windows)

顺便说一句,我可以更改这些进程的两个代码。

异步(重叠)操作当然完全受匿名管道支持。支持的异步操作或否-仅取决于调用
zwcreatednamedpipefile
ZwOpenFile
中使用的
FILE\u SYNCHRONOUS\u IO\u[no]NALERT
,但不取决于从哪个名称(或空名称)获得管道。使用
FILE\u SYNCHRONOUS\u IO\u NONALERT
选项创建管道对-仅因为此api返回的句柄不能用于异步操作。不幸的是,我们没有参数来更改此行为,但我们可以自己完成此任务

从vista开始,我们可以创建匿名(未命名)和异步管道对,但为此您需要使用NDLLAPI。下一个代码与内部代码几乎相似,只是我创建了异步管道对

NTSTATUS CreatePipeAnonymousPair(PHANDLE phServerPipe, PHANDLE phClientPipe)
{
    HANDLE hFile;

    IO_STATUS_BLOCK iosb;

    static UNICODE_STRING NamedPipe = RTL_CONSTANT_STRING(L"\\Device\\NamedPipe\\");

    OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &NamedPipe, OBJ_CASE_INSENSITIVE };

    NTSTATUS status;

    if (0 <= (status = ZwOpenFile(&hFile, SYNCHRONIZE, &oa, &iosb, FILE_SHARE_VALID_FLAGS, 0)))
    {
        oa.RootDirectory = hFile;

        static LARGE_INTEGER timeout = { 0, MINLONG };
        static UNICODE_STRING empty = {};

        oa.ObjectName = &empty;

        if (0 <= (status = ZwCreateNamedPipeFile(phServerPipe,
            FILE_READ_ATTRIBUTES|FILE_READ_DATA|
            FILE_WRITE_ATTRIBUTES|FILE_WRITE_DATA|
            FILE_CREATE_PIPE_INSTANCE, 
            &oa, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE,
            FILE_CREATE, 0, FILE_PIPE_BYTE_STREAM_TYPE, FILE_PIPE_BYTE_STREAM_MODE,
            FILE_PIPE_QUEUE_OPERATION, 1, 0, 0, &timeout)))
        {

            oa.RootDirectory = *phServerPipe;
            oa.Attributes = OBJ_CASE_INSENSITIVE|OBJ_INHERIT;

            if (0 > (status = ZwOpenFile(phClientPipe, FILE_READ_ATTRIBUTES|FILE_READ_DATA|
                FILE_WRITE_ATTRIBUTES|FILE_WRITE_DATA, &oa, &iosb, FILE_SHARE_VALID_FLAGS, 0)))
            {
                ZwClose(oa.RootDirectory);
                *phServerPipe = 0;
            }
        }

        ZwClose(hFile);
    }

    return status;
}
NTSTATUS CreatePipeAnonymousPair(幻影phServerPipe,幻影phClientPipe)
{
处理文件;
IO_状态_块iosb;
静态UNICODE\u字符串NamedPipe=RTL\u常量\u字符串(L“\\Device\\NamedPipe\”;
对象属性oa={sizeof(oa),0,&NamedPipe,OBJ_不区分大小写};
非关税国家地位;
如果(0,您可以使用
lpSecurityAttributes
参数将ACL显式分配给新管道。这将允许您确保,如果其他用户登录,他们无法连接到管道

但是,如果您在父进程中创建管道的两端,则几乎没有渎职的空间,因此通常不需要显式设置ACL。一旦打开管道的客户端,其他进程无论如何都无法连接到管道(如果希望创建第二个实例,则必须创建第二个实例)因此,只有很短的时间间隔,在这段时间内,另一个进程可能会发生干扰;即使发生了这种情况,您也无法连接客户端,这样您就知道出了问题

换句话说,攻击范围仅限于拒绝服务,而且由于攻击进程需要在同一台机器上运行,因此只需对CPU进行压缩,就可以实现更有效的拒绝服务

请注意:

  • 创建管道时,应使用
    文件\u标志\u第一个\u管道\u实例
    标志,以确保知道是否存在名称冲突

  • 出于明显的原因,您还应该使用
    PIPE\u REJECT\u REMOTE\u CLIENTS

  • 命名管道上的默认权限不允许其他非管理用户创建新实例,因此在这种情况下,中间人攻击不会带来风险

  • 以同一用户或管理用户身份运行的恶意进程可能会在您的连接中间有人(无论您是否设置了ACL)但是,由于任何此类恶意进程也可能将恶意代码直接注入父级和/或子级,因此没有必要担心它。攻击者已经站在了错误的一边;锁定窗口对您没有任何好处

  • 如果您的进程以提升权限运行,您可能应该在管道上设置ACL。默认ACL可能会允许非提升进程作为同一用户上下文在连接中间运行。您可以通过设置仅授予管理员完全访问权限的ACL来解决此问题。风险仍然很小但在这种特殊情况下,纵深防御措施可能是合适的

  • ,因此使用命名管道实际上并没有丢失任何东西。原则上,攻击者可以像命名管道一样轻松地在中间插入匿名管道。(编辑:根据RbMm,这不再是事实。)


调用
CreateNamedPipe
时,将指向
安全属性
结构的指针作为最终参数传递。这允许您完全按照需要限制访问。通过查看
CreateNamedPipe
的文档可以很容易地了解这一点:
lpSecurityAttributes
参数f与
CreatePipe
…异步(重叠)操作的方式相同,匿名管道当然完全支持异步(重叠)操作。支持的异步操作或否-仅取决于调用ZwCreateNamedPipeFile和ZwOpenFile时使用的是FILE_SYNCHRONOUS_IO_[no]NALERT,而不是从哪个名称(或空)开始的使用
FILE\u SYNCHRONOUS\u IO\u NONALERT
选项创建管道对-仅因为此api返回的句柄不能用于异步操作。不幸的是,CreatePipe没有参数来更改此行为,但我们可以自己执行此操作task@CodyGray-当然,我们可以设置一些非默认安全设置scriptor,但任何SD都不能限制对独子进程的访问。拥有
SE_TAKE_OWNERSHIP\u特权的用户也可以更改管道上的SD。从另一个角度看,存在感知,因此担心独子进程可以访问管道“匿名管道是使用具有唯一名称的命名管道实现的”-只有在xp/win2003中才是这样。但是从vista开始-匿名管道已经没有名字了。它们是如何创建的-在我的回答中。所以从vista开始(在所有最新的系统上)可能创建无法按名称打开的匿名管道。unfor