Ich verwalte eine Gentoo Hardened-Box, die /bin/ping
Dateifunktionen verwendet, um die Notwendigkeit von setuid-root-Binärdateien (z. B. CAP_NET_RAW usw.) zum größten Teil zu beseitigen .
Tatsächlich ist die einzige Binärdatei, die ich noch habe, die folgende:
abraxas ~ # find / -xdev -type f -perm -u=s
/usr/lib64/misc/glibc/pt_chown
abraxas ~ #
Wenn ich das setuid-Bit entferne oder mein Root-Dateisystem wieder nosuid
einbinde, funktionieren sshd und GNU Screen nicht mehr, weil sie grantpt(3)
ihre Master-Pesudoterminals aufrufen und glibc anscheinend dieses Programm ausführt, um das Slave-Pseudoterminal darunter zu chownen und chmodieren /dev/pts/
, und GNU Screen kümmert sich darum, wann diese Funktion funktioniert scheitert.
Das Problem ist, dass in der Manpage für grantpt(3)
explizit angegeben ist, dass unter Linux bei devpts
eingehängtem Dateisystem keine solche Hilfsbinärdatei erforderlich ist. Der Kernel setzt automatisch die UID & GID des Slaves auf die reale UID & GID des Prozesses, der geöffnet wurde /dev/ptmx
(durch Aufrufen getpt(3)
).
Ich habe ein kleines Beispielprogramm geschrieben, um dies zu demonstrieren:
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main(void)
{
int master;
char slave[16];
struct stat slavestat;
if ((master = getpt()) < 0) {
fprintf(stderr, "getpt: %m\n");
return 1;
}
printf("Opened a UNIX98 master terminal, fd = %d\n", master);
/* I am not going to call grantpt() because I am trying to
* demonstrate that it is not necessary with devpts mounted,
* the owners and mode will be set automatically by the kernel.
*/
if (unlockpt(master) < 0) {
fprintf(stderr, "unlockpt: %m\n");
return 2;
}
memset(slave, 0, sizeof(slave));
if (ptsname_r(master, slave, sizeof(slave)) < 0) {
fprintf(stderr, "ptsname: %m\n");
return 2;
}
printf("Device name of slave pseudoterminal: %s\n", slave);
if (stat(slave, &slavestat) < 0) {
fprintf(stderr, "stat: %m\n");
return 3;
}
printf("Information for device %s:\n", slave);
printf(" Owner UID: %d\n", slavestat.st_uid);
printf(" Owner GID: %d\n", slavestat.st_gid);
printf(" Octal mode: %04o\n", slavestat.st_mode & 00007777);
return 0;
}
Beobachten Sie es in Aktion, während das setuid-Bit des oben genannten Programms entfernt ist:
aaron@abraxas ~ $ id
uid=1000(aaron) gid=100(users) groups=100(users)
aaron@abraxas ~ $ ./ptytest
Opened a UNIX98 master terminal, fd = 3
Device name of slave pseudoterminal: /dev/pts/17
Information for device /dev/pts/17:
Owner UID: 1000
Owner GID: 100
Octal mode: 0620
Ich habe nur ein paar Ideen, wie ich dieses Problem umgehen kann:
1) Ersetzen Sie das Programm durch ein Skelett, das einfach 0 zurückgibt.
2) Patch grantpt () in meiner libc, um nichts zu tun.
Ich kann beide automatisieren, aber hat jemand eine Empfehlung für eine über die andere, oder Empfehlungen, wie man dies sonst lösen kann?
Sobald dies gelöst ist, kann ich endlich mount -o remount,nosuid /
.
quelle
pty
(wie sie sollen) sondern nach dem Programm?Antworten:
Wenn Ihre Glibc einigermaßen aktuell ist und devpts korrekt eingerichtet ist, sollte es nicht nötig sein, den
pt_chown
Helfer überhaupt aufzurufen .Möglicherweise stößt du auf ein bekanntes / potenzielles Problem beim Entfernen von setuid-root von
pt_chown
.grantpt()
unterstütztdevfs
von glibc-2.7 , wurden Änderungen in glibc-2.11 vorgenommen, so dass statt explizit zu prüfenDEVFS_SUPER_MAGIC
, ob Arbeit erforderlich ist, bevor versucht wirdchown()
oder auf das Aufrufen zurückgegriffen wirdpt_chown
.Von
glibc-2.17/sysdeps/unix/grantpt.c
Eine ähnliche Zeilengruppe wird zum Überprüfen der GID und der Berechtigungen verwendet. Der Haken ist, dass uid, gid und mode den Erwartungen entsprechen müssen (you, tty und genau 620; bestätigen mit
/usr/libexec/pt_chown --help
). Wenn dies nichtchown()
der Fall ist (was die Fähigkeiten CAP_CHOWN, CAP_FOWNER der aufrufenden Binärdatei / des aufrufenden Prozesses erfordern würde), wird versucht, daspt_chown
externe Hilfsprogramm (das setuid-root sein muss) zu verwenden , wenn dies fehlschlägt . Umpt_chown
Fähigkeiten nutzen zu können, muss sie (und damit Ihre Glibc) mit kompiliert worden seinHAVE_LIBCAP
. Es sieht jedoch so aus , als obpt_chown
(ab glibc-2.17 und wie Sie bereits bemerkt haben, obwohl Sie die Version nicht angegeben haben) fest programmiert ist, umgeteuid()==0
unabhängig vomHAVE_LIBCAP
relevanten Code Folgendes zu wollenglibc-2.17/login/programs/pt_chown.c
:(Wenn
geteuid()==0
ich erwarte, bevor ich versuche, Fähigkeiten zu nutzen, scheint das nicht wirklich im Geiste der Fähigkeiten zu sein, würde ich damit fortfahren, einen Fehler in dieser zu protokollieren.)Eine mögliche Problemumgehung könnte darin bestehen, den betroffenen Programmen CAP_CHOWN und CAP_FOWNER zuzuweisen, aber das kann ich wirklich nicht empfehlen, da Sie das natürlich nicht auf ptys beschränken können.
Wenn das nicht hilft, lösen Sie es, das Patchen
sshd
undscreen
ist etwas weniger unangenehm als glibc Patchen. Da das Problem jedoch in glibc liegt, wäre ein saubererer Ansatz die selektive Verwendung der DLL-Injektion zur Implementierung eines Dummygrantpt()
.quelle