【问题标题】:Windows Named Pipe Access controlWindows 命名管道访问控制
【发布时间】:2017-04-12 05:01:56
【问题描述】:

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

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

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

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

【问题讨论】:

  • 调用CreateNamedPipe 时,将指向SECURITY_ATTRIBUTES 结构的指针作为最后一个参数传递。这允许您完全根据需要限制访问。通过查看CreateNamedPipe 的文档很容易弄清楚这一点:lpSecurityAttributes 参数的功能与CreatePipe 的功能相同...
  • 异步(重叠)操作当然完全由匿名管道支持。是否支持异步操作 - 仅取决于调用 ZwCreateNamedPipeFile 和 ZwOpenFile 中使用的 FILE_SYNCHRONOUS_IO_[NO]NALERT,但不取决于哪个名称(或空)具有管道。 CreatePipe 使用FILE_SYNCHRONOUS_IO_NONALERT 选项创建管道对 - 仅因为此 api 返回的此句柄不能用于异步操作。不幸的是 CreatePipe 没有参数来改变这种行为,但我们可以自己做这个任务
  • @CodyGray - 当然我们可以设置一些非默认的安全描述符,但是任何 SD 都不能限制只有子进程的访问。拥有SE_TAKE_OWNERSHIP_PRIVILEGE 的人也可以更改管道上的 SD。从另一面来看存在意义,所以担心只有子进程可以访问管道

标签: windows ipc named-pipes nonblocking


【解决方案1】:

可以使用lpSecurityAttributes 参数显式地将ACL 分配给新管道。这将允许您确保,如果其他用户登录,他们无法连接到管道。

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

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

注意:

  • 您应该在创建管道时使用FILE_FLAG_FIRST_PIPE_INSTANCE 标志,以确保您知道是否存在名称冲突。

  • 出于显而易见的原因,您还应该使用PIPE_REJECT_REMOTE_CLIENTS

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

  • 以同一用户或管理用户身份运行的恶意进程可能潜在地干扰您的连接(无论您是否设置了 ACL)但由于任何此类恶意进程也可能将恶意代码直接注入父级和/或子级,因此无需担心。攻击者已经在the air-tight hatchway的错误一边;锁窗户对你没有任何好处。

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

  • An anonymous pipe is implemented as a named pipe with a unique name,因此使用命名管道实际上并没有丢失任何东西。原则上,攻击者可以像使用命名管道一样轻松地在匿名管道中使用中间人。(编辑:根据 RbMm,这不再是正确的。)

【讨论】:

  • “匿名管道是使用具有唯一名称的命名管道实现的”——这仅在 xp/win2003 中是正确的。但从 vista 开始 - 匿名管道已经没有名字了。他们是如何创造的——在我的回答中。所以从 vista 开始(以及在所有最新系统上)可能创建无法按名称打开的匿名管道。不幸的是 CreatePipe 没有创建异步管道的参数,并且限制一个管道只写,另一个只读。但如果使用本机 api - 从 vista 开始可能自己创建真正的匿名管道
  • ^ 你知道官方提到过这个事实吗?我没看过。
  • 博客链接好像失效了。有人可以复活它吗?
【解决方案2】:

匿名管道当然完全支持异步(重叠)操作。是否支持异步操作 - 仅取决于在调用 ZwCreateNamedPipeFileZwOpenFile 中使用的 FILE_SYNCHRONOUS_IO_[NO]NALERT,但不取决于哪个名称(或空)具有管道。 CreatePipe 使用 FILE_SYNCHRONOUS_IO_NONALERT 选项创建管道对 - 仅因为此 api 返回的此句柄不能用于异步操作。不幸的是CreatePipe 没有参数来改变这种行为,但我们可以自己做这个任务

从 vista 开始,我们可以创建匿名(未命名)和异步管道对,但为此您需要使用 ndll api。下一个代码几乎类似于CreatePipe 内部代码,除了我创建异步管道对。

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

注意 hClientPipe 创建为 Inherited - 因此可以将其传递给子进程。同样,当您将在ConnectNamedPipe 中使用hServerPipe 时,您会得到FALSEGetLastError() == ERROR_PIPE_CONNECTED(因为客户端已经连接)/或者如果您将使用FSCTL_PIPE_LISTEN - 你得到STATUS_PIPE_CONNECTED - 这真的不是错误,而是好的代码

【讨论】:

    猜你喜欢
    • 2010-12-18
    • 1970-01-01
    • 2018-07-10
    • 2012-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-22
    相关资源
    最近更新 更多