cli/connhelper: quote ssh arguments to prevent shell injection by thaJeztah · Pull Request #6147 · docker/cli (original) (raw)
When connecting to a remote daemon through an ssh:// connection,
the CLI connects with the remote host using ssh, executing the
docker system dial-stdio command on the remote host to connect
to the daemon API's unix socket.
By default, the docker system dial-stdio command connects with the
daemon using the default location (/var/run/docker.sock), or the
location as configured on the remote host.
Commit 25ebf0e (included in docker CLI v24.0.0-rc.2 and higher) introduced a feature to allow the location of the socket to be specified through the host connection string, for example:
DOCKER_HOST='ssh://example.test/run/custom-docker.sock'The custom path is included as part of the ssh command executed from the client machine to connect with the remote host. THe example above would execute the following command from the client machine;
ssh -o ConnectTimeout=30 -T -- example.test docker --host unix:///run/custom-docker.sock system dial-stdiossh executes remote commands in a shell environment, and no quoting was in place, which allowed for a connection string to include additional content, which would be expanded / executed on the remote machine.
For example, the following example would execute echo hello > /hello.txt
on the remote machine;
export DOCKER_HOST='ssh://example.test/var/run/docker.sock $(echo hello > /hello.txt)'
docker info
# (output of docker info from the remote machine)While this doesn't allow the user to do anything they're not already able to do so (by directly using the same SSH connection), the behavior is not expected, so this patch adds quoting to prevent such URLs from resulting in expansion.
This patch updates the cli/connhelper and cli/connhelper/ssh package to quote parameters used in the ssh command to prevent code execution and expansion of variables on the remote machine. Quoting is also applied to other parameters that are obtained from the DOCKER_HOST url, such as username and hostname.
- The existing
Spec.Args()method inthe cli/connhelper/ssh package now quotes arguments, and returns a nil slice when failing to quote. Users of this package should therefore check the returned arguments before consuming. This method did not provide an error-return, and adding one would be a breaking change. - A new
Spec.Commandmethod is introduced, which (unlike theSpec.Args()method) provides an error return. Users are recommended to use this new method instead of theSpec.Args()method.
Some minor additional changes in behavior are included in this patch;
- Connection URLs with a trailing slash (e.g.
ssh://example.test/) would previously result inunix:///being used as custom socket path. After this patch, the trailing slash is ignored, and no custom socket path is used. - Specifying a remote command is now required. When passing an empty
remote command,
Spec.Args()now results in anilvalue to be returned (or anno remote command specifiederror when usingSpec.Comnmand().
Signed-off-by: Sebastiaan van Stijn github@gone.nl