Passing user-controlled arguments to open_port/2 with spawn/spawn_executable is insecure on Windows

As per VU#123335 - Multiple programming languages fail to escape arguments properly in Microsoft Windows

Programming languages typically provide a way to execute commands (for e.g., os/exec in Golang) on the operating system to facilitate interaction with the OS. Typically, the programming languages also allow for passing arguments which are considered data (or variables) for the command to be executed. The arguments themselves are expected to be not executable and the command is expected to be executed along with properly escaped arguments, as inputs to the command. Microsoft Windows typically processes these commands using a CreateProcess function that spawns a cmd.exe for execution of the command. Microsoft Windows has documented some of the concerns related to how these should be properly escaped before execution as early as 2011. See Everyone quotes command line arguments the wrong way | Microsoft Learn.

A vulnerability was discovered in the way multiple programming languages fail to properly escape the arguments in a Microsoft Windows command execution environment. This can lead confusion at execution time where an expected argument for a command could be executed as another command itself. An attacker with knowledge of the programming language can carefully craft inputs that will be processed by the compiled program as commands. This unexpected behavior is due to lack of neutralization of arguments by the programming language (or its command execution module) that initiates a Windows execution environment. The researcher has found multiple programming languages, and their command execution modules fail to perform such sanitization and/or validation before processing these in their runtime environment.

As we cannot fix this without breaking backwards compatibility for legitimate use cases, users are advised to avoid passing untrusted input as arguments to open_port/2. The documentation will be updated to this effect in the near future.

2 Likes

According to the blog post this only applies when the executable is a batch file (.bat, .cmd), in which case the “cmd.exe” is implicitly launched. If I understand correctly, when executing binaries the parameter list in args is passed directly to that executable, and no injection is possible.

So with spawn_executable, if the command path is pointing to a .exe file, there is no issue. And with spawn there is just the caveat that batch files may be picked over .exe file if they exist in the user’s path, so the caller should specify the full command name, including .exe, to avoid spawning cmd accidentally through a similarly names batch file.

Is that correct?

1 Like

Yes, I believe so, but things are so gnarly under the hood that I’d recommend people not to pass untrusted inputs if it can be avoided, even for ordinary executables.

2 Likes