From: Daniel P. Berrangé <[email protected]>

The remote driver client supports specifying a transport in the URI
scheme component such as +ext, +unix, +tls, etc. This determines how
it should connect to the daemons. It strips this transport from the
scheme to create a plain driver name that it forwards on to the remote
server.

It also, however, supports a "name" URI parameter which can be used
to override the stripped URI that gets sent to the remote server.
Unfortunately there is no validation of the URI by the remote server,
so the URI override could include the transport in the scheme
component. When the remote server sees a transport in the URI scheme,
the connection gets diverted into the remote driver which then opens
another client connection.

When the "ext" transport is combined with the "command" URI parameter,
this allows the client to trick the server into running an arbitrary
command with the same privileges as the server. This can be abused
with a read-only connection to a privileged server in order to elevate
local privileges.

There is no a valid reason to accept a transport component in the
URI scheme received by the server, so validate this condition and
reject any connection that violates it.

This patch is derived from a proposal made by the reporter along
with their disclosure, but generalized to block all schemes, not
merely +ext and apply unconditionally to all connections not merely
read-only ones.

Reported-by: Deutsche Telekom Red Team <[email protected]>
Fixes: CVE-2026-15268
Signed-off-by: Daniel P. Berrangé <[email protected]>
---
 src/remote/remote_daemon_dispatch.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/src/remote/remote_daemon_dispatch.c 
b/src/remote/remote_daemon_dispatch.c
index 329853b6da..95ab173b7c 100644
--- a/src/remote/remote_daemon_dispatch.c
+++ b/src/remote/remote_daemon_dispatch.c
@@ -2135,6 +2135,31 @@ remoteDispatchProbeURI(bool readonly,
 }
 #endif /* VIRTPROXYD */
 
+static int
+remoteCheckPermittedConnURI(const char *uristr)
+{
+    g_autoptr(virURI) uri = NULL;
+
+    if (!(uri = virURIParse(uristr)))
+        return -1;
+
+    /*
+     * Use of a transport (eg "+ext") in the scheme can be used to
+     * trick the daemon into using the remote driver to connect to
+     * an arbitrary socket under the caller's control. The valid
+     * URIs from the remote driver client will never include a
+     * transport component, so always reject that attempt.
+     */
+    if (uri->scheme &&
+        strchr(uri->scheme, '+')) {
+        virReportError(VIR_ERR_OPERATION_DENIED,
+                       _("Remote URI '%1$s' is not permitted to include a 
transport"),
+                       uristr);
+        return -1;
+    }
+
+    return 0;
+}
 
 static int
 remoteDispatchConnectOpen(virNetServer *server G_GNUC_UNUSED,
@@ -2164,6 +2189,10 @@ remoteDispatchConnectOpen(virNetServer *server 
G_GNUC_UNUSED,
 
     name = args->name ? *args->name : NULL;
 
+    if (name && STRNEQ(name, "") &&
+        remoteCheckPermittedConnURI(name) < 0)
+        goto cleanup;
+
     /* If this connection arrived on a readonly socket, force
      * the connection to be readonly.
      */
-- 
2.55.0

Reply via email to