通过 UNIX 套接字传递凭据的安全问题

通过 UNIX 套接字传递凭据的安全问题

UNIX 套接字通常有一种机制来验证其对等进程。不过需要小心,以免副手攻击混乱。

例如,Linux 有两种通过 UNIX 套接字传递凭据的方法:SO_PASSCREDSO_PEERCREDSO_PEERCRED仅支持流套接字 或socketpair(2),并且用户身份源自有效凭证,并在连接套接字或创建套接字对时固定。 SO_PASSCRED另一方面,为每条消息再次生成,并且默认情况下从真实凭据派生。 FreeBSD 有类似的 API,但细节有所不同。

一般来说,进程使用的套接字要么由该进程创建,从父进程继承,要么通过 UNIX 套接字传递。如果套接字是由进程创建的,则进程可以明确地承担安全使用套接字的责任。对于继承和传递的套接字,SO_PEERCRED不会导致特殊问题,因为凭据是从创建者派生的。

SO_PASSCRED存在这样的问题:进程调用write(2)可能会无意中通过它们未创建或连接的套接字传递其凭据,并且写入的消息通常可以由创建者控制。在继承套接字的情况下,setuid/setgid 进程与其父进程将具有不同的凭据,但由于传递的凭据基于进程的真实凭据,因此父进程不应能够使用提升进程的凭据。

另一方面,如果 UNIX 套接字通过 UNIX 套接字传递,则接收者可能具有提升的真实凭据。在这种情况下,接收套接字的守护进程可能会被欺骗到write(2)它,即使该守护进程不知道对等点。

可以采取哪些预防措施来避免凭证被滥用?是否可以将不受信任的套接字安全地传递给守护进程?

  • SO_PEERCRED应尽可能使用服务。
  • 如果守护进程不打算接收套接字,它应该fstat(2)接收接收到的文件描述符并检查类型。
  • 特权守护进程可以SCM_CREDENTIALS在发送到不受信任的套接字时显式添加消息并使用非特权用户身份。
  • 服务进行身份验证SO_PASSCRED可以确保简单的write(2)凭据不是有效的使用。例如,可能需要辅助消息,或者困惑的代表不太可能遵循的多往返协议。

常用的守护进程如何解决这个问题?

相关内容