Fix CVE-2023-47039
This commit is contained in:
parent
afbf4694c4
commit
ad833b01b2
196
backport-CVE-2023-47039.patch
Normal file
196
backport-CVE-2023-47039.patch
Normal file
@ -0,0 +1,196 @@
|
||||
From 906e92715f4ee68ea95086867f4f97b1f4f10ac3 Mon Sep 17 00:00:00 2001
|
||||
From: Tony Cook <tony@develop-help.com>
|
||||
Date: Tue, 3 Oct 2023 09:40:07 +1100
|
||||
Subject: [PATCH] win32: default the shell to cmd.exe in the Windows system
|
||||
directory
|
||||
|
||||
This prevents picking up cmd.exe from the current directory, or
|
||||
even from the PATH.
|
||||
|
||||
This protects against a privilege escalation attack where an attacker
|
||||
in a separate session creates a cmd.exe in a directory where the
|
||||
target account happens to have its current directory.
|
||||
---
|
||||
t/win32/system.t | 30 ++++++++++++--------
|
||||
win32/win32.c | 71 +++++++++++++++++++++++++++++++++++++++++-------
|
||||
2 files changed, 79 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/t/win32/system.t b/t/win32/system.t
|
||||
index 939a02db55..c885059012 100644
|
||||
--- a/t/win32/system.t
|
||||
+++ b/t/win32/system.t
|
||||
@@ -82,6 +82,7 @@ close $F;
|
||||
chdir($testdir);
|
||||
END {
|
||||
chdir($cwd) && rmtree("$cwd/$testdir") if -d "$cwd/$testdir";
|
||||
+ unlink "cmd.exe";
|
||||
}
|
||||
if (open(my $EIN, "$cwd/win32/${exename}_exe.uu")) {
|
||||
note "Unpacking $exename.exe";
|
||||
@@ -104,21 +105,20 @@ else {
|
||||
}
|
||||
note "Compiling $exename.c";
|
||||
note "$Config{cc} $Config{ccflags} $exename.c";
|
||||
- if (system("$Config{cc} $Config{ccflags} $minus_o $exename.c >log 2>&1") != 0) {
|
||||
+ if (system("$Config{cc} $Config{ccflags} $minus_o $exename.c >log 2>&1") != 0 ||
|
||||
+ !-f "$exename.exe") {
|
||||
note "Could not compile $exename.c, status $?";
|
||||
- note "Where is your C compiler?";
|
||||
- skip_all "can't build test executable";
|
||||
- }
|
||||
- unless (-f "$exename.exe") {
|
||||
- if (open(LOG,'<log'))
|
||||
- {
|
||||
- while(<LOG>) {
|
||||
- note $_;
|
||||
- }
|
||||
- }
|
||||
+ note "Where is your C compiler?";
|
||||
+ if (open(LOG,'<log'))
|
||||
+ {
|
||||
+ while(<LOG>) {
|
||||
+ note $_;
|
||||
+ }
|
||||
+ }
|
||||
else {
|
||||
- warn "Cannot open log (in $testdir):$!";
|
||||
+ warn "Cannot open log (in $testdir):$!";
|
||||
}
|
||||
+ skip_all "can't build test executable";
|
||||
}
|
||||
}
|
||||
copy("$plxname.bat","$plxname.cmd");
|
||||
@@ -128,6 +128,12 @@ unless (-x "$testdir/$exename.exe") {
|
||||
skip_all "can't build test executable";
|
||||
}
|
||||
|
||||
+# test we only look for cmd.exe in the standard place
|
||||
+delete $ENV{PERLSHELL};
|
||||
+copy("$testdir/$exename.exe", "$testdir/cmd.exe") or die $!;
|
||||
+copy("$testdir/$exename.exe", "cmd.exe") or die $!;
|
||||
+$ENV{PATH} = qq("$testdir";$ENV{PATH});
|
||||
+
|
||||
open my $T, "$^X -I../lib -w win32/system_tests |"
|
||||
or die "Can't spawn win32/system_tests: $!";
|
||||
my $expect;
|
||||
diff --git a/win32/win32.c b/win32/win32.c
|
||||
index 94248ca168..5d54cf8d4a 100644
|
||||
--- a/win32/win32.c
|
||||
+++ b/win32/win32.c
|
||||
@@ -117,7 +117,7 @@ static char* win32_get_xlib(const char *pl,
|
||||
|
||||
static BOOL has_shell_metachars(const char *ptr);
|
||||
static long tokenize(const char *str, char **dest, char ***destv);
|
||||
-static void get_shell(void);
|
||||
+static int get_shell(void);
|
||||
static char* find_next_space(const char *s);
|
||||
static int do_spawn2(pTHX_ const char *cmd, int exectype);
|
||||
static int do_spawn2_handles(pTHX_ const char *cmd, int exectype,
|
||||
@@ -600,7 +600,13 @@ tokenize(const char *str, char **dest, char ***destv)
|
||||
return items;
|
||||
}
|
||||
|
||||
-static void
|
||||
+static const char
|
||||
+cmd_opts[] = "/x/d/c";
|
||||
+
|
||||
+static const char
|
||||
+shell_cmd[] = "cmd.exe";
|
||||
+
|
||||
+static int
|
||||
get_shell(void)
|
||||
{
|
||||
dTHX;
|
||||
@@ -612,12 +618,53 @@ get_shell(void)
|
||||
* interactive use (which is what most programs look in COMSPEC
|
||||
* for).
|
||||
*/
|
||||
- const char* defaultshell = "cmd.exe /x/d/c";
|
||||
- const char *usershell = PerlEnv_getenv("PERL5SHELL");
|
||||
- w32_perlshell_items = tokenize(usershell ? usershell : defaultshell,
|
||||
- &w32_perlshell_tokens,
|
||||
- &w32_perlshell_vec);
|
||||
+ const char *shell = PerlEnv_getenv("PERL5SHELL");
|
||||
+ if (shell) {
|
||||
+ w32_perlshell_items = tokenize(shell,
|
||||
+ &w32_perlshell_tokens,
|
||||
+ &w32_perlshell_vec);
|
||||
+ }
|
||||
+ else {
|
||||
+ /* tokenize does some Unix-ish like things like
|
||||
+ \\ escaping that don't work well here
|
||||
+ */
|
||||
+ char shellbuf[MAX_PATH];
|
||||
+ UINT len = GetSystemDirectoryA(shellbuf, sizeof(shellbuf));
|
||||
+ if (len == 0) {
|
||||
+ translate_to_errno();
|
||||
+ return -1;
|
||||
+ }
|
||||
+ else if (len >= MAX_PATH) {
|
||||
+ /* buffer too small */
|
||||
+ errno = E2BIG;
|
||||
+ return -1;
|
||||
+ }
|
||||
+ if (shellbuf[len-1] != '\\') {
|
||||
+ my_strlcat(shellbuf, "\\", sizeof(shellbuf));
|
||||
+ ++len;
|
||||
+ }
|
||||
+ if (len + sizeof(shell_cmd) > sizeof(shellbuf)) {
|
||||
+ errno = E2BIG;
|
||||
+ return -1;
|
||||
+ }
|
||||
+ my_strlcat(shellbuf, shell_cmd, sizeof(shellbuf));
|
||||
+ len += sizeof(shell_cmd)-1;
|
||||
+
|
||||
+ Newx(w32_perlshell_vec, 3, char *);
|
||||
+ Newx(w32_perlshell_tokens, len + 1 + sizeof(cmd_opts), char);
|
||||
+
|
||||
+ my_strlcpy(w32_perlshell_tokens, shellbuf, len+1);
|
||||
+ my_strlcpy(w32_perlshell_tokens + len +1, cmd_opts,
|
||||
+ sizeof(cmd_opts));
|
||||
+
|
||||
+ w32_perlshell_vec[0] = w32_perlshell_tokens;
|
||||
+ w32_perlshell_vec[1] = w32_perlshell_tokens + len + 1;
|
||||
+ w32_perlshell_vec[2] = NULL;
|
||||
+
|
||||
+ w32_perlshell_items = 2;
|
||||
+ }
|
||||
}
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -635,7 +682,9 @@ Perl_do_aspawn(pTHX_ SV *really, SV **mark, SV **sp)
|
||||
if (sp <= mark)
|
||||
return -1;
|
||||
|
||||
- get_shell();
|
||||
+ if (get_shell() < 0)
|
||||
+ return -1;
|
||||
+
|
||||
Newx(argv, (sp - mark) + w32_perlshell_items + 2, const char*);
|
||||
|
||||
if (SvNIOKp(*(mark+1)) && !SvPOKp(*(mark+1))) {
|
||||
@@ -765,7 +814,8 @@ do_spawn2_handles(pTHX_ const char *cmd, int exectype, const int *handles)
|
||||
if (needToTry) {
|
||||
char **argv;
|
||||
int i = -1;
|
||||
- get_shell();
|
||||
+ if (get_shell() < 0)
|
||||
+ return -1;
|
||||
Newx(argv, w32_perlshell_items + 2, char*);
|
||||
while (++i < w32_perlshell_items)
|
||||
argv[i] = w32_perlshell_vec[i];
|
||||
@@ -3482,7 +3532,8 @@ win32_pipe(int *pfd, unsigned int size, int mode)
|
||||
DllExport PerlIO*
|
||||
win32_popenlist(const char *mode, IV narg, SV **args)
|
||||
{
|
||||
- get_shell();
|
||||
+ if (get_shell() < 0)
|
||||
+ return NULL;
|
||||
|
||||
return do_popen(mode, NULL, narg, args);
|
||||
}
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -24,7 +24,7 @@ Name: perl
|
||||
License: (GPL+ or Artistic) and (GPLv2+ or Artistic) and MIT and UCD and Public Domain and BSD
|
||||
Epoch: 4
|
||||
Version: %{perl_version}
|
||||
Release: 3
|
||||
Release: 4
|
||||
Summary: A highly capable, feature-rich programming language
|
||||
Url: https://www.perl.org/
|
||||
Source0: https://www.cpan.org/src/5.0/%{name}-%{version}.tar.xz
|
||||
@ -36,6 +36,7 @@ Patch4: perl-5.34.0-Destroy-GDBM-NDBM-ODBM-SDBM-_File-objects-only-from-.patch
|
||||
Patch5: change-lib-to-lib64.patch
|
||||
Patch6: disable-rpath-by-default.patch
|
||||
Patch7: backport-CVE-2023-47038.patch
|
||||
Patch8: backport-CVE-2023-47039.patch
|
||||
|
||||
BuildRequires: gcc bash findutils coreutils make tar procps bzip2-devel gdbm-devel perl-File-Compare perl-File-Find
|
||||
BuildRequires: zlib-devel perl-interpreter perl-generators
|
||||
@ -497,6 +498,9 @@ make test_harness
|
||||
%{_mandir}/man3/*
|
||||
|
||||
%changelog
|
||||
* Fri Dec 8 2023 hongjinghao <hongjinghao@huawei.com> - 4:5.38.0.4
|
||||
- Fix CVE-2023-48039
|
||||
|
||||
* Mon Nov 27 2023 hongjinghao <hongjinghao@huawei.com> - 4:5.38.0.3
|
||||
- Fix CVE-2023-47038
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user