@@michawhite7613 Nah, this has nothing to do with the Windows CreateProcessW API. If this was a problem with CreateProcessW then the same vulnerability would also happen with non-.bat files. The problem is in the implementation of cmd.exe (that gets implicitly ran when attempting to execute a batch file). Your program escapes the argument list correctly and packs them into the single argument string of CreateProcessW. CreateProcessW spawns a new process and passes all of the arguments to it. At this point, any normal program would treat those arguments as raw strings, but cmd.exe instead intentionally evaluates them in a shell. So basically, cmd.exe manually "un-escapes" the arguments one extra time and calls it a feature.
@@michawhite7613 It doesn't, that's why it's a problem in the first place. POSIX systems use an array of null terminated strings, so your array of arguments gets passed as-is even in bash scripts. The shell itself parses that when you run commands, so you escape for the shell when you're in a shell context. In code, if you pass an array of arguments with spaces in them, they don't magically become more arguments, you can really put whatever you want in there as long as it doesn't contain a null byte. Windows seems to have carried over stuff from DOS where it probably read up to the first space to find out which program to run, then just passed everything until to it raw. So CreateProcess* functions take a single string too, which gives an opportunity for every program to do whatever the hell they want, making passing arguments to subprocesses in Windows safely impossible. I could decide my program uses tab delimited arguments, and there's nothing you can do about it apart for special-casing my program.
@@ruroruro To be fair to it, `cmd.exe \c` *is* a shell. If I pass arguments to `bash -c` or `zsh -c`, I generally expect them to evaluate those arguments as a shell as if I'd typed them into my terminal, and they will.
This can still be a big problem; look at npm or VSCode: these typically get called using `npm` and `code`, but those are batch files on Windows ("npm.cmd" and "code.cmd"). So if you use these you cannot do it using `npm` or `code` in path anymore, or you could be exploited. Some might not even realize they were calling a batch file for these! THAT is why this is such a big deal! Ofc the solution is for these programs to NOT use batch file wrappers, but for now you have to manually search for the actual executable and always use an explicit ".exe" extension
0:15 "Rust is a programming language" 🗣🗣🗣🗣🔥🔥🔥 Btw, I found out that ChatGPT can write batch files *literally* yesterday while using the task scheduler on Windows to schedule the execution of a Python script on one of the PCs at my job, so I'm technically part of the people still using it.
I pointed out rust specifically because they were the ONLY language mentioned in the actual cve description, which I found weird because so many languages are affected.
Thank you James, I can’t wait to have to send this video to my OIS when they tell me I need to abandon python. I keep telling them the real thing we need to abandon are windows servers!
The problem is that unlike 'sh -c' or 'bash -c' on Linux, which only process one argument as a shell script and pass the rest as unevaluated arguments, 'cmd /c' actually parses all following arguments as a single shell command. There is no way to pass untrusted unevaluated arguments to 'cmd /c'. Without _knowing_ whether the target is a batch script or cmd.exe (or even a copy of cmd.exe!), it's impossible for a programming language API to correctly escape arguments here. The backwards-compatible solution would be for Microsoft to provide a new flag for cmd.exe that behaves like Linux's 'sh -c' and only processes one argument as a shell script, and for batch script invocations to use this new flag if a certain compatibility option is not set (in settings or registry or whereever)
It would also be possible to write a 'bad-sh' program for linux that behaves similarly, and every script that defines '#!/usr/bin/bad-sh' would then have the same problem as bat files on windows. (Or at least, similar, since Linux at least has an OS level array of arguments) The problem isn't actually the programming languages, it's the windows cmd shell. But I absolutely understand that Programming languages are trying to make it harder to shoot yourself in the foot with this, since it's a pretty easily overlooked way to accidently run untrusted commands.
here's the part that's questionable to me: ``` To run a batch file, you must start the command interpreter; set lpApplicationName to cmd.exe and set lpCommandLine to the following arguments: /c plus the name of the batch file. ``` Is what the documentation says, and what it actually does is run cmd for you regardless.
It only runs "cmd.exe" automatically because ".bat" and ".cmd" are configured to open with that application in the registry by default. You could always go into the registry and modify those associations to open the files in a text editor. When Windows is told to launch a file that's not an executable, it looks at the file associations in the registry to figure out what you want it to do with the file.
I hope you see this even though it's a month late, but the execv*() functions are actually very problematic for the fact that you can elide the program name as the first argument and cause all kinds of havoc with calling an executable. Basically, if your program processes arguments in the wrong way and a third-party has called you via an execv*() function, then problems ensue.
Seen! I think it's impossible to avoid all problems no matter which interface you choose, you always have to be careful when dealing with os level calls.
Consider the following: doing EXACTLY the same thing on Linux, using test.sh instead of test.bat is PERFECTLY SAFE. Now please explain to me, why is this the programmers fault instead of Microsofts?
But you're not passing untrusted user input to a shell, you're passing untrusted user input to a shell _script_. You might not even expect to be calling a shell script, the script may be user provided and you expect an exe or a py file and they gave you a bat file. It's safe to do on every operating system except Windows.
@@maxpoulin64 If you execute a user provided executable (shell, exe, py,...), you voluntarily build a command injection vulnerability into your system. The entire goal of the BadBat exploit is command injection.
Is it a known thing in the Windows world that safely escaping arguments is impossible? Because from a Linux/Mac point of view, I wouldn't. If I run a bash script, I don't have to escape arguments because the program is the shell _script_, not the shell itself. It's `shell=False`, it's not supposed to run through a shell. It might run the script using a shell as the interpreter via the shebang, but in no way is the input arguments to the script ever parsed as shell commands or even shell options.The docs says it's a safe API, and on POSIX it indeed is. If I had to run something on Windows, I wouldn't think twice and assume that as the docs says and as every other operating system does, my array of arguments shows up as-is unmangled in the subprocess. The fact that magically if you happen to call a batch script it'll interpret the arguments as shell commands is... weird. Why on earth does cmd.exe even implement that? Isn't it the calling shell's job to handle stuff like "&" to fork in the background?
Except doing EXACTLY the same thing on Linux, using test.sh instead of test.bat is PERFECTLY SAFE. The fact that cmd.exe evaluates the contents of its arguments instead of passing them to the batch file as raw strings is just crazy.
@@maxpoulin64 The reason cmd.exe does that is because of the way that you ask it to run a batch file. MCoding didn't go into it, but basically, there isn't actually a flag to tell cmd.exe (which *is* the shell) to interpret a batch file. What you do is run `cmd \c [batch_file_name] [batch file args...]`, which is the same idea as running `sh -c "./[shell_script_name] [shell_script_args...]"`, rather than the much safer `sh [shell_script_name] [shell_script_args...]`
The problem is that sanitization functions weren't correct, because of an unknown feature of cms.exe. Rust fixed their sanitization to support this. Node just removed the ability to call batch scripts.
@@aperturesignaturebandwidth its not the users/programmers fault and its not the languages fault. It's pretty clear that this is Microsofts fault. The fact that cmd.exe evaluates its arguments before passing them to the batch script is completely insane, imho.
@@aperturesignaturebandwidth For example in sql you could write “1; drop table”. “;” is special character here witch means new line of code and after that is bad code (delete table). So it would be a good idea to escape characters (like in python place “\” before bad stuff), remove it completely or pass to built in parsing algorithm ( in sql something like query = “select * from table where user_name == @user_input”; query.addarg(“@user_input”, nasty_user_input). As opposite to embedding whatever user given to the query. That is called sanitation, i.e. removing special characters from user input.
@@aperturesignaturebandwidth Doing the escaping correctly is extremely convoluted because the parsing of cmd.exe is messed up and doesn't have good escapes for everything so you need to hack your way around it. That's also why Rust chose to return an error for certain convoluted inputs instead of trying to escape them. In most cases, you can probably just filter or disallow all the relevant special characters. If you need to allow all special characters and escape them correctly, your best bet is probably to check the article by the person that found the CVE. Iirc Microsoft also has some documentation on the topic.
This behavior / issue has been with us (and properly documented) for ages. But. Somebody piled bunch of abstractions on top of it, and in meantime, forgot how the bottom layers actually worked.
I love the snark behind "first you're running windows", and then later 'it feels like I should've validated my inputs'. Windows still dominates the market share, and input validation is sadly lacking all over the place.
I'd love that, but not until they're fully open source. Right now there's still so much mystery behind them that there's a good chance it's just a pump and dump scheme, I don't want any free advertisement for them at this point.
I really haven't looked into mojo at all yet. I like to stick to videos around proven technologies and methods, so if mojo sticks around for a few more years, I might make some content on it.
Can anyone explain a circumstance in which this can be exploited? Looks like it could never affect 99.9% of users, just don't type in a malicious command on your own machine. You can already do that by just opening the command prompt.
I wonder if this isn't a vulnerability in the batch file. On Unix you are told to always properly quote parameter expansion (i.e., write «echo "$1"», not «echo $1» to prevent similar issues. But there are no quotes on %1 in the batch file, even there are quotes on "%~1" on the previous line (2:13).
Thats not the point. This would also work if the batch file were completely empty. The call actually getting attacked is `cmd /c problem.bat & calc.exe`. here, cmd executes `problem.bat` and then `calc.exe` as it treats `&` special here already
I am surprised this is even considered an exploit. I have always assumed it would work like this, so I treat calls to a subprocess as if I were executing a query on a database -- in no way would I just trust user input to not contain anything malicious.
But when do you actually want to pass input into a subprocess.run/call/check_output in the first place? This seems more like a software architecture problem rather than a Windows bug. In the cases where shell is additionally set to true, any arbitrary command sequences can be executed either way through command chaining in cmd.
Did you watch the last part of the video? The fact that CreateProcessW passes encodes and packs the arguments into a single string has literally nothing to do with this CVE. In this case you successfully escape the argument, pass them to the cmd.exe process and instead of treating those arguments as normal strings (like for exmple python.exe or bash would), it decides to evaluate them.
@@ruroruro "Escaping" is only necessary because there's an opaque parser between you and the batch file that you need to appease. It seems insane to me that we've designed programs around adding fluff to a string just so that another program can remove it, hopefully in a symmetric way. When you can't disable, control, or even see this pointless second layer, it's no wonder these injection issues pop up so often.
@@tryashtar Once again. Rewatch the video. There is indeed an opaque parser between you and any other process (CreateProcessW isn't specific to batch files). But the escaping done by Python and the parser inside CreateProcessW cancel each other out PERFECTLY. You can tell that there is no vulnerability in this escape-then-parse logic, because passing arguments to any other executable works just fine. The problem only appears when the target executable is a batch file. That's because the problem is inside the implementation of cmd.exe specifically, not in the CreateProcessW API.
@@ruroruro Yes I understand. I'm not complaining about CreateProcessW, just a general complaint about unparsed strings being the communication method between programs in most operating systems.
I think the create process api is related mostly in that it causes a lot of developer confusion about what needs to be escaped and what doesn't. The cve could still be a thing if we had an array version of it, but I think people would be much less likely to fall for it when they read the docs, which would no longer mention about "escaping" inputs on Windows.
when people started writting/filming about this "vulnerability" I became confused because it looked like they forgot about SQL injection stories and like they want "nothing needs checking" programs... why are they even programmers ?
Literally: If you rely on passing user input in your program to a batch file for processing, you have bigger problems with your code on a fundamental level.
I got to tell people today something to the effect of "this is the expected operation, please adjust your own operations in order to match," and was met with "but can we change it anyway?" No. No we cannot. #YouBecomeWhatYouHate #HatingMicrosoftIsAnOkayHatred
So in a nutshell...... sanitize your inputs... got it.... I've never seen something that should be at best a 1 out of 10 be treated as so critical just because people don't know how to sanitize inputs.
Im fairly sure that 99.9% would not be able to sanitize input to pass to batch files properly, and there is no real good resource out there on how to do it. Its not as easy as you think and from the provided "fixes", only Rust did it correctly.
What gets me is ... who the hell is making use of batch files and passing arguments through blindly? Bat files are just the pickiest sons of b***ches out there with it's argument list and you have to do it carefully. I know I make use of them to do a whole host of automated file creation/updating with preset values that vary on a few values & a few strings. Though One think I never did was pass the strings directly through to the next bat file without modifying the strings [as they would be from expected values & strings] bat files are great for aid files for your other programs and projects, and cleanups.. but this whole thing confuses me.... who setups a rust cli tool for windows, that calls a bat file to do something, it could have just done with stored cmd.exe calls, instead based on inteneral logic with code more robust than batch script. This seems like someone doing bad practices overall. There is genuinely no real reason to be calling anything except the most default & specialized bat files from another programing language whatsoever. I know i've set my own nest of bat files up... but I also am using intellij and doing mods for games and the terminal access to is quick to produce a certain support file for what i need from it.
Is there such a thing as issuing a CVE recall? This whole discussion needs to be restarted under a reasonable premise... instead of some researcher getting their cve score inflated to make it sound like they discovered a legitimately critical flaw instead of discovering an old shell with a bad api.
Of course they are following NSA™, I mean, Microsoft® exact instructions. All those silly paranoid people making noise again. How silly!! Lol. Great explanation as always!!❤
It only errors when it recieves certain convoluted inputs that it can not escape properly. Unlike Python, it (now) ensures that inputs are always escaped properly in any other case, even for Batch files.
No, Windows API never satisfied a property of POSIX APIs that Rust and many other languages - including those most of Windows is implemented in - expects. Windows batch files in particular cannot be written in a way to compensate. Rust did make the mistake of claiming that the functions would behave POSIX style when Windows made that impossible.
java chad move "won't fix"
skill issue, moving on
the problem is somewhere between the software and the hardware. Skill issue.
what the actual fuck xDDDD
it's ultimately a windows API design issue
@@figbootyep
Heartening to see someone look into this and get a real sense of what's going on instead of shooting off a video last week when the news was hot
*Me, who was just busy and totally would have fired off a vid with everyone else*
Yeah *those* guys 🫣
Windows skill issues.
xz... ahem 😂
@@HoSza1 Caught before reaching production systems
@@dirlrido2522 bat: never used in production
@@ItsCOMMANDer_Uncommon use doesn't make bat not an exploitable part of every Windows system lmao
@@dirlrido2522 bat isnt the problem lol, (deprecated) cmd.exe is
Quite weird that the Win API doesn't have a way of processing an array of arguments.
It does, iirc, it's just implemented incorrectly.
@@michawhite7613 Nah, this has nothing to do with the Windows CreateProcessW API. If this was a problem with CreateProcessW then the same vulnerability would also happen with non-.bat files.
The problem is in the implementation of cmd.exe (that gets implicitly ran when attempting to execute a batch file). Your program escapes the argument list correctly and packs them into the single argument string of CreateProcessW. CreateProcessW spawns a new process and passes all of the arguments to it. At this point, any normal program would treat those arguments as raw strings, but cmd.exe instead intentionally evaluates them in a shell.
So basically, cmd.exe manually "un-escapes" the arguments one extra time and calls it a feature.
@@michawhite7613 It doesn't, that's why it's a problem in the first place. POSIX systems use an array of null terminated strings, so your array of arguments gets passed as-is even in bash scripts. The shell itself parses that when you run commands, so you escape for the shell when you're in a shell context. In code, if you pass an array of arguments with spaces in them, they don't magically become more arguments, you can really put whatever you want in there as long as it doesn't contain a null byte. Windows seems to have carried over stuff from DOS where it probably read up to the first space to find out which program to run, then just passed everything until
to it raw. So CreateProcess* functions take a single string too, which gives an opportunity for every program to do whatever the hell they want, making passing arguments to subprocesses in Windows safely impossible. I could decide my program uses tab delimited arguments, and there's nothing you can do about it apart for special-casing my program.
@@ruroruro To be fair to it, `cmd.exe \c` *is* a shell. If I pass arguments to `bash -c` or `zsh -c`, I generally expect them to evaluate those arguments as a shell as if I'd typed them into my terminal, and they will.
@@Howtheheckarehandleswitbash -c only evaluates one argument as shell script:
```
bash -c 'echo "$0"' '&echo hello'
```
output:
```
&echo hello
```
This can still be a big problem; look at npm or VSCode: these typically get called using `npm` and `code`, but those are batch files on Windows ("npm.cmd" and "code.cmd"). So if you use these you cannot do it using `npm` or `code` in path anymore, or you could be exploited. Some might not even realize they were calling a batch file for these! THAT is why this is such a big deal!
Ofc the solution is for these programs to NOT use batch file wrappers, but for now you have to manually search for the actual executable and always use an explicit ".exe" extension
0:15 "Rust is a programming language" 🗣🗣🗣🗣🔥🔥🔥
Btw, I found out that ChatGPT can write batch files *literally* yesterday while using the task scheduler on Windows to schedule the execution of a Python script on one of the PCs at my job, so I'm technically part of the people still using it.
I pointed out rust specifically because they were the ONLY language mentioned in the actual cve description, which I found weird because so many languages are affected.
Thank you James, I can’t wait to have to send this video to my OIS when they tell me I need to abandon python. I keep telling them the real thing we need to abandon are windows servers!
Well, hopefully you weren't passing along untrusted inputs in the first place so nothing to worry about!
OIS?
@@Norsilca office of information security
The problem is that unlike 'sh -c' or 'bash -c' on Linux, which only process one argument as a shell script and pass the rest as unevaluated arguments, 'cmd /c' actually parses all following arguments as a single shell command. There is no way to pass untrusted unevaluated arguments to 'cmd /c'.
Without _knowing_ whether the target is a batch script or cmd.exe (or even a copy of cmd.exe!), it's impossible for a programming language API to correctly escape arguments here.
The backwards-compatible solution would be for Microsoft to provide a new flag for cmd.exe that behaves like Linux's 'sh -c' and only processes one argument as a shell script, and for batch script invocations to use this new flag if a certain compatibility option is not set (in settings or registry or whereever)
It would also be possible to write a 'bad-sh' program for linux that behaves similarly, and every script that defines '#!/usr/bin/bad-sh' would then have the same problem as bat files on windows. (Or at least, similar, since Linux at least has an OS level array of arguments)
The problem isn't actually the programming languages, it's the windows cmd shell. But I absolutely understand that Programming languages are trying to make it harder to shoot yourself in the foot with this, since it's a pretty easily overlooked way to accidently run untrusted commands.
They already provide it, it’s “pwsh -command” 😹
here's the part that's questionable to me:
```
To run a batch file, you must start the command interpreter; set lpApplicationName to cmd.exe and set lpCommandLine to the following arguments: /c plus the name of the batch file.
```
Is what the documentation says, and what it actually does is run cmd for you regardless.
It only runs "cmd.exe" automatically because ".bat" and ".cmd" are configured to open with that application in the registry by default. You could always go into the registry and modify those associations to open the files in a text editor. When Windows is told to launch a file that's not an executable, it looks at the file associations in the registry to figure out what you want it to do with the file.
I hope you see this even though it's a month late, but the execv*() functions are actually very problematic for the fact that you can elide the program name as the first argument and cause all kinds of havoc with calling an executable. Basically, if your program processes arguments in the wrong way and a third-party has called you via an execv*() function, then problems ensue.
Seen! I think it's impossible to avoid all problems no matter which interface you choose, you always have to be careful when dealing with os level calls.
If you are passing untrusted user input (escaped or not) to shell - it's on you.
Consider the following: doing EXACTLY the same thing on Linux, using test.sh instead of test.bat is PERFECTLY SAFE. Now please explain to me, why is this the programmers fault instead of Microsofts?
But you're not passing untrusted user input to a shell, you're passing untrusted user input to a shell _script_. You might not even expect to be calling a shell script, the script may be user provided and you expect an exe or a py file and they gave you a bat file. It's safe to do on every operating system except Windows.
@@maxpoulin64 If you execute a user provided executable (shell, exe, py,...), you voluntarily build a command injection vulnerability into your system. The entire goal of the BadBat exploit is command injection.
this is my exact reaction to seeing this CVE. i was like "isnt this just, expected behavior?" lmao
the clearer explanation i see so far. Bravo !!
This is literally the behavior I expected... since ALWAYS
Is it a known thing in the Windows world that safely escaping arguments is impossible? Because from a Linux/Mac point of view, I wouldn't. If I run a bash script, I don't have to escape arguments because the program is the shell _script_, not the shell itself. It's `shell=False`, it's not supposed to run through a shell. It might run the script using a shell as the interpreter via the shebang, but in no way is the input arguments to the script ever parsed as shell commands or even shell options.The docs says it's a safe API, and on POSIX it indeed is.
If I had to run something on Windows, I wouldn't think twice and assume that as the docs says and as every other operating system does, my array of arguments shows up as-is unmangled in the subprocess. The fact that magically if you happen to call a batch script it'll interpret the arguments as shell commands is... weird. Why on earth does cmd.exe even implement that? Isn't it the calling shell's job to handle stuff like "&" to fork in the background?
Except doing EXACTLY the same thing on Linux, using test.sh instead of test.bat is PERFECTLY SAFE. The fact that cmd.exe evaluates the contents of its arguments instead of passing them to the batch file as raw strings is just crazy.
@@maxpoulin64 The reason cmd.exe does that is because of the way that you ask it to run a batch file. MCoding didn't go into it, but basically, there isn't actually a flag to tell cmd.exe (which *is* the shell) to interpret a batch file. What you do is run `cmd \c [batch_file_name] [batch file args...]`, which is the same idea as running `sh -c "./[shell_script_name] [shell_script_args...]"`, rather than the much safer `sh [shell_script_name] [shell_script_args...]`
6:30 the C cast to (LPSTARTUPINFOW) is cursed. Always raises a red flag to me!
Just look for an article entitled "How Command Line Parameters Are Parsed". Windows command line is just crazy.
Very exhaustive take on subject. Great job !
Superb video!
Thank you very much!
Muy bien amigo! Qué es tu opinion de JavaScript y Rust?
What does it mean to validate an unknown/untrusted input? Is there a way to determine if some input you have wants to run an executable?
The problem is that sanitization functions weren't correct, because of an unknown feature of cms.exe. Rust fixed their sanitization to support this. Node just removed the ability to call batch scripts.
@@michawhite7613 well, for the 5 languages that won't change, it seems like the user should sanitize. What does this mean? What does it look like?
@@aperturesignaturebandwidth its not the users/programmers fault and its not the languages fault. It's pretty clear that this is Microsofts fault. The fact that cmd.exe evaluates its arguments before passing them to the batch script is completely insane, imho.
@@aperturesignaturebandwidth For example in sql you could write “1; drop table”. “;” is special character here witch means new line of code and after that is bad code (delete table). So it would be a good idea to escape characters (like in python place “\” before bad stuff), remove it completely or pass to built in parsing algorithm ( in sql something like query = “select * from table where user_name == @user_input”; query.addarg(“@user_input”, nasty_user_input). As opposite to embedding whatever user given to the query. That is called sanitation, i.e. removing special characters from user input.
@@aperturesignaturebandwidth Doing the escaping correctly is extremely convoluted because the parsing of cmd.exe is messed up and doesn't have good escapes for everything so you need to hack your way around it. That's also why Rust chose to return an error for certain convoluted inputs instead of trying to escape them. In most cases, you can probably just filter or disallow all the relevant special characters. If you need to allow all special characters and escape them correctly, your best bet is probably to check the article by the person that found the CVE. Iirc Microsoft also has some documentation on the topic.
This behavior / issue has been with us (and properly documented) for ages. But. Somebody piled bunch of abstractions on top of it, and in meantime, forgot how the bottom layers actually worked.
Great explanation, thanks.
I love the snark behind "first you're running windows", and then later 'it feels like I should've validated my inputs'.
Windows still dominates the market share, and input validation is sadly lacking all over the place.
I think you overestimate the average python programmer, just saying
Hi James, will you ever make a video on Mojo?
I'd love that, but not until they're fully open source. Right now there's still so much mystery behind them that there's a good chance it's just a pump and dump scheme, I don't want any free advertisement for them at this point.
@@felixfourcolor I don't think someone like Chris Lattner would be involved in such scheme.
I really haven't looked into mojo at all yet. I like to stick to videos around proven technologies and methods, so if mojo sticks around for a few more years, I might make some content on it.
@@kinomonogatari I also hope not, but we can't know. I'm very skeptical of their ludicrous performance claim, and I don't want to add to the hype.
Can anyone explain a circumstance in which this can be exploited? Looks like it could never affect 99.9% of users, just don't type in a malicious command on your own machine. You can already do that by just opening the command prompt.
Github, GitLab and other user configurable CI/CD/Actions wich must be done on Windows....
Nice! Thank you!
And thank you for watching!
I wonder if this isn't a vulnerability in the batch file. On Unix you are told to always properly quote parameter expansion (i.e., write «echo "$1"», not «echo $1» to prevent similar issues. But there are no quotes on %1 in the batch file, even there are quotes on "%~1" on the previous line (2:13).
Thats not the point. This would also work if the batch file were completely empty. The call actually getting attacked is `cmd /c problem.bat & calc.exe`. here, cmd executes `problem.bat` and then `calc.exe` as it treats `&` special here already
@@Grub4K Ok, that wasn't clear to me from the video.
I am surprised this is even considered an exploit. I have always assumed it would work like this, so I treat calls to a subprocess as if I were executing a query on a database -- in no way would I just trust user input to not contain anything malicious.
But when do you actually want to pass input into a subprocess.run/call/check_output in the first place? This seems more like a software architecture problem rather than a Windows bug. In the cases where shell is additionally set to true, any arbitrary command sequences can be executed either way through command chaining in cmd.
When writing any Python wrapper for a CLI.
It is indeed a very nice use pattern. A shell written in Python might be the only valid use case. 🤔
It seems strange to make this issue a CVE given this is known how to work
I mean they made CVEs out of all of the “this is how the http2 protocol works” DDOS issues so CVEs have already been enshittified
"how its known to work" - so, i mean, if it is wrong... then u'd just accept it?
When will we move past communication between programs via concatenated strings that get parsed and interpreted along the way, this is embarrassing
Did you watch the last part of the video? The fact that CreateProcessW passes encodes and packs the arguments into a single string has literally nothing to do with this CVE. In this case you successfully escape the argument, pass them to the cmd.exe process and instead of treating those arguments as normal strings (like for exmple python.exe or bash would), it decides to evaluate them.
@@ruroruro "Escaping" is only necessary because there's an opaque parser between you and the batch file that you need to appease. It seems insane to me that we've designed programs around adding fluff to a string just so that another program can remove it, hopefully in a symmetric way. When you can't disable, control, or even see this pointless second layer, it's no wonder these injection issues pop up so often.
@@tryashtar Once again. Rewatch the video. There is indeed an opaque parser between you and any other process (CreateProcessW isn't specific to batch files). But the escaping done by Python and the parser inside CreateProcessW cancel each other out PERFECTLY. You can tell that there is no vulnerability in this escape-then-parse logic, because passing arguments to any other executable works just fine. The problem only appears when the target executable is a batch file. That's because the problem is inside the implementation of cmd.exe specifically, not in the CreateProcessW API.
@@ruroruro Yes I understand. I'm not complaining about CreateProcessW, just a general complaint about unparsed strings being the communication method between programs in most operating systems.
I think the create process api is related mostly in that it causes a lot of developer confusion about what needs to be escaped and what doesn't. The cve could still be a thing if we had an array version of it, but I think people would be much less likely to fall for it when they read the docs, which would no longer mention about "escaping" inputs on Windows.
_squints_
Okay, so unless you're already doing something exceptionally *_bad,_* on a platform that sucks, this is an underpants-on-head error.
when people started writting/filming about this "vulnerability" I became confused because it looked like they forgot about SQL injection stories and like they want "nothing needs checking" programs... why are they even programmers ?
Literally: If you rely on passing user input in your program to a batch file for processing, you have bigger problems with your code on a fundamental level.
So, this is in the funny space that includes the interface between the API implementation (by Microsoft) and the consumers of the API.
I got to tell people today something to the effect of "this is the expected operation, please adjust your own operations in order to match," and was met with "but can we change it anyway?"
No. No we cannot. #YouBecomeWhatYouHate #HatingMicrosoftIsAnOkayHatred
Damn I've a mix a suborocess with shell cmds and without one on Linux servers.
So in a nutshell...... sanitize your inputs... got it.... I've never seen something that should be at best a 1 out of 10 be treated as so critical just because people don't know how to sanitize inputs.
Im fairly sure that 99.9% would not be able to sanitize input to pass to batch files properly, and there is no real good resource out there on how to do it. Its not as easy as you think and from the provided "fixes", only Rust did it correctly.
execve for no cve, counter-intuitive
Oh nœh, cve numbers not making any practical sense AGAIN?!
You can just skip a bunch of steps and call Windows as a whole a CVE
10? Nope
What gets me is ... who the hell is making use of batch files and passing arguments through blindly? Bat files are just the pickiest sons of b***ches out there with it's argument list and you have to do it carefully. I know I make use of them to do a whole host of automated file creation/updating with preset values that vary on a few values & a few strings. Though One think I never did was pass the strings directly through to the next bat file without modifying the strings [as they would be from expected values & strings]
bat files are great for aid files for your other programs and projects, and cleanups.. but this whole thing confuses me....
who setups a rust cli tool for windows, that calls a bat file to do something, it could have just done with stored cmd.exe calls, instead based on inteneral logic with code more robust than batch script. This seems like someone doing bad practices overall. There is genuinely no real reason to be calling anything except the most default & specialized bat files from another programing language whatsoever.
I know i've set my own nest of bat files up... but I also am using intellij and doing mods for games and the terminal access to is quick to produce a certain support file for what i need from it.
The random ChatGPT reference was kinda weird. But hey, if that's what you are in to I wont kink shame.
Yeah. Windows. Who would run batch files, anyway?
People who deal with legacy code? Do you know how most of the radar software out there only runs on windows?
@@Ruhrpottpatriot Yes. Also medical equipment, ATM machines (with XP), to name a few.
Wow.... does linux have not a "shell apocalypse" with redefing variables ?
Is there such a thing as issuing a CVE recall? This whole discussion needs to be restarted under a reasonable premise... instead of some researcher getting their cve score inflated to make it sound like they discovered a legitimately critical flaw instead of discovering an old shell with a bad api.
cmd.exe line parsing is garbage. Its handling of circumflex '^' for line splitting is terribly buggy.
Just don't execute untrusted input, lol. It's not a language or platform bug, it's a programming skill issue.
Of course they are following NSA™, I mean, Microsoft® exact instructions. All those silly paranoid people making noise again. How silly!! Lol.
Great explanation as always!!❤
java wont fix im giggling so hard
Literally same as making a rookie mistake of not sanitizing SQL queries.
Skill issue, cry about it.
At this point, programming languages are cementing that windows users have -major skill issues- been unaware of CMD's oddly behaviour.
The amount of bots in this comment section lmao... also, 3 views in 1 min, bro really fell off
Chad C++... Still tge safest language
Then don't have a "Shell=False" flag, seems really annoying if text doesn't to what it says.
OK. So don't run Windows! Microsoft isn't taking security seriously.
Who is still writing batch files? Phhh noobs. I use CMD instead like a pro
What do you mean by using CMD *instead* ?
Rust is not more secure nor securable than C.
Inaccurate. It is more secure in the same sense that the only secure computer is one that's never turned on.
so rust developers just broke windows api because people does not validate inputs?
It only errors when it recieves certain convoluted inputs that it can not escape properly. Unlike Python, it (now) ensures that inputs are always escaped properly in any other case, even for Batch files.
No, Windows API never satisfied a property of POSIX APIs that Rust and many other languages - including those most of Windows is implemented in - expects. Windows batch files in particular cannot be written in a way to compensate. Rust did make the mistake of claiming that the functions would behave POSIX style when Windows made that impossible.