process: command injection via argument list on Windows
The process library on Windows is vulnerable to a command
injection vulnerability, via cmd.exe
's interpretation of
arguments. Programs that invoke batch files (.bat
,
.cmd
) and pass arguments whose values are affected by
program inputs may be affected.
This issue was discovered in many programming languages' Windows process execution behaviour. It was tracked by CERT/CC as VU#123335 and a coordinated disclosure was made on 2024-04-09 17:00 UTC.
A fix was released in process-1.6.19.0.
Background
Unlike POSIX systems, Windows does not have a mechanism for passing multiple arguments.Command line parsing is up to individual programs.
The process library defines the RawCommand
constructor for specifying an executable and its arguments:
data CmdSpec
= ShellCommand String
| RawCommand FilePath [String]
On Windows, the RawCommand
executable name and arguments
are serialised into a single command line string, with separate
arguments quoted separately. process then invokes the Windows
CreateProcess
routine with this command line string is given as the
lpCommandLine
argument.
Issue
When executing .bat
or .cmd
files, CreateProcess
implicitly spawns cmd.exe
. The System.Process
command line construction does not escape characters with special
meaning to cmd.exe
. As a consequence, a command injection
vulnerability arises when the following conditions are satisfied:
- Program running on Windows
- Program executes a
.bat
or.cmd
file - The argument values include or are influenced by program input
Demonstration
The following batch file, test.bat
, merely prints the
executable name the first two arguments (as interpreted by
cmd.exe
):
@ECHO OFF
ECHO 0: %0
ECHO 1: %1
ECHO 2: %2
PAUSE
The following Haskell program executes test.bat
with
basic string arguments. The output is as expected:
λ> readProcess "test.bat" ["a","b"] [] >>= putStrLn
0: "test.bat"
1: "a"
2: "b"
However, we can use a close quote and the &
character to induce cmd.exe
to execute a program named in
the argument:
λ> readProcess "test.bat" ["\"&calc.exe"] [] >>= putStrLn
0: "test.bat"
1: "\"
2:
In addition to producing the above output, calc.exe
is
executed.
Mitigation
The lack of a general mechanism on Windows for safely conveying
command line arguments to programs increases the risk of this kind of
security issue. The fact that cmd.exe
command line parsing
is complex and poorly documented exacerbates this issue, and also
heightens the risk that the fix is incomplete, or causes other
issues.
If possible, avoid executing batch files where arguments include or
are influenced by untrusted program inputs. If it must be done, reject
arguments that include special characters including &
and "
.
Fix versions
process was modified to perform additional escaping and
quoting when executing .bat
and .cmd
files on
Windows (ignoring character case). The behaviour is unchanged in all
other cases.
The fix was released in process-1.6.19.0. The following GHC releases were the first in their series to include a fixed version of the process library:
- GHC 9.10.1-alpha3 (released 2024-04-15)
- GHC 9.8.3 (released 2024-10-20)
- GHC 9.6.5 (released 2024-04-16)
Such a change in semantics should normally result in a major version bump. Because we expect very few (if any) users will be impacted by the behavioural change, the GHC team made a pragmatic decision to avoid the disruption that a major version bump would cause.
A follow-up fix was released in
process-1.6.23.0 to handle batch scripts with
paths ending in whitespace and periods and unescaped %
expansions.
Acknowledgements
Security researcher RyotaK discovered and responsibly disclosed this vulnerability, coordinating the response across the many affected langauges and ecosystems.
Ben Gamari commited and released the fix, which was based on a
proposal by Fraser Tweedale. Fraser also improved the
System.Process
module documentation to better explain the
Windows semantics.
Security researcher Kainan Zhang (@4xpl0r3r) discovered and responsibly disclosing the issue in the first fix and the Rust Security Response WG coordinated the response.
Info
- Published
- April 09, 2024
- Modified
- April 09, 2024
- CAPECs
- < none >
- CWEs
- 150
- Keywords
- windows
- Aliases
- CVE-2024-3566, VU#123335
- Related
- CVE-2024-1874, CVE-2024-24576, CVE-2024-22423
- References
- [ARTICLE] https://flatt.tech/research/posts/batbadbut-you-cant-securely-execute-commands-on-windows/
- [ADVISORY] https://kb.cert.org/vuls/id/123335
- [FIX] https://github.com/haskell/process/commit/3c419f9eeedac024c9dccce544e5a6fb587179a5
- [FIX] https://github.com/haskell/process/commit/951b02dd95559b1a26f2456bfb97cf740ea40934
- [FIX] https://github.com/haskell/process/commit/5fc91f5f36ed4479be2b95f04f264bb78ac8089d
Affected
process
- CVSS
- CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
- Versions
>=1.0.0.0 && <1.6.23.0
- OSes
- windows
- Declarations
- < none >