[PATCH] remote: block use of URI transport in scheme & query parameters

Daniel P. Berrangé via Devel posted 1 patch 1 week, 2 days ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/libvirt tags/patchew/20260716125007.1627140-1-berrange@redhat.com
src/remote/remote_daemon_dispatch.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
[PATCH] remote: block use of URI transport in scheme & query parameters
Posted by Daniel P. Berrangé via Devel 1 week, 2 days ago
From: Daniel P. Berrangé <berrange@redhat.com>

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 <redteam@telekom.de>
Fixes: CVE-2026-15268
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 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

Re: [PATCH] remote: block use of URI transport in scheme & query parameters
Posted by Peter Krempa via Devel 1 week, 2 days ago
On Thu, Jul 16, 2026 at 13:50:07 +0100, Daniel P. Berrangé via Devel wrote:
> From: Daniel P. Berrangé <berrange@redhat.com>
> 
> 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 <redteam@telekom.de>
> Fixes: CVE-2026-15268
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>  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
> 

Reviewed-by: Peter Krempa <pkrempa@redhat.com>