CVE-2017-8422
CVE-2017-8422
Einführung:
Die „K Desktop Environment“ (KDE) ist eine grafische Desktopumgebung für das X Window System. Die KDElibs-Pakete enthalten Kernellibrarys für die K Desktop Environment. In der Art und Weise, wie die KDElibs D-Bus-Nachrichten verarbeitet werden, wurde ein Fehler bei der Rechteausweitung gefunden. Ein lokaler Benutzer könnte diesen Fehler möglicherweise nutzen, um Root-Rechte zu erlangen, indem er eine Caller-ID fälscht und eine privilegierte Hilfsanwendung nutzt. (CVE-2017-8422).
Wir werden in diesem Blog das Gesamtproblem beschreiben, indem wir den smb4k-Code durchgehen und erklären, welche DBUS-Funktionen aufgerufen werden und wie sich ein bestimmter smb4k-Bug auf das Gesamtbild des KAuth-Fehlers abbildet.
Code Analyse:
Es gibt ein Problem mit smb4k, dass das KAuth-Framework verwendet und allen Argumenten vertraut, die an den Helfer übergeben werden:
ActionReply Smb4KMountHelper::mount(const QVariantMap &args)
{
...
command << args["mh_command"].toString();
command << args["mh_unc"].toString();
command << args["mh_mountpoint"].toString();
command << args["mh_options"].toStringList();
...
proc.setProgram(command);
// Run the mount process.
proc.start();
...
}
Dieser Code läuft als root, ausgelöst über DBUS-Aktivierung durch smb4k GUI-Code, der als Benutzer läuft, und die “args”, die vom Benutzer geliefert werden, über:
void Smb4KMountJob::slotStartMount()
{
...
Action::executeActions(actions, NULL, "net.sourceforge.smb4k.mounthelper");
...
}
nach dem Ausfüllen von “actions” (es gibt nur eine) mit dem richtigen Namen (net.sourceforge.smb4k.mounthelper.mount) und HelperID (net.sourceforge.smb4k.mounthelper), um die DBUS-Aktivierung auszulösen, sowie das Argumenten-Verzeichnis, das die Schlüssel/Wertpaare “mh_command” etc. enthält. Es ruft die Listenversion von Action::executeAction() [man beachte das nachgestellte ’s'] mit einer Ein-Element-Liste auf, aber das spielt keine Rolle. Wichtig ist hier, dass die Argumente von einem Code erstellt werden, der als Benutzer läuft - und möglicherweise bösartige Eingaben enthält - und von dem Hilfsprogramm ausgewertet werden, das als root läuft.
Der obige Aufruf endet bei DBusHelperProxy::executeAction(), immer noch auf der Seite des Aufrufers. Diese Funktion übersetzt ihn in einen DBUS-Methodenaufruf, der schließlich privilegiert ausgeführt wird und die folgende Schnittstelle hat:
<interface name="org.kde.kf5auth">
...
<method name="performAction" >
<arg name="action" type="s" direction="in" />
<arg name="callerID" type="ay" direction="in" />
<arg name="arguments" type="ay" direction="in" />
<arg name="r" type="ay" direction="out" />
</method>
...
</interface>
Im Gegensatz zu den Root-Helfer-DBUS-Schnittstellen selbst, die nicht zugänglich sind, ist die KAuth DBUS-Schnittstelle org.kde.kf5auth:
<busconfig>
<policy context="default">
<allow send_interface="org.kde.kf5auth"/>
<allow receive_sender="org.kde.kf5auth"/>
<allow receive_interface="org.kde.kf5auth"/>
</policy>
</busconfig>
Der Code für den eigentlichen Aufruf von user zu root lautet wie folgt:
void DBusHelperProxy::executeAction(const QString &action,
const QString &helperID, const QVariantMap &arguments)
{
...
QDBusMessage::createMethodCall(helperID, QLatin1String("/"),
QLatin1String("org.kde.kf5auth"), QLatin1String("performAction"));
QList<QVariant> args;
args << action << BackendsManager::authBackend()->callerID() << blob;
message.setArguments(args);
m_actionsInProgress.push_back(action);
QDBusPendingCall pendingCall = m_busConnection.asyncCall(message);
...
}
Dieser Code ruft die DBUS-Methode performAction() auf und übergibt das vom Benutzer bereitgestellte Argumenten Verzeichnis, das in unserem smb4k-Fall unter anderem den handgefertigten bösen “mh_command”-Schlüssel und auch andere Schlüssel/Wertpaare enthält.
Dabei gibt es zwei Probleme:
Der KAuth-Frameworks performAction()-Methode wird die CallerID vom Benutzer übergeben, und die Methode ist vom Benutzer aufrufbar. Dies erlaubt es, sich als beliebigen Anrufer zu maskieren und alle Polkit-Prüfungen zu umgehen, die möglicherweise später im KAuth Polkit-Backend über Aufrufe in. PolicyKitBackend::isCallerAuthorized(const QString &action,QByteArray callerID)
Das zweite Problem besteht darin, dass smb4k den Argumenten vertraut, die vom Benutzer und vom KAuth DBUS-Dienst(der als Root läuft) übergeben werden, an den Mount-Helfer DBUS-Dienst weitergeleitet werden, der ebenfalls als Root läuft, aber nicht von Benutzern kontaktiert werden darf. Das ist ein logischer Fehler. Es war wahrscheinlich nicht beabsichtigt, dass Benutzer die Funktion performAction() selbst aufrufen, es als Proxy für DBUS-Dienste verwenden und nebenbei Anrufer-IDs fälschen. Die CallerID sieht normalerweise so “:1.123” aus und ist ein eindeutiger DBUS-Name, der auf den Absender der Nachricht verweist. Sie können sich das wie die Quelladresse eines IP-Pakets vorstellen. Diese ID sollte über eine DBUS-Funktion ermittelt werden, während die Nachricht eintrifft, sodass sie tatsächlich vertrauenswürdig ist und als Subjekt für politische Autorisierungen bei der Verwendung von Systembus-Namen-Subjekten verwendet werden kann. Wenn man dem Aufrufer erlaubt, die Werte für diese ID willkürlich zu wählen, wird die ganze Idee der Authentifizierung und Autorisierung zunichtegemacht.
Lösung des Problems:
KAuth users sollen auf die neuste Version updaten:
# emerge --sync
# emerge --ask --oneshot --verbose ">=kde-frameworks/kauth-5.29.0-r1"
KDELibs users sollen auf die neuste Version updaten:
# emerge --sync
# emerge --ask --oneshot --verbose ">=kde-frameworks/kdelibs-4.14.32"
Oder man wendet folgende Patches an: