2013-04-12 8 views
5

Gibt es eine (kompatibel) Art und Weise zu Parodie (als root) der Unix-Socket (Dateisystem-Buchsen) Peer Anmeldeinformationen, die durch getsockopt() erhalten werden kann, Option SO_PEERCRED?UNIX-Sockets: Ist es möglich, getsockopt() SO_PEERCRED zu fälschen?

Hintergrund:
ich zu einer Server-Anwendung anschließen müssen (was ich nicht ändern kann), die die UID des Prozesses überprüft, die über SO_PEERCRED ihm verbindet. Ich möchte die Informationen spoofen, um in der Lage zu sein, mit der Anwendung als root zu verbinden, auch.

UPDATE

Um die Frage zu klären,:
Ich bin für eine nicht-invasive Art und Weise der Suche, dass der Server eine bestimmte Peer UID/GID sieht. Lösungen werden entmutigt, die den Kern (oder um die Verwendung von Kernel-Module), oder die ändert den Serverprozess oder dessen Belade-/Verknüpfungsprozess in irgendeiner Weise (LD_PRELOAD, Systemruf interceptions etc.) ändern müssen.

Grundsätzlich sollte die Lösung funktionieren, wenn auf einem beliebigen Linux (oder Unix im Allgemeinen) Server ohne besondere Anforderungen ausgeführt wird. Der Serverprozess wird möglicherweise bereits ausgeführt.

+1

Wenn Sie 'root' sind, warum nicht nur' setuid'? Sie können dies über einen vollständig kontrollierten untergeordneten Prozess tun, sodass Sie vermeiden können, dass die Berechtigung tatsächlich verloren geht. – nneonneo

+0

Ich bin mir nicht sicher, aber unter Linux gibt es einen oktalen Wert Präfix Flags in '/ proc//fdinfo/'. – alk

+1

Können Sie den Start des Serverprozesses steuern, dh können Sie ein LD_PRELOAD verwenden, um die Bibliotheksfunktion/syscall thunk zu ändern, um die gemeldeten Anmeldeinformationen zu ändern? –

Antwort

-1

Nein. Der Grund dafür ist, dass der Mechanismus, der die UID und GID des Peers liefert, intern im Kernel ist, und Sie können den Kernel nicht spoofieren! Der Kernel verwendet die PID des Peers, um die effektiven Anmeldeinformationen des Peers abzuleiten. Dies geschieht, wenn eine Seite eine connect auf dem Sockel macht. Siehe den Anruf zu copy_peercred() von unix_stream_connect() in net/unix/af_unix.c. Es gibt keine Möglichkeit, dass der Peer die Daten, die er sendet, oder den Socket, der den Kernel davon überzeugen wird, dass die PID des Peers nicht das ist, die er ist, ändern kann. Dies unterscheidet sich von AF_INET-Sockets, bei denen der Kernel keine internen Kenntnisse über den Prozess des Peers besitzt und nur die Daten in den IP-Paket-Headern sehen kann, die der Peer sendet.

Die einzige Sache, die Sie tun können, um diesen Effekt zu erhalten, ist, die effektive UID des Peer-Prozesses zu root oder was UID/GID Sie wollen, und dafür benötigen Sie entweder Root-Passwort oder sudo Privilegien.

+1

Aber Sie * können * den Kernel spoofen - als root können Sie das Verhalten des laufenden Kernels ändern, indem Sie ein Modul laden. –

+0

@ChrisStratton: Kein Modul, das Sie schreiben, kann das Verhalten von Unix-Domain-Sockets ändern. –

+0

Sie sind ** streng ** falsch, das zu glauben. Der einfachste Ansatz wäre ein Modul, das den Systemaufruf an der Stelle des Versands direkt nach dem Eintritt in den Kernel umleitet, aber auch die Modifizierung der Interna der Unix-Domain-Socket-Implementierung ist letztendlich eine Option. Denken Sie daran, etwas, das nicht exportiert wird, ist nicht * geschützt *, es ist nur * schwieriger zu lokalisieren * - und nicht alles so schwer, wenn die Quelle geöffnet ist und die Build-Einstellungen wahrscheinlich bekannt sind. –

3

Sie sind auf dem richtigen Weg. Ein Root-Prozess hat die Rechte, solche Dinge zu fälschen. Das Problem ist nur, dass SO_PEERCRED keinen Mechanismus oder eine API für einen Prozess bereitstellt, um anzugeben, welche Identität dem Peer präsentiert werden soll.

Zwei Dinge, die Sie tun können:

  1. Vorübergehend Wurzel fallen (setreuid(desired,-1)), wenn Sie den connect Anruf. Eine Unix-Domain-Verbindung wird zu dem Zeitpunkt, zu dem der Prozess connect (und listen in die entgegengesetzte Richtung) aufgerufen wird, mit den Anmeldeinformationen des Peers versehen. SO_PEERCRED teilt Ihnen im Moment die Anmeldeinformationen des Peers nicht mit. Dann können Sie root fortsetzen.

  2. Besser, verwenden Sie eine andere API. Die Message-Passing-API ermöglicht es einem Prozess auszuwählen, welche Identität einem Peer angezeigt werden soll. Rufen Sie sendmsg mit einem struct cmsg auf, der die Anmeldeinformationen enthält, die Sie senden möchten. Der Kernel ignoriert die von einem nichtprivilegierten Benutzer angegebenen Anmeldeinformationen und stellt immer sicher, dass die andere Seite die tatsächliche Identität sieht, aber ein privilegierter Prozess kann vorgeben, jemand anderes zu sein. Dies ist für Ihre Bedürfnisse besser geeignet, da das Ablegen und Wiedergewinnen von Root eine gefährliche Aktivität darstellt und in diesem Fall unnötig ist. Google für "SCM_CREDENTIALS" (oder "man -K" für es auf Ihrem System), um Code-Beispiele zu erhalten.

+1

Wenn der Server die SO_PASSCRED-Socket-Option nicht einstellt und die Anmeldeinformationen liest, funktioniert Lösung 2 nicht. Wenn nur SO_PEERCRED verwendet wird, sind Sie mit der einfachen, einmaligen PID-Authentifizierung beschäftigt. Für SO_PEERCRED Beispiel siehe http://man7.org/tlpi/code/online/dist/sockets/scm_cred_recv.c.html. In jedem Fall ist es für root, SCM_CREDENTIALS zu verwenden, um Privilegien zu senken, kaum "Spoofing". –

+1

OK, nennen Sie es sich "imitieren", dann ... Auch ich erinnere mich, dass Sie, wenn Sie einige Anmeldeinformationen senden, nicht am anderen Ende SO_PASSCRED setzen müssen; Sie sollten für Sie in der Ausgabe "recvmsg" ankommen. Vielleicht hängt das Betriebssystem davon ab? Ich neige nicht dazu, Linux zu benutzen. SO_PASSCRED ist normalerweise, wenn Sie Anmeldeinformationen auslesen möchten, aber die andere Seite schreibt sie nicht; es teilt dem Kernel mit, dass er die Anmeldeinformationen des Peers für jede Nachricht angibt (besonders schön für DGRAM-Sockets). –

+1

Lesen Sie das Beispiel, "Wir müssen die SO_PASSCRED-Socket-Option festlegen, um Anmeldeinformationen zu erhalten". Gleiches gilt für BSD/FreeBSD, wo die Option SCM_CREDS heißt. –

Verwandte Themen