Ich versuche zu verstehen, wie Linux-Fähigkeiten an einen Prozess weitergegeben werden, der exec()
von einem anderen ausgeführt wurde. Soweit ich gelesen habe, muss eine Fähigkeit im vererbbaren Set enthalten sein, damit sie nach der Ausführung erhalten bleibt. Ich bin mir jedoch nicht sicher, wie dieses Set gefüllt wird.
Mein Ziel ist es, ein Programm als normaler Benutzer ausführen zu können, für das normalerweise Root-Rechte erforderlich sind. Es muss die Fähigkeit haben, cap_dac_override
eine private Datei lesen zu können. Weitere Fähigkeiten möchte ich ihm nicht geben.
Hier ist mein Wrapper:
#include <unistd.h>
int main(int argc, char *argv[]) {
return execl("/usr/bin/net", "net", "ads", "dns", "register", "-P", NULL);
}
Dies funktioniert, wenn ich für die resultierende ausführbare Datei die Setuid-Berechtigung festlege:
~ $ sudo chown root: ./registerdns
~ $ sudo chmod u+s ./registerdns
~ $ ./registerdns
Successfully registered hostname with DNS
Ich würde jedoch lieber Capabilities statt Setuid verwenden. Ich habe versucht, die cap_dac_override
Capability im Wrapper festzulegen:
~ $ sudo setcap cap_dac_override=eip ./registerdns
~ $ ./registerdns
Failed to open /var/lib/samba/private/secrets.tdb
ERROR: Unable to open secrets database
Ich habe auch versucht, das Vererbungsflag für die cap_dac_override
Fähigkeit der net
ausführbaren Datei selbst zu setzen:
~ $ sudo setcap cap_dac_override=eip ./registerdns
~ $ sudo setcap cap_dac_override=i /usr/bin/net
~ $ ./registerdns
Failed to open /var/lib/samba/private/secrets.tdb
ERROR: Unable to open secrets database
Ich muss den Wrapper verwenden, um sicherzustellen, dass die Funktion nur bei Verwendung genau dieses Argumentsatzes verfügbar ist. Das net
Programm führt noch verschiedene andere Dinge aus, bei denen es gefährlich sein könnte, den Benutzern zu weitreichende Berechtigungen dafür zu erteilen.
Ich verstehe offensichtlich nicht, wie die Vererbung funktioniert. Ich kann nicht herausfinden, wie ich den Wrapper so einrichte, dass er seine Fähigkeiten an den Ersetzungsprozess weitergibt, damit dieser sie nutzen kann. Ich habe die Manpage und zahllose andere Dokumente darüber gelesen, wie es funktioniert.sollenArbeit, und ich dachte, ich würde das tun, was es beschreibt.
Antwort1
Es stellt sich heraus, dass die Einstellung +i auf dem Wrappernichtfüge die Fähigkeit dem CAP_INHERITABLE
Set für den Wrapper-Prozess hinzu, damit sie nicht durchgereicht wird exec
. Ich musste daher vor dem Aufruf manuell CAP_DAC_OVERRIDE
hinzufügen :CAP_INHERITABLE
execl
#include <sys/capability.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv[]) {
cap_t caps = cap_get_proc();
printf("Capabilities: %s\n", cap_to_text(caps, NULL));
cap_value_t newcaps[1] = { CAP_DAC_OVERRIDE, };
cap_set_flag(caps, CAP_INHERITABLE, 1, newcaps, CAP_SET);
cap_set_proc(caps);
printf("Capabilities: %s\n", cap_to_text(caps, NULL));
cap_free(caps);
return execl("/usr/bin/net", "net", "ads", "dns", "register", "-P", NULL);
}
Zusätzlich musste ich cap_dac_override
die erlaubten Dateifunktionen um Folgendes ergänzen /usr/bin/net
und das effektive Bit setzen:
~ $ sudo setcap cap_dac_override=p ./registerdns
~ $ sudo setcap cap_dac_override=ei /usr/bin/net
~ $ ./registerdns
Capabilities = cap_dac_override+p
Capabilities = cap_dac_override+ip
Successfully registered hostname with DNS
Ich glaube, ich verstehe jetzt völlig, was passiert:
- Der Wrapper benötigt es
CAP_DAC_OVERRIDE
in seinem zulässigen Satz, damit er es zu seinem vererbbaren Satz hinzufügen kann. - Der vererbbare Prozesssatz des Wrappers unterscheidet sich von seinem vererbbaren Dateisatz. Daher ist die Einstellung +i für die Datei sinnlos. Der Wrapper muss using
CAP_DAC_OVERRIDE
/ explizit hinzufügen .CAP_INHERITABLE
cap_set_flag
cap_set_proc
- Die
net
Datei muss in ihrem vererbbaren Set habenCAP_DAC_OVERRIDE
, damit sie die Fähigkeit vom Wrapper tatsächlich in ihrCAP_PERMITTED
Set erben kann. Außerdem muss das effektive Bit gesetzt sein, damit es automatisch zu hochgestuft wirdCAP_EFFECTIVE
.
Antwort2
Ich denke, Sie brauchen beides:
setcap cap_dac_override+pe ./registerdns
setcap cap_dac_override+i /usr/bin/net
Die pe
aktivierten Flags registerdns
geben an, dass die Berechtigung durch Ausführen des Programms erworben wird. Die i
aktivierten Flags net
geben an, dass die Berechtigung vom aufrufenden Programm übernommen werden darf.