|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: "Security advisory for the standard library (CVE-2022-21658)" |
| 4 | +author: The Rust Security Response WG |
| 5 | +--- |
| 6 | + |
| 7 | +> This is a cross-post of [the official security advisory][advisory]. The |
| 8 | +> official advisory contains a signed version with our PGP key, as well. |
| 9 | +
|
| 10 | +[advisory]: https://groups.google.com/g/rustlang-security-announcements/c/R1fZFDhnJVQ |
| 11 | + |
| 12 | +The Rust Security Response WG was notified that the `std::fs::remove_dir_all` |
| 13 | +standard library function is vulneable a race condition enabling symlink |
| 14 | +following (CWE-363). An attacker could use this security issue to trick a |
| 15 | +privileged program into deleting files and directories the attacker couldn't |
| 16 | +otherwise access or delete. |
| 17 | + |
| 18 | +This issue has been assigned [CVE-2022-21658][1]. |
| 19 | + |
| 20 | +## Overview |
| 21 | + |
| 22 | +Let's suppose an attacker obtained unprivileged access to a system and needed |
| 23 | +to delete a system directory called `sensitive/`, but they didn't have the |
| 24 | +permissions to do so. If `std::fs::remove_dir_all` followed symbolic links, |
| 25 | +they could find a privileged program that removes a directory they have access |
| 26 | +to (called `temp/`), create a symlink from `temp/foo` to `sensitive/`, and wait |
| 27 | +for the privileged program to delete `foo/`. The privileged program would |
| 28 | +follow the symlink from `temp/foo` to `sensitive/` while recursively deleting, |
| 29 | +resulting in `sensitive/` being deleted. |
| 30 | + |
| 31 | +To prevent such attacks, `std::fs::remove_dir_all` already includes protection |
| 32 | +to avoid recursively deleting symlinks, as described in its documentation: |
| 33 | + |
| 34 | +> This function does **not** follow symbolic links and it will simply remove |
| 35 | +> the symbolic link itself. |
| 36 | +
|
| 37 | +Unfortunately that check was implemented incorrectly in the standard library, |
| 38 | +resulting in a TOCTOU (Time-of-check Time-of-use) race condition. Instead of |
| 39 | +telling the system not to follow symlinks, the standard library first checked |
| 40 | +whether the thing it was about to delete was a symlink, and otherwise it would |
| 41 | +proceed to recursively delete the directory. |
| 42 | + |
| 43 | +This exposed a race condition: an attacker could create a directory and replace |
| 44 | +it with a symlink between the check and the actual deletion. While this attack |
| 45 | +likely won't work the first time it's attempted, in our experimentation we were |
| 46 | +able to reliably perform it within a couple of seconds. |
| 47 | + |
| 48 | +## Affected Versions |
| 49 | + |
| 50 | +Rust 1.0.0 through Rust 1.58.0 is affected by this vulnerability. We're going |
| 51 | +to release Rust 1.58.1 later today, which will include mitigations for this |
| 52 | +vulnerability. Patches to the Rust standard library are also available for |
| 53 | +custom-built Rust toolchains here (TODO: link). |
| 54 | + |
| 55 | +Note that the following targets don't have usable APIs to properly mitigate the |
| 56 | +attack, and are thus still vulnerable even with a patched toolchain: |
| 57 | + |
| 58 | +* macOS before version 10.10 (Yosemite) |
| 59 | +* REDOX |
| 60 | + |
| 61 | +## Mitigations |
| 62 | + |
| 63 | +We recommend everyone to update to Rust 1.58.1 as soon as possible, especially |
| 64 | +people developing programs expected to run in privileged contexts (including |
| 65 | +system daemons and setuid binaries), as those have the highest risk of being |
| 66 | +affected by this. |
| 67 | + |
| 68 | +Note that adding checks in your codebase before calling `remove_dir_all` will |
| 69 | +**not** mitigate the vulnerability, as they would also be vulnerable to race |
| 70 | +conditions like `remove_dir_all` itself. The existing mitigation is working as |
| 71 | +intended outside of race conditions. |
| 72 | + |
| 73 | +## Acknowledgments |
| 74 | + |
| 75 | +We want to thank Hans Kratz for independently discovering and disclosing this |
| 76 | +issue to us according to the [Rust security policy][2], for developing the fix |
| 77 | +for UNIX-like targets and for reviewing fixes for other platforms. |
| 78 | + |
| 79 | +We also want to thank Florian Weimer for reviewing the UNIX-like fix and for |
| 80 | +reporting the same issue back in 2018, even though the Security Response WG |
| 81 | +didn't realize the severity of the issue at the time. |
| 82 | + |
| 83 | +Finally we want to thank Pietro Albini for coordinating the security response |
| 84 | +and writing this advisory, Chris Denton for writing the Windows fix, Alex |
| 85 | +Crichton for writing the WASI fix, and Mara Bos for reviewing the patches. |
| 86 | + |
| 87 | +[1]: https://www.cve.org/CVERecord?id=CVE-2022-21658 |
| 88 | +[2]: https://www.rust-lang.org/policies/security |
0 commit comments