【问题标题】:How to identify/authorize the sender of a message in a named pipe? (CreateNamedPipe)如何在命名管道中识别/授权消息的发送者? (创建命名管道)
【发布时间】:2017-02-03 15:08:17
【问题描述】:

我已经使用命名管道在两个应用程序之间创建了通信。 第一个应用程序使用CreateNamedPipe 创建一个命名管道,并读取第二个应用程序发送的带有ReadFile 的接收消息。两个应用程序都能够按照预期的方式进行通信。

是否有可能以某种方式识别收到的消息的发件人? 如果没有某种标识(例如获取发送者 exe 路径)或授权,其他所有应用程序都可以使用该管道向我的应用程序发送消息。

(编辑) 更多细节,因为在这种情况下似乎很重要:
创建管道的应用程序作为 Windows 服务运行。 两个应用程序在同一系统上本地运行。

【问题讨论】:

  • 您必须自己实现。管道是安全对象,但 Windows 的安全模型不是面向应用程序的,而是面向用户的。
  • 难道没有至少一种方法可以找出消息的来源吗?类似于通过命名管道发送消息的文件的句柄/名称/路径?
  • @CodeX 不直接。发送者必须在消息数据本身中识别自己。服务器唯一可以自行确定的是运行发送消息的应用程序的用户帐户。为此,服务器必须先impersonate the connected client,然后才能检索用户信息。如果服务器有足够的权限,它可能能够枚举本地系统上所有打开的句柄,查找该用户打开的任何句柄并指向您的服务器管道名称...
  • @CodeX ... 但这是一项非常复杂的任务,需要低级别的 API 和操作系统内部知识,并且无论如何只能用于本地进程,而不是网络上的远程进程。
  • ImpersonateNamedPipeClient 存在。也存在 undocumented FSCTL_PIPE_QUERY_CLIENT_PROCESS 通过使用它我们可以获得打开命名管道的进程的 id

标签: winapi named-pipes


【解决方案1】:

GetNamedPipeClientProcessId() 将为您提供客户端进程的进程 ID。然后,您可以使用OpenProcess() 打开该进程的句柄并调用GetModuleFileNameEx() 以确定该进程中正在运行的应用程序。然后,您可以以任何您认为最好的方式审查应用程序,例如,您可能想要检查 digital certificate 的身份,或者您可能更愿意只检查路径名是否符合您的预期。

请注意,尝试限制对特定应用程序而不是特定用户的访问永远不会是健壮的;攻击者总是可以控制已批准的应用程序并用他们自己的代码替换它的代码。基本上它不会超过减速带,但如果你觉得值得去做,它是可以做到的。


如果您真正想知道的是 user 连接了什么,您应该改用 cmets 中已经建议的 ImpersonateNamedPipeClient(),然后是 OpenThreadToken() 等等。或者更好的是,在创建命名管道时设置权限,以便首先只有授权用户才能连接。


既然您已经阐明客户端以提升的权限运行,我可以提出更具体的建议:同时执行上述两项。 配置命名管道的权限,以便只有管理员组的成员可以访问它;这将确保只有以提升权限运行的应用程序才能访问它。检查可执行文件也不会受到伤害,但它本身还不够,因为攻击者可以启动您的应用程序的副本,抑制请求的提升,并将他们自己的代码注入到进程中。 (或者,正如 conio 指出的那样,修改他们自己的进程,使其看起来好像正在运行您的可执行文件;GetModuleFileNameEx() 不打算用作安全措施,因此它不会努力避免欺骗。)

【讨论】:

  • GetNamedPipeClientProcessId 似乎正是我正在寻找的!我明天要写一些代码来测试它。关于安全方面:找出应用程序后,我将使用 WinVerifyTrust() 检查其签名。这样我就知道我的应用程序没有被修改。如果攻击者能够覆盖内存中的代码,那么系统肯定已经存在更大的问题......
  • 你的威胁模型是什么?关心连接的是什么应用程序而不是连接的是什么用户的唯一原因是,如果你想保护自己免受用户的伤害,这是行不通的,因为用户总是可以修改在他们自己的进程中运行的代码。
  • ...当然,这同样适用于在用户上下文中运行的任何恶意软件。
  • 威胁是恶意软件。我想避免用户系统上的某些恶意软件向我的服务发送消息/命令的一般可能性。基本思想是只信任我自己的应用程序。只要可执行文件没有被修改,我想信任它。
  • 攻击者可以启动您的应用程序,然后(例如)注入恶意 DLL,其方式与 this question 中显示的方式相同。您的代码将运行,但他的代码也会运行。更复杂的方法是使用CREATE_SUSPENDED 标志启动您的应用程序,并在让进程开始运行之前替换内存中的代码; Cygwin 做了类似的事情来实现 fork()。这些攻击都不需要提升权限,因为这两个进程在相同的用户上下文中运行。还有很多其他方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多