From a019245faa12aaea0bf3e77d17c0aa610df49d94 Mon Sep 17 00:00:00 2001 From: Oleg Iarygin Date: Thu, 9 Feb 2023 02:12:19 +0400 Subject: [PATCH 1/2] gh-101283: Improved fallback logic for subprocess with shell=True on Windows (GH-101286) (cherry picked from commit 23751ed826ee63fb486e874ec25934ea87dd8519) Co-authored-by: Oleg Iarygin --- Doc/library/subprocess.rst | 40 +++++++++++++++++++ Lib/subprocess.py | 16 +++++++- ...-01-24-16-12-00.gh-issue-101283.9tqu39.rst | 3 ++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Security/2023-01-24-16-12-00.gh-issue-101283.9tqu39.rst diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index 7ce274652d394a..ebd1577bff1332 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -111,6 +111,14 @@ compatibility with older versions, see the :ref:`call-function-trio` section. Added the *text* parameter, as a more understandable alias of *universal_newlines*. Added the *capture_output* parameter. + .. versionchanged:: 3.11.2 + + Changed Windows shell search order for ``shell=True``. The current + directory and ``%PATH%`` are replaced with ``%COMSPEC%`` and + ``%SystemRoot%\System32\cmd.exe``. As a result, dropping a + malicious program named ``cmd.exe`` into a current directory no + longer works. + .. class:: CompletedProcess The return value from :func:`run`, representing a process that has finished. @@ -459,6 +467,14 @@ functions. *executable* parameter accepts a bytes and :term:`path-like object` on Windows. + .. versionchanged:: 3.11.2 + + Changed Windows shell search order for ``shell=True``. The current + directory and ``%PATH%`` are replaced with ``%COMSPEC%`` and + ``%SystemRoot%\System32\cmd.exe``. As a result, dropping a + malicious program named ``cmd.exe`` into a current directory no + longer works. + *stdin*, *stdout* and *stderr* specify the executed program's standard input, standard output and standard error file handles, respectively. Valid values are :data:`PIPE`, :data:`DEVNULL`, an existing file descriptor (a positive @@ -1077,6 +1093,14 @@ calls these functions. .. versionchanged:: 3.3 *timeout* was added. + .. versionchanged:: 3.11.2 + + Changed Windows shell search order for ``shell=True``. The current + directory and ``%PATH%`` are replaced with ``%COMSPEC%`` and + ``%SystemRoot%\System32\cmd.exe``. As a result, dropping a + malicious program named ``cmd.exe`` into a current directory no + longer works. + .. function:: check_call(args, *, stdin=None, stdout=None, stderr=None, \ shell=False, cwd=None, timeout=None, \ **other_popen_kwargs) @@ -1107,6 +1131,14 @@ calls these functions. .. versionchanged:: 3.3 *timeout* was added. + .. versionchanged:: 3.11.2 + + Changed Windows shell search order for ``shell=True``. The current + directory and ``%PATH%`` are replaced with ``%COMSPEC%`` and + ``%SystemRoot%\System32\cmd.exe``. As a result, dropping a + malicious program named ``cmd.exe`` into a current directory no + longer works. + .. function:: check_output(args, *, stdin=None, stderr=None, shell=False, \ cwd=None, encoding=None, errors=None, \ @@ -1162,6 +1194,14 @@ calls these functions. .. versionadded:: 3.7 *text* was added as a more readable alias for *universal_newlines*. + .. versionchanged:: 3.11.2 + + Changed Windows shell search order for ``shell=True``. The current + directory and ``%PATH%`` are replaced with ``%COMSPEC%`` and + ``%SystemRoot%\System32\cmd.exe``. As a result, dropping a + malicious program named ``cmd.exe`` into a current directory no + longer works. + .. _subprocess-replacements: diff --git a/Lib/subprocess.py b/Lib/subprocess.py index d4d04a5c3436a6..9dd9deb24ed9f9 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -1298,7 +1298,21 @@ def _execute_child(self, args, executable, preexec_fn, close_fds, if shell: startupinfo.dwFlags |= _winapi.STARTF_USESHOWWINDOW startupinfo.wShowWindow = _winapi.SW_HIDE - comspec = os.environ.get("COMSPEC", "cmd.exe") + if not executable: + # gh-101283: without a fully-qualified path, before Windows + # checks the system directories, it first looks in the + # application directory, and also the current directory if + # NeedCurrentDirectoryForExePathW(ExeName) is true, so try + # to avoid executing unqualified "cmd.exe". + comspec = os.environ.get('ComSpec') + if not comspec: + system_root = os.environ.get('SystemRoot', '') + comspec = os.path.join(system_root, 'System32', 'cmd.exe') + if not os.path.isabs(comspec): + raise FileNotFoundError('shell not found: neither %ComSpec% nor %SystemRoot% is set') + if os.path.isabs(comspec): + executable = comspec + args = '{} /c "{}"'.format (comspec, args) if cwd is not None: diff --git a/Misc/NEWS.d/next/Security/2023-01-24-16-12-00.gh-issue-101283.9tqu39.rst b/Misc/NEWS.d/next/Security/2023-01-24-16-12-00.gh-issue-101283.9tqu39.rst new file mode 100644 index 00000000000000..0efdfa10234185 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2023-01-24-16-12-00.gh-issue-101283.9tqu39.rst @@ -0,0 +1,3 @@ +:class:`subprocess.Popen` now uses a safer approach to find +``cmd.exe`` when launching with ``shell=True``. Patch by Eryk Sun, +based on a patch by Oleg Iarygin. From fd3390bca981376617e31fc325ef07e6e4415859 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 8 Feb 2023 22:31:13 +0000 Subject: [PATCH 2/2] Apply suggestions from code review --- Doc/library/subprocess.rst | 10 +++++----- Lib/subprocess.py | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index ebd1577bff1332..8eea5a474eda7c 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -111,7 +111,7 @@ compatibility with older versions, see the :ref:`call-function-trio` section. Added the *text* parameter, as a more understandable alias of *universal_newlines*. Added the *capture_output* parameter. - .. versionchanged:: 3.11.2 + .. versionchanged:: 3.8.17 Changed Windows shell search order for ``shell=True``. The current directory and ``%PATH%`` are replaced with ``%COMSPEC%`` and @@ -467,7 +467,7 @@ functions. *executable* parameter accepts a bytes and :term:`path-like object` on Windows. - .. versionchanged:: 3.11.2 + .. versionchanged:: 3.8.17 Changed Windows shell search order for ``shell=True``. The current directory and ``%PATH%`` are replaced with ``%COMSPEC%`` and @@ -1093,7 +1093,7 @@ calls these functions. .. versionchanged:: 3.3 *timeout* was added. - .. versionchanged:: 3.11.2 + .. versionchanged:: 3.8.17 Changed Windows shell search order for ``shell=True``. The current directory and ``%PATH%`` are replaced with ``%COMSPEC%`` and @@ -1131,7 +1131,7 @@ calls these functions. .. versionchanged:: 3.3 *timeout* was added. - .. versionchanged:: 3.11.2 + .. versionchanged:: 3.8.17 Changed Windows shell search order for ``shell=True``. The current directory and ``%PATH%`` are replaced with ``%COMSPEC%`` and @@ -1194,7 +1194,7 @@ calls these functions. .. versionadded:: 3.7 *text* was added as a more readable alias for *universal_newlines*. - .. versionchanged:: 3.11.2 + .. versionchanged:: 3.8.17 Changed Windows shell search order for ``shell=True``. The current directory and ``%PATH%`` are replaced with ``%COMSPEC%`` and diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 9dd9deb24ed9f9..7d363fa3153fa4 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -1312,6 +1312,8 @@ def _execute_child(self, args, executable, preexec_fn, close_fds, raise FileNotFoundError('shell not found: neither %ComSpec% nor %SystemRoot% is set') if os.path.isabs(comspec): executable = comspec + else: + comspec = executable args = '{} /c "{}"'.format (comspec, args) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy