cpan-authors / IPC-Run

https://metacpan.org/pod/IPC::Run
Other
21 stars 38 forks source link

Windows: insufficient quoting of arg containing double quote #142

Closed nmisch closed 3 years ago

nmisch commented 3 years ago

On Windows, a double quotation mark (U+0022) in a command argument causes the argument to expand into multiple arguments:

#! /usr/bin/perl

# Test results w/ Strawberry Perl v5.26.1 and IPC::Run at git commit 211e794.
# Behaviors in question are older.  Same result with ActivePerl v5.24.1.

use strict;
use warnings;
use IPC::Run ();
use Config;

# envision a real program where this argument comes from an untrusted source
my $arg;

$ENV{PATH} = '/usr/bin' if ${^TAINT};
my $perl = $Config{perlpath};
$perl .= $Config{_exe} unless $perl =~ /$Config{_exe}$/i;

# CreateProcess gets: C:\STRAWB~1\perl\bin\perl.exe "-V:u32size \""" -Mnosuch_example"
# got: Can't locate nosuch_example.pm in @INC (you may need to install the nosuch_example module) (@INC contains: C:/Strawberry/perl/site/lib C:/Strawberry/perl/vendor/lib C:/Strawberry/perl/lib .).
# wanted: -Mnosuch_example: not found;
$arg = 'u32size \" -Mnosuch_example';
IPC::Run::run [$perl, "-V:$arg"];

When the argument source is not trusted, this can create a security vulnerability. I discussed the matter with perl5-security-report@perl.org, but we decided to give up on fixing it in private. (Perl/perl5#14434 is a similar vulnerability in core Perl, but the cause is different.)

While Unix has a native argv[] concept, the closest native Windows analog is the GetCommandLine() string. Most applications use standard Microsoft startup code to parse the command line into an argv[] according to rules in https://docs.microsoft.com/en-us/cpp/cpp/main-function-command-line-args#parsing-c-command-line-arguments. There is no Windows API for serializing an array of argument strings into a command line string. IPC::Run's win32_spawn() attempts to quote arguments, without following all those rules.