|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: "Security advisory for the standard library (CVE-2024-24576)" |
| 4 | +author: The Rust Security Response WG |
| 5 | +--- |
| 6 | + |
| 7 | +The Rust Security Response WG was notified that the Rust standard library did |
| 8 | +not properly escape arguments when invoking batch files (with the `bat` and |
| 9 | +`cmd` extensions) on Windows using the [`Command`][1] API. An attacker able to |
| 10 | +control the arguments passed to the spawned process could execute arbitrary |
| 11 | +shell commands by bypassing the escaping. |
| 12 | + |
| 13 | +The severity of this vulnerability is **critical** if you are invoking batch |
| 14 | +files on Windows with untrusted arguments. No other platform or use is |
| 15 | +affected. |
| 16 | + |
| 17 | +This vulnerability is identified by CVE-2024-24576. |
| 18 | + |
| 19 | +## Overview |
| 20 | + |
| 21 | +The [`Command::arg`][2] and [`Command::args`][3] APIs state in their |
| 22 | +documentation that the arguments will be passed to the spawned process as-is, |
| 23 | +regardless of the content of the arguments, and will not be evaluated by a |
| 24 | +shell. This means it should be safe to pass untrusted input as an argument. |
| 25 | + |
| 26 | +On Windows, the implementation of this is more complex than other platforms, |
| 27 | +because the Windows API only provides a single string containing all the |
| 28 | +arguments to the spawned process, and it's up to the spawned process to split |
| 29 | +them. Most programs use the standard C run-time argv, which in practice results |
| 30 | +in a mostly consistent way arguments are splitted. |
| 31 | + |
| 32 | +One exception though is `cmd.exe` (used among other things to execute batch |
| 33 | +files), which has its own argument splitting logic. That forces the standard |
| 34 | +library to implement custom escaping for arguments passed to batch files. |
| 35 | +Unfortunately it was reported that our escaping logic was not thorough enough, |
| 36 | +and it was possible to pass malicious arguments that would result in arbitrary |
| 37 | +shell execution. |
| 38 | + |
| 39 | +## Mitigations |
| 40 | + |
| 41 | +Due to the complexity of `cmd.exe`, we didn't identify a solution that would |
| 42 | +correctly escape arguments in all cases. To maintain our API guarantees, we |
| 43 | +improved the robustness of the escaping code, and changed the `Command` API to |
| 44 | +return an [`InvalidInput`][4] error when it cannot safely escape an argument. |
| 45 | +This error will be emitted when spawning the process. |
| 46 | + |
| 47 | +The fix will be included in Rust 1.77.2, to be released later today. |
| 48 | + |
| 49 | +If you implement the escaping yourself or only handle trusted inputs, on |
| 50 | +Windows you can also use the [`CommandExt::raw_arg`][5] method to bypass the |
| 51 | +standard library's escaping logic. |
| 52 | + |
| 53 | +## Affected Versions |
| 54 | + |
| 55 | +All Rust versions before 1.77.2 on Windows are affected, if your code or one of |
| 56 | +your dependencies executes batch files with untrusted arguments. Other |
| 57 | +platforms or other uses on Windows are not affected. |
| 58 | + |
| 59 | +## Acknowledgments |
| 60 | + |
| 61 | +We want to thank RyotaK for responsibly disclosing this to us according to the |
| 62 | +[Rust security policy][6], and Simon Sawicki (Grub4K) for identifying some of |
| 63 | +the escaping rules we adopted in our fix. |
| 64 | + |
| 65 | +We also want to thank the members of the Rust project who helped us disclose |
| 66 | +the vulnerability: Chris Denton for developing the fix; Mara Bos for reviewing |
| 67 | +the fix; Pietro Albini for writing this advisory; Pietro Albini, Manish |
| 68 | +Goregaokar and Josh Stone for coordinating this disclosure; Amanieu d'Antras |
| 69 | +for advising during the disclosure. |
| 70 | + |
| 71 | +[1]: https://doc.rust-lang.org/std/process/struct.Command.html |
| 72 | +[2]: https://doc.rust-lang.org/std/process/struct.Command.html#method.arg |
| 73 | +[3]: https://doc.rust-lang.org/std/process/struct.Command.html#method.args |
| 74 | +[4]: https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.InvalidInput |
| 75 | +[5]: https://doc.rust-lang.org/std/os/windows/process/trait.CommandExt.html#tymethod.raw_arg |
| 76 | +[6]: https://www.rust-lang.org/policies/security |
0 commit comments