[GH-ISSUE #1158] Root priv esc via tmpfs TOCTOU #797

Closed
opened 2026-05-05 06:51:55 -06:00 by gitea-mirror · 4 comments
Owner

Originally created by @mcarpenter on GitHub (Mar 25, 2017).
Original GitHub issue: https://github.com/netblue30/firejail/issues/1158

There's a TOCTOU attack possible using --tmpfs now that it can be used on a user-controlled directory under $HOME (commit 22414adf2a). I have a working exploit for this that I can share with committers but the essence is:

  • Call firejail with --tmpfs pointing to a subdirectory of $HOME.
  • The validity of the tmpfs directory is checked early.
  • Whilst other flags are being processed, replace the specified directory with a symlink to a sensitive location (eg /etc).
  • A tmpfs is mounted over this target location. From inside the jail this is empty and writable by the non-privileged attacker. Targetting eg /etc one can easily obtain a root shell and escape with it from the jail. (nosuid on the mounted file systems was a good attempted mitigation for this scenario but there are ways around it).

I have tested against the most recent commit.

martin@ubuntu:~/github/firejail$ git log -1 
commit 118afb4479662881160b96b0cdfa2f07825ae910
Author: Reiner Herrmann <reiner@reiner-h.de>
Date:   Sat Mar 25 12:44:45 2017 +0100

    Use thunderbird instead of icedove for testing
    
    Thunderbird is back in Debian, and Icedove is gone.
    Tests will then also run in more distributions.
martin@ubuntu:~/github/firejail$ ./sploit 
Switching to pid 30002, the first child process inside the sandbox
Child process initialized
bash-4.3# id
uid=0 gid=10000 groups=10000
bash-4.3# 
Originally created by @mcarpenter on GitHub (Mar 25, 2017). Original GitHub issue: https://github.com/netblue30/firejail/issues/1158 There's a TOCTOU attack possible using `--tmpfs` now that it can be used on a user-controlled directory under `$HOME` (commit 22414adf2a79b08a77bacbc002fb6ebb126d5b32). I have a working exploit for this that I can share with committers but the essence is: * Call firejail with `--tmpfs` pointing to a subdirectory of `$HOME`. * The validity of the `tmpfs` directory is checked early. * Whilst other flags are being processed, replace the specified directory with a symlink to a sensitive location (eg `/etc`). * A `tmpfs` is mounted over this target location. From inside the jail this is empty and writable by the non-privileged attacker. Targetting eg `/etc` one can easily obtain a root shell and escape with it from the jail. (`nosuid` on the mounted file systems was a good attempted mitigation for this scenario but there are ways around it). I have tested against the most recent commit. martin@ubuntu:~/github/firejail$ git log -1 commit 118afb4479662881160b96b0cdfa2f07825ae910 Author: Reiner Herrmann <reiner@reiner-h.de> Date: Sat Mar 25 12:44:45 2017 +0100 Use thunderbird instead of icedove for testing Thunderbird is back in Debian, and Icedove is gone. Tests will then also run in more distributions. martin@ubuntu:~/github/firejail$ ./sploit Switching to pid 30002, the first child process inside the sandbox Child process initialized bash-4.3# id uid=0 gid=10000 groups=10000 bash-4.3#
Author
Owner

@netblue30 commented on GitHub (Mar 25, 2017):

Big thanks! Reverted back - tmpfs allowed only to superuser.

Question: would this be even possible to implement? Something like a link check before, mount, and another link check? I put something here: 1375682920

<!-- gh-comment-id:289219509 --> @netblue30 commented on GitHub (Mar 25, 2017): Big thanks! Reverted back - tmpfs allowed only to superuser. Question: would this be even possible to implement? Something like a link check before, mount, and another link check? I put something here: https://github.com/netblue30/firejail/commit/137568292056a774d731f9516879ad9b4175b920
Author
Owner

@mcarpenter commented on GitHub (Mar 27, 2017):

Thanks for reverting. I misread git tag -l on Friday (lexicographic ordering, meh, and the tag for 9.44.9 is missing?) so I think 22414ad made it into 9.44.10? I will request a CVE.

Given there is no atomic "check then mount" option this is always going to be racy (unsafe). I'd advise against it. You can't even open() the mount point, check that and then pass the FD to fmount() (doesn't exist...), and the mount point is hidden when mount succeeds. You might be able to minimize the exposure (eg check ISDIR using lstat() rather than stat()) but not in a way that is 100% bullet proof. There will always be some gap (race) in pre-check/mount/post-check.

There's a nice comment on a similar problem from @solardiz that I happened to read last week that covers some other issues (eg information leak). I can't link directly to that comment but look for "fix this issue" at https://hackerone.com/reports/204802#activity-1478225 .

<!-- gh-comment-id:289414318 --> @mcarpenter commented on GitHub (Mar 27, 2017): Thanks for reverting. I misread `git tag -l` on Friday (lexicographic ordering, meh, and the tag for 9.44.9 is missing?) so I think 22414ad made it into 9.44.10? I will request a CVE. Given there is no atomic "check then mount" option this is always going to be racy (unsafe). I'd advise against it. You can't even `open()` the mount point, check that and then pass the FD to `fmount()` (doesn't exist...), and the mount point is hidden when mount succeeds. You might be able to minimize the exposure (eg check `ISDIR` using `lstat()` rather than `stat()`) but not in a way that is 100% bullet proof. There will always be some gap (race) in pre-check/mount/post-check. There's a nice comment on a similar problem from @solardiz that I happened to read last week that covers some other issues (eg information leak). I can't link directly to that comment but look for "fix this issue" at https://hackerone.com/reports/204802#activity-1478225 .
Author
Owner

@mcarpenter commented on GitHub (Mar 27, 2017):

Change was in dev branch only -- CVE not requested.

<!-- gh-comment-id:289424626 --> @mcarpenter commented on GitHub (Mar 27, 2017): Change was in dev branch only -- CVE not requested.
Author
Owner

@netblue30 commented on GitHub (Mar 27, 2017):

Change was in dev branch only

Yes, this tmpfs thing is something new. I gave up on it, it will create too many problems. I also cleaned up my attempt to put a tmpfs on ~/.cache directory. Thank you for your input and let me know if you run in something else.

<!-- gh-comment-id:289597724 --> @netblue30 commented on GitHub (Mar 27, 2017): > Change was in dev branch only Yes, this tmpfs thing is something new. I gave up on it, it will create too many problems. I also cleaned up my attempt to put a tmpfs on ~/.cache directory. Thank you for your input and let me know if you run in something else.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/firejail#797
No description provided.