yabai
yabai copied to clipboard
Local privilege escalation with sudoers setup
Hi, at the end you can find my initial email to Åsmund and his reply.
Summary
The issue is regarding this part of the documentation. If you followed the documentation previously and did not include the sha256 hash of the yabai
binary in the sudoers file, it opens up the possibility for a local privilege escalation. Take a look at the email at the end if you want to know how and why it works.
Note: The documentation already includes the hint to embed the sha256 sum of the yabai binary to prevent this issue.
My current workaround:
Get the yabai
installation path:
which yabai
Get the hash of the yabai
binary:
shasum -a 256 /opt/homebrew/bin/yabai | cut -d' ' -f 1
Edit the /private/etc/sudoers.d/yabai
manually to look like this (replace YOUR_USER
, use the hash from the command above, and check the yabai path):
YOUR_USER ALL = (root) NOPASSWD: sha256:d76b3115ddcbd8f9bd297cda2cd777bd10f1d6db65fd2f7efb2d0336880fe9e0 /opt/homebrew/bin/yabai --load-sa
Now you can save the following bash script and run it manually after an upgrade of yabai
took place. It will recalculate the hash and replace it in the corresponding file. Use at your own risk.
#!/bin/bash
# calculate new hash for the binary
SHA256=$(shasum -a 256 /opt/homebrew/bin/yabai | cut -d' ' -f 1)
echo "New yabai hash: $SHA256"
# replace the hash in-place in the sudoers file
sudo sed -i '' -e 's/sha256:[[:alnum:]]*/sha256:'${SHA256}'/' /private/etc/sudoers.d/yabai
As I said in the email, I don't really know the inner workings of brew and hadn't had the time to look into it, so if someone knows a way how to automate this or some other way, please comment.
Initial email:
Hi Åsmund,
I recently installed yabai and noticed an issue while following the documentation. I thought I'll send you an email first instead of opening a public issue and addressing this.
The documentation 1 for running the yabai --load-sa
command as root using
the sudoers policy plugin introduces a local privilege escalation
vulnerability.
POC:
$ which yabai
/opt/homebrew/bin/yabai
$ cd /opt/homebrew/bin
$ mv yabai yabai.bak
$ echo '#/bin/bash\nid' > yabai
$ chmod +x yabai
$ sudo yabai --load-sa
Running sudo yabai --load-sa
now results in executing the bash script as root
without the need of a password.
To restore the yabai
setup, just rename yabai.bak
back to yabai
.
The problem is that the yabai executable is owned by the user and, therefore, the user can change it. This can be fixed by adding a hash of the valid yabai executable.
Quoting from the sudoers manpage (man sudoers
):
A command may be preceded by a Digest_List, a comma-separated list of one or more Digest_Spec entries. If a Digest_List is present, the command will only match successfully if it can be verified using one of the SHA-2 digests in the list. Starting with version 1.9.0, the ALL reserved word can be used in conjunction with a Digest_List. The following digest for‐ mats are supported: sha224, sha256, sha384, and sha512. The string may be specified in either hex or base64 format (base64 is more compact). There are several utilities capable of generating SHA-2 digests in hex format such as openssl, shasum, sha224sum, sha256sum, sha384sum, sha512sum.
For instance, adding a sha256 sum prevents this problem. The corresponding line
in the sudoers file /private/etc/sudoers.d/yabai
would look like this:
YOUR_USER ALL = (root) NOPASSWD: sha256:d76b3115ddcbd8f9bd297cda2cd777bd10f1d6db65fd2f7efb2d0336880fe9e0 /opt/homebrew/bin/yabai --load-sa
As the manpage states, instead of the hex value a shorter base64 representation of the hash can be used as well.
I don't know how homebrew works or if something similiar as "post-install"
scripts can be provided. If that's the case the following script can be run to
update the hash for the yabai
binary when the package is upgraded.
#!/bin/bash
# calculate new hash for the binary
SHA256=$(shasum -a 256 /opt/homebrew/bin/yabai | cut -d' ' -f 1)
echo "New yabai hash: $SHA256"
# replace the hash in-place in the sudoers file
sudo sed -i '' -e 's/sha256:[[:alnum:]]*/sha256:'${SHA256}'/' /private/etc/sudoers.d/yabai
The above script works on my M1 MacBook. Maybe it has to be adjusted for other
platforms if brew
can be run there, too.
If you have any questions, let me know.
/Max
And Åsmund's reply:
Hey,
You are correct; that is indeed an issue.
The wiki instructions should be updated include this information. From what I can tell it would not be possible to have the hash be updated automatically upon brew upgrade, as the sudoers file requires root privileges to be modified, which brew does not (and should not) have.
I do not have time to do this right away, but feel free to post this as a github issue, including my reply, so that people become aware and can perform preventative measures.
Regards, Åsmund