A flaw was found in Cockpit. A local authenticated user with control over a target account's home directory can exploit a privileged symlink dereference vulnerability in the `ssh-add-public-key.sh` helper. When this helper runs with elevated privileges, it can be tricked into following attacker-controlled symlinks within the `.ssh` or `authorized_keys` paths. This allows the attacker to arbitrarily change file ownership and modes, potentially leading to local privilege escalation and impacting the integrity, confidentiality, and availability of the system.
AI_ONLY_REPORT
package: cockpit-356-1.el10
------
Summary: Privileged Symlink Dereference in
`pkg/users/ssh-add-public-key.sh` Allows Arbitrary Ownership/Mode Changes:
the privileged add-key helper follows attacker-controlled `.ssh` and
`authorized_keys` symlinks, allowing attacker-chosen ownership changes and
related mode changes when the helper runs with an active privileged
bridge/root context.
Requirements to exploit: A local authenticated user must be able to control
the target account's home directory contents and must get the helper to run
with elevated privileges, such as in an active privileged Cockpit session.
The issue is not arbitrary `home_dir` injection; it arises from symlink
manipulation inside the configured home path. Without a privileged
bridge/root context, the same code path does not cross a security boundary.
Component affected: `cockpit-356-1.el10` Users "Add public key" helper,
`pkg/users/ssh-add-public-key.sh`, invoked from
`pkg/users/authorized-keys.js`
Version affected: `cockpit-356-1.el10` when the Users "Add public key"
workflow is executed with an active privileged bridge/root context
Patch available: no released package fix established; proposed patch
included below
Version fixed: unknown
Upstream coordination: Not notified.
CVSS: CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H - 7.8 (HIGH)
AV:L - The attacker needs a local authenticated account whose home
directory contents they can control.
AC:L - Preparing the required symlink state is straightforward and does
not require races or special timing.
PR:L - Low privileges are sufficient before exploitation.
UI:R - The vulnerable add-key action must be invoked in a session where
the helper actually has privileged/root execution context.
S:U - The vulnerable component and the impacted resources are under the
same host security authority.
C:H - Redirected privileged file handling can expose protected files or
make them accessible to the attacker.
I:H - Attacker-chosen ownership changes on sensitive paths can directly
break privilege boundaries and enable further unauthorized modification.
A:H - Ownership or mode changes on critical paths can disrupt services
or system operation.
Impact: Important. Based on Red Hat's severity guidance, this issue can
allow a local authenticated user to gain additional privileges by
redirecting privileged filesystem operations to attacker-chosen paths. That
is a direct integrity boundary break with potentially severe
confidentiality and availability consequences once triggered. It is not
Critical because exploitation is not remote or unauthenticated and requires
both user interaction and a privileged execution context.
Embargo: yes
Reason: The issue provides a straightforward local privilege-escalation
technique when the affected workflow is used in a privileged session, and
there is no released fix yet.
Acknowledgement: Aisle Research
Vulnerability Details: The helper script performs privileged operations in
`$2/.ssh` without checking whether `.ssh` or `authorized_keys` are symlinks:
```sh
mkdir -p "$2/.ssh"
cd "$2/.ssh"
chown $1 .
touch authorized_keys 2> /dev/null || true
chown $1 authorized_keys 2> /dev/null || true
sed -i -e '$a\' authorized_keys
cat >> authorized_keys
chown $1 authorized_keys 2> /dev/null || true
chmod 600 authorized_keys
```
The Users page reaches this helper through `cockpit.script(adder,
[user_name, home_dir], { superuser: "try", err: "message" })`, and the
add-key action is exposed when `user == current_user |
!!superuser.allowed`. The `home_dir` value comes from the account record,
so the problem is not arbitrary path input from the UI; it is privileged
dereference of attacker-controlled symlinks inside the configured home path.
If `.ssh` is a symlink to an attacker-chosen directory, `cd "$2/.ssh"` and
`chown $1 .` operate on the symlink target directory and can change its
ownership under elevated privileges. Subsequent `touch`, `chown`, and
`chmod` operations then act within that dereferenced location. An
`authorized_keys` symlink can also influence file handling in that
directory, although the exact final file state depends on how the
underlying utilities handle in-place edits. The core issue is that
privileged filesystem changes are performed on attacker-controlled paths
without rejecting symlinks.
Steps to reproduce: The following reproducer demonstrates the deterministic
directory-ownership change through a symlinked `.ssh` directory without
relying on tool-specific in-place editing behavior.
1. Prepare a safe victim path and an attacker-controlled home directory:
```bash
sudo rm -rf /tmp/ssh-poc-home /tmp/ssh-poc-target
sudo mkdir -p /tmp/ssh-poc-home /tmp/ssh-poc-target
sudo chown root:root /tmp/ssh-poc-target
ln -s /tmp/ssh-poc-target /tmp/ssh-poc-home/.ssh
```
2. Confirm the initial owner:
```bash
stat -c '%U:%G %n' /tmp/ssh-poc-target
```
3. Run the helper as root with a benign test key:
```bash
printf 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAITestKeyForPoC\n' | \
sudo /bin/sh pkg/users/ssh-add-public-key.sh nobody /tmp/ssh-poc-home
```
4. Check the target directory again:
```bash
stat -c '%U:%G %n' /tmp/ssh-poc-target
```
Expected result: the owner of `/tmp/ssh-poc-target` changes from `root` to
`nobody`, demonstrating that the privileged helper followed the attacker's
`.ssh` symlink and applied `chown` to the target directory.
Mitigation: Until a fix is available, avoid using the Users "Add public
key" workflow in a privileged session for untrusted accounts, and verify
that the target account's `.ssh` directory and `authorized_keys` path are
not symlinks before using the feature. Administratively managed `.ssh`
contents that are not attacker-controlled reduce exposure.
Proposed Fix: A minimal hardening change is to reject symlinked `.ssh` and
`authorized_keys` paths before performing privileged filesystem operations,
canonicalize the working directory with `cd -P`, and use `chown -h`
defensively.
```diff
— a/pkg/users/ssh-add-public-key.sh
+++ b/pkg/users/ssh-add-public-key.sh
@@
set -euf
-mkdir -p "$2/.ssh"
-cd "$2/.ssh"
+user="$1"
+home="$2"
+ssh_dir="$home/.ssh"
+
+mkdir -p – "$ssh_dir"
+[ -d "$ssh_dir" ] || { echo "Invalid .ssh directory: $ssh_dir" >&2; exit
1; }
+[ -L "$ssh_dir" ] && { echo "Refusing symlinked .ssh directory: $ssh_dir"
>&2; exit 1; }
+cd -P – "$ssh_dir"
-chown $1 .
+[ -e authorized_keys ] && [ -L authorized_keys ] && {
+ echo "Refusing symlinked authorized_keys" >&2
+ exit 1
+}
touch authorized_keys 2> /dev/null || true
-chown $1 authorized_keys 2> /dev/null || true
+[ -L authorized_keys ] && {
+ echo "Refusing symlinked authorized_keys" >&2
+ exit 1
+}
+chown -h "$user" .
+chown -h "$user" authorized_keys 2> /dev/null || true
sed -i -e '$a\' authorized_keys
cat >> authorized_keys
-chown $1 authorized_keys 2> /dev/null || true
+chown -h "$user" authorized_keys 2> /dev/null || true
chmod 600 authorized_keys
```
------
This report was generated using AI technology. Always review AI-generated
content prior to use
AI_ONLY_REPORT package: cockpit-356-1.el10 ------ Summary: Privileged Symlink Dereference in `pkg/users/ssh-add-public-key.sh` Allows Arbitrary Ownership/Mode Changes: the privileged add-key helper follows attacker-controlled `.ssh` and `authorized_keys` symlinks, allowing attacker-chosen ownership changes and related mode changes when the helper runs with an active privileged bridge/root context. Requirements to exploit: A local authenticated user must be able to control the target account's home directory contents and must get the helper to run with elevated privileges, such as in an active privileged Cockpit session. The issue is not arbitrary `home_dir` injection; it arises from symlink manipulation inside the configured home path. Without a privileged bridge/root context, the same code path does not cross a security boundary. Component affected: `cockpit-356-1.el10` Users "Add public key" helper, `pkg/users/ssh-add-public-key.sh`, invoked from `pkg/users/authorized-keys.js` Version affected: `cockpit-356-1.el10` when the Users "Add public key" workflow is executed with an active privileged bridge/root context Patch available: no released package fix established; proposed patch included below Version fixed: unknown Upstream coordination: Not notified. CVSS: CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H - 7.8 (HIGH) AV:L - The attacker needs a local authenticated account whose home directory contents they can control. AC:L - Preparing the required symlink state is straightforward and does not require races or special timing. PR:L - Low privileges are sufficient before exploitation. UI:R - The vulnerable add-key action must be invoked in a session where the helper actually has privileged/root execution context. S:U - The vulnerable component and the impacted resources are under the same host security authority. C:H - Redirected privileged file handling can expose protected files or make them accessible to the attacker. I:H - Attacker-chosen ownership changes on sensitive paths can directly break privilege boundaries and enable further unauthorized modification. A:H - Ownership or mode changes on critical paths can disrupt services or system operation. Impact: Important. Based on Red Hat's severity guidance, this issue can allow a local authenticated user to gain additional privileges by redirecting privileged filesystem operations to attacker-chosen paths. That is a direct integrity boundary break with potentially severe confidentiality and availability consequences once triggered. It is not Critical because exploitation is not remote or unauthenticated and requires both user interaction and a privileged execution context. Embargo: yes Reason: The issue provides a straightforward local privilege-escalation technique when the affected workflow is used in a privileged session, and there is no released fix yet. Acknowledgement: Aisle Research Vulnerability Details: The helper script performs privileged operations in `$2/.ssh` without checking whether `.ssh` or `authorized_keys` are symlinks: ```sh mkdir -p "$2/.ssh" cd "$2/.ssh" chown $1 . touch authorized_keys 2> /dev/null || true chown $1 authorized_keys 2> /dev/null || true sed -i -e '$a\' authorized_keys cat >> authorized_keys chown $1 authorized_keys 2> /dev/null || true chmod 600 authorized_keys ``` The Users page reaches this helper through `cockpit.script(adder, [user_name, home_dir], { superuser: "try", err: "message" })`, and the add-key action is exposed when `user == current_user | !!superuser.allowed`. The `home_dir` value comes from the account record, so the problem is not arbitrary path input from the UI; it is privileged dereference of attacker-controlled symlinks inside the configured home path. If `.ssh` is a symlink to an attacker-chosen directory, `cd "$2/.ssh"` and `chown $1 .` operate on the symlink target directory and can change its ownership under elevated privileges. Subsequent `touch`, `chown`, and `chmod` operations then act within that dereferenced location. An `authorized_keys` symlink can also influence file handling in that directory, although the exact final file state depends on how the underlying utilities handle in-place edits. The core issue is that privileged filesystem changes are performed on attacker-controlled paths without rejecting symlinks. Steps to reproduce: The following reproducer demonstrates the deterministic directory-ownership change through a symlinked `.ssh` directory without relying on tool-specific in-place editing behavior. 1. Prepare a safe victim path and an attacker-controlled home directory: ```bash sudo rm -rf /tmp/ssh-poc-home /tmp/ssh-poc-target sudo mkdir -p /tmp/ssh-poc-home /tmp/ssh-poc-target sudo chown root:root /tmp/ssh-poc-target ln -s /tmp/ssh-poc-target /tmp/ssh-poc-home/.ssh ``` 2. Confirm the initial owner: ```bash stat -c '%U:%G %n' /tmp/ssh-poc-target ``` 3. Run the helper as root with a benign test key: ```bash printf 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAITestKeyForPoC\n' | \ sudo /bin/sh pkg/users/ssh-add-public-key.sh nobody /tmp/ssh-poc-home ``` 4. Check the target directory again: ```bash stat -c '%U:%G %n' /tmp/ssh-poc-target ``` Expected result: the owner of `/tmp/ssh-poc-target` changes from `root` to `nobody`, demonstrating that the privileged helper followed the attacker's `.ssh` symlink and applied `chown` to the target directory. Mitigation: Until a fix is available, avoid using the Users "Add public key" workflow in a privileged session for untrusted accounts, and verify that the target account's `.ssh` directory and `authorized_keys` path are not symlinks before using the feature. Administratively managed `.ssh` contents that are not attacker-controlled reduce exposure. Proposed Fix: A minimal hardening change is to reject symlinked `.ssh` and `authorized_keys` paths before performing privileged filesystem operations, canonicalize the working directory with `cd -P`, and use `chown -h` defensively. ```diff — a/pkg/users/ssh-add-public-key.sh +++ b/pkg/users/ssh-add-public-key.sh @@ set -euf -mkdir -p "$2/.ssh" -cd "$2/.ssh" +user="$1" +home="$2" +ssh_dir="$home/.ssh" + +mkdir -p – "$ssh_dir" +[ -d "$ssh_dir" ] || { echo "Invalid .ssh directory: $ssh_dir" >&2; exit 1; } +[ -L "$ssh_dir" ] && { echo "Refusing symlinked .ssh directory: $ssh_dir" >&2; exit 1; } +cd -P – "$ssh_dir" -chown $1 . +[ -e authorized_keys ] && [ -L authorized_keys ] && { + echo "Refusing symlinked authorized_keys" >&2 + exit 1 +} touch authorized_keys 2> /dev/null || true -chown $1 authorized_keys 2> /dev/null || true +[ -L authorized_keys ] && { + echo "Refusing symlinked authorized_keys" >&2 + exit 1 +} +chown -h "$user" . +chown -h "$user" authorized_keys 2> /dev/null || true sed -i -e '$a\' authorized_keys cat >> authorized_keys -chown $1 authorized_keys 2> /dev/null || true +chown -h "$user" authorized_keys 2> /dev/null || true chmod 600 authorized_keys ``` ------ This report was generated using AI technology. Always review AI-generated content prior to use