【问题标题】:UNIX sockets: Is it possible to spoof getsockopt() SO_PEERCRED?UNIX 套接字:是否可以欺骗 getsockopt() SO_PEERCRED?
【发布时间】:2013-04-05 03:47:03
【问题描述】:

是否有一种(兼容的)方法可以欺骗(以 root 身份)unix 套接字(文件系统套接字)对等凭据通过getsockopt()获得,选项SO_PEERCRED

背景:
我需要连接到一个服务器应用程序(我无法修改),它检查通过SO_PEERCRED 连接到它的进程的UID。我想伪造这些信息,以便能够连接到应用程序也以 root 身份

更新

澄清问题
我正在寻找一种非侵入性的方式让服务器看到特定的对等方UID/GID不鼓励需要更改内核(或使用内核模块)或更改服务器进程或其加载/链接进程的解决方案> 以任何方式(LD_PRELOAD、系统调用拦截等)。

基本上,该解决方案可以在没有任何特殊要求的任何 linux(或一般的 unix)服务器上运行时工作。服务器进程可能已经在运行。

【问题讨论】:

  • 如果你是root,为什么不只是setuid?你可以从一个完全受控的子进程中做到这一点,这样你就可以避免实际上失去特权。
  • 我不确定,但在 Linux 下,/proc/<pid>/fdinfo/<sd> 中有一个八进制值前缀标志。
  • 你能控制服务器进程的启动,即你能用一个LD_PRELOAD来修改库函数/syscall thunk来改变报告的凭据吗?
  • @MRalwasser:你所说的“恶搞”是什么意思?将服务器应用程序运行在具有修改内核或被黑客入侵的 Glibc 的不同服务器上会被视为“欺骗”。使用setuid 怎么样?那是“欺骗”吗?通常这些方法都不会被视为“恶搞”。

标签: c security sockets unix unix-socket


【解决方案1】:

你在正确的路线上。根进程有权欺骗这样的事情,问题只是 SO_PEERCRED 没有为进程提供任何机制或 API 来指定应该向对等方提供什么身份。

你可以做两件事:

  1. 在拨打connect 电话时暂时删除根目录 (setreuid(desired,-1))。在调用connect 的进程(以及listen 以另一种方式)时,unix 域连接被标记有对等方的凭据。 SO_PEERCRED 不会告诉您当前对等方的凭据。然后你就可以恢复root了。

  2. 更好,使用另一个 API。消息传递 API 允许进程选择要呈现给对等方的标识。使用包含您要发送的凭据的struct cmsg 调用sendmsg。内核将忽略非特权用户指定的凭据,并始终确保对方看到实际身份,但特权进程可以伪装成其他任何人。这更符合您的需求,因为删除和重新获得根是一项危险的活动,在这种情况下是不必要的。谷歌搜索“SCM_CREDENTIALS”(或“man -K”在您的系统上)以获取代码示例。

【讨论】:

  • 如果服务器未设置 SO_PASSCRED 套接字选项并读取凭据,则解决方案 2 将不起作用。如果它只使用 SO_PEERCRED,那么您将陷入简单的一次性 PID 身份验证。对于 SO_PEERCRED 示例,请参阅 man7.org/tlpi/code/online/dist/sockets/scm_cred_recv.c.html。无论如何,root 使用 SCM_CREDENTIALS 来降低权限几乎不是“欺骗”。
  • 好吧,那就叫它“冒充”吧……另外,我似乎记得如果你发送一些凭据,你不应该在另一端设置 SO_PASSCRED;他们应该在recvmsg 输出中为您到达。也许这取决于操作系统?我不倾向于使用linux。 SO_PASSCRED 通常用于当您想读出凭据但对方没有写入它们时;它告诉内核在每条消息中为您提供对等方的凭据(尤其适用于 DGRAM 套接字)。
  • 阅读示例,“我们必须设置 SO_PASSCRED 套接字选项才能接收凭据”。对于名为 SCM_CREDS 的 BSD/FreeBSD 也是如此。
【解决方案2】:

没有。原因是提供对等体的UID和GID的机制是内核内部的,你不能欺骗内核!内核使用对等体的 PID 来推断对等体的有效凭证。当一侧在套接字上执行connect 时,就会发生这种情况。请参阅 net/unix/af_unix.c 中的 unix_stream_connect()copy_peercred() 的调用。没有任何方法可以让对等方更改它发送的数据或让内核相信对等方的 PID 不是这样的套接字。这与 AF_INET 套接字不同,内核不知道对等方进程的内部知识,只能看到对等方发送的 IP 数据包头中的数据。

要获得此效果,您唯一可以做的就是将对等进程的有效 UID 设置为 root 或您想要的任何 UID/GID,为此您需要 root 密码或 sudo 权限。

【讨论】:

  • 但是您可以欺骗内核 - 作为 root,您可以通过加载模块来修改正在运行的内核的行为。
  • @ChrisStratton:您编写的任何模块都不能改变 Unix 域套接字的行为。
  • 严重错误地相信了这一点。最简单的方法是制作一个模块,该模块将在进入内核后在调度点重定向系统调用,但修改 unix 域套接字实现的内部结构最终也是一种选择。请记住,未导出的内容没有受保护,它只是更难定位 - 当源代码打开且构建设置可能已知时,并不是那么难。
  • 在其他可能性中,是的。但是那篇文章提出了一个非常错误的假设,即必须首先修改内核以导出 sys 调用表。这不是真的 - 有许多已知属性可以找到它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-27
  • 2012-10-09
  • 2015-09-15
相关资源
最近更新 更多