Live data from Hacker News

BatBadBut: You can't securely execute commands on Windows

flatt.tech

21–30 of 43 posts

Re: BatBadBut: You can't securely execute commands on Windows

#21
post #15

Earlier quoted context omitted.

Sure, but nothing is stopping /bin/sh from doing stupid things with its argument list once it gets them, which from what i understand is the equivalent of what is happening on windows.

The difference is if you’re using execve and friends /bin/sh will never be implicitly invoked from under you.

From https://man7.org/linux/man-pages/man2/execve.2.html

pathname must be either a binary executable, or a script starting with a line of the form: #!interpreter [optional-arg]

which is the equivalent of Windows starting CMD.EXE to execute a batch file. The only difference WRT the shell being invoked implicitly is how a script is detected (file name extension vs. first line of content), but that doesn't seem to be relevant when it comes to the shell mis-interpreting its inputs.

Re: BatBadBut: You can't securely execute commands on Windows

#22
post #21

Earlier quoted context omitted.

The difference is if you’re using execve and friends /bin/sh will never be implicitly invoked from under you.

From https://man7.org/linux/man-pages/man2/execve.2.html pathname must be either a binary executable, or a script starting with a line of the form: #!interpreter [optional-arg] which is the equivalent of Windows starting CMD.EXE to execute a batch file. The only difference WRT the shell being invoked implicitly is how a script is detected (file name extension vs. first line of content), but that doesn't seem to be re…

It is still pretty relevant, as the .bat file contents can't prevent improper arguments from executing arbitrary code, whereas a #!/bin/sh file invoked with arbitrary arguments will not do any code execution other than what the file itself asks for. And, even still, the #! form will still pass the arguments as separate elements, i.e. a file containing "#!python3" invoked via an execve argv of ["the-file", "arg1 \"foo ^%`'\\", "arg2"] will result in a total invocation of ["python3", "the-file", "arg1 \"foo ^%`'\\", "arg2"] (JSON-formatted here for clarity reasons, there's no backslash-escaping happening anywhere in reality).

Re: BatBadBut: You can't securely execute commands on Windows

#24
This is a weird coincidence – I ran into this exact problem two days ago, the day before the post was published.

I was just trying to write a simple batch script that accepted filenames as arguments and was surprised to find that there is no safe way to do so, as they're always passed through shell expansion, so if you have a filename like "foo %PATH% bar.txt" (which is allowed) the script will receive it with the PATH variable expanded and cannot get at the actual filename.

Also, passing arguments to programs is unsafe on Windows even if you don't go through the shell, because the quoting rules are entirely up to the program being invoked. The CreateProcess function[0] accepts a string, not an array, so you have to quote the arguments – but you can't do this quoting correctly unless you know exactly what program you're invoking and what grammar it has chosen for parsing its lpCommandLine string.

The article mentions that "many programming languages guarantee that the command arguments are escaped properly", but there is no universal "escaped properly" on Windows. There is escaped properly for the C runtime's parser[1], or escaped properly for CommandLineToArgv[2] which parses "in a way that is similar to" the C runtime, or escaped properly for .NET which has its own set of rules[3] – but there is no guarantee that any particular program is using any of these ways; any program can use whatever rules it likes!

Raymond Chen has written[4] about this as well.

PowerShell has an interesting workaround[5] of sorts: If you specify "-EncodedCommand" and "-EncodedArguments" it lets you pass base64-encoded strings when you "require complex quotation marks or curly braces".

[0] https://learn.microsoft.com/en-us/windows/win32/api/processt...

[1] https://learn.microsoft.com/en-us/cpp/c-language/parsing-c-c...

[2] https://learn.microsoft.com/en-us/windows/win32/api/shellapi...

[3] https://learn.microsoft.com/en-us/dotnet/api/system.environm...

[4] https://devblogs.microsoft.com/oldnewthing/20100917-00/?p=12...

[5] https://learn.microsoft.com/en-us/powershell/module/microsof...

Re: BatBadBut: You can't securely execute commands on Windows

#25
post #11
post #9

Earlier quoted context omitted.

> Is there any reason Windows couldn't add an equivalent of execvpe for arguments and environment to be passed as arrays, which newer programs could then use directly? I fail to see how this would help. If i understand correctly, the issue is how cmd.exe interprets the args, not how the args get to it.

I think both sides play a role - aiui cmd.exe (and other programs) interpret the arguments in an inconsistent way, but this is only relevant because there is no standard way to pass multiple arguments. I had something like this in mind: - Create `CreateProcessArgv`, a version of `CreateProcess` that takes `argv` rather than `lpCommandLine` (like `execv*`) - Create `GetCommandLineArgv`, an alternative to `GetCommandLi…

This creates compatibility issues with applications that inspect the command line of running programs and for example restart them with the same command line. It also probably ties in into a lot of general program-execution use cases like the Task Scheduler.

Re: BatBadBut: You can't securely execute commands on Windows

#26

Who‘s still using batch files and cmd.exe now that we have PowerShell?

PowerShell has that whole execution policy thing, so you can't just launch a PowerShell script unless you wrap it in a batch file or some other script.

I could see how allowing the user to whitelist individual scripts would make sense, but as far as I can tell that's not how it works? A blanket policy of "all scripts are forbidden unless wrapped with fragile and shady-looking hacks" doesn't seem particularly useful.

Re: BatBadBut: You can't securely execute commands on Windows

#27
post #8

This seems more like a gap in the windows API than in the programming languages.

Is linux really any different? I think the escaping rules are just better known.

It's similar if you're invoking through the shell, which should be avoided for precisely this reason, but if you're launching a program directly (through execv or CreateProcess) there is one big difference:

On Linux the parsing is done on the caller's side of the interface, so the caller knows what quoting rules to apply – could be Python's rules if they're using Python to construct the argument array, bash's rules if they're using bash, etc.

On Windows, the parsing is done on the receiver's side of the interface, so the caller can't know how it's supposed to be quoted unless they have special knowledge of a specific receiver and its parsing rules.

Re: BatBadBut: You can't securely execute commands on Windows

#28
post #24

This is a weird coincidence – I ran into this exact problem two days ago, the day before the post was published. I was just trying to write a simple batch script that accepted filenames as arguments and was surprised to find that there is no safe way to do so, as they're always passed through shell expansion, so if you have a filename like "foo %PATH% bar.txt" (which is allowed) the script will receive it with the PA…

Also: https://blogs.msdn.microsoft.com/twistylittlepassagesallalik...

Here's my try in ruby from a prior life: https://github.com/chef/mixlib-shellout/blob/main/lib/mixlib...

Re: BatBadBut: You can't securely execute commands on Windows

#30
post #20

Would LOVE to hear what other side of an "airtight" hatchway this one is.

It’s not an admin vulnerability, so there’s no hatchway. The real issue here is blindly passing user-provided input to a batch script, possibly from the Internet, and if you’re doing that then you’ve got much bigger problems. If you’re doing it using an account with any kind of privileges, you’re kinda asking to get broken into.
Post reply on HN