Improve PEPs 551 and 578 (#679)

This commit is contained in:
Steve Dower 2018-07-04 09:53:40 -07:00 committed by GitHub
parent 267ef773c6
commit 0440c6d4f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 82 additions and 44 deletions

View File

@ -10,16 +10,16 @@ Created: 23-Aug-2017
Python-Version: 3.7 Python-Version: 3.7
Post-History: 24-Aug-2017 (security-sig), 28-Aug-2017 (python-dev) Post-History: 24-Aug-2017 (security-sig), 28-Aug-2017 (python-dev)
Status Relationship to PEP 578
====== =======================
This PEP is currently in the process of being split into two. This PEP has been split into two since its original posting.
See PEP 578 for the new auditing APIs proposed for addition to the next See `PEP 578 <https://www.python.org/dev/peps/pep-0578/>`_ for the
version of Python. auditing APIs proposed for addition to the next version of Python.
PEP 551 is now a draft informational PEP, providing guidance to those This is now an informational PEP, providing guidance to those planning
planning to integrate Python into their secure or audited environments. to integrate Python into their secure or audited environments.
Abstract Abstract
======== ========
@ -417,7 +417,30 @@ Since ``importlib``'s use of ``open_for_import`` may be easily bypassed
with monkeypatching, an audit hook **should** be used to detect with monkeypatching, an audit hook **should** be used to detect
attribute changes on type objects. attribute changes on type objects.
[TODO: more good advice; less bad advice] Rejected Advice
===============
This section discusses common or "obviously good" recommendations that
we are specifically *not* making. These range from useless or incorrect
through to ideas that are simply not feasible in any real world
environment.
**Do not** 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 [14]_), 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.
**Do not** 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.
**Do not** use audit hooks to abort operations without logging the
event first. You will regret not knowing why your process disappeared.
[TODO - more bad advice]
Further Reading Further Reading
=============== ===============
@ -474,7 +497,7 @@ References
.. [4] `<https://aka.ms/deviceguard>`_ .. [4] `<https://aka.ms/deviceguard>`_
.. [5] AMSI, `<https://msdn.microsoft.com/en-us/library/windows/desktop/dn889587(v=vs.85).aspx>`_ .. [5] Antimalware Scan Interface, `<https://msdn.microsoft.com/en-us/library/windows/desktop/dn889587(v=vs.85).aspx>`_
.. [6] Persistent Zone Identifiers, `<https://msdn.microsoft.com/en-us/library/ms537021(v=vs.85).aspx>`_ .. [6] Persistent Zone Identifiers, `<https://msdn.microsoft.com/en-us/library/ms537021(v=vs.85).aspx>`_
@ -492,6 +515,8 @@ References
.. [13] SELinux access decisions `<http://man7.org/linux/man-pages/man3/avc_entry_ref_init.3.html>`_ .. [13] SELinux access decisions `<http://man7.org/linux/man-pages/man3/avc_entry_ref_init.3.html>`_
.. [14] The failure of pysandbox `<https://lwn.net/Articles/574215/>`_
Acknowledgments Acknowledgments
=============== ===============

View File

@ -356,6 +356,10 @@ see which operations provide audit events.
``_ctypes._CData``, ``ctypes.cdata``, "``(ptr_as_int,)``", "Detect ``_ctypes._CData``, ``ctypes.cdata``, "``(ptr_as_int,)``", "Detect
when code is accessing arbitrary memory using ``ctypes``. when code is accessing arbitrary memory using ``ctypes``.
" "
"``new_mmap_object``",``mmap.__new__``,"``(fileno, map_size, access,
offset)``", "Detects creation of mmap objects. On POSIX, access may
have been calculated from the ``prot`` and ``flags`` arguments.
"
``sys._getframe``, ``sys._getframe``, "``(frame_object,)``", "Detect ``sys._getframe``, ``sys._getframe``, "``(frame_object,)``", "Detect
when code is accessing frames directly. when code is accessing frames directly.
" "
@ -374,21 +378,23 @@ see which operations provide audit events.
members that are marked as restricted, and members that may allow members that are marked as restricted, and members that may allow
bypassing imports. bypassing imports.
" "
"``urllib.urlopen``",``urllib.Request``,"``(url, data, headers,
method)``", "Detects URL requests.
"
Performance Impact Performance Impact
================== ==================
The important performance impact is the case where events are being The important performance impact is the case where events are being
raised but there are no hooks attached. This is the unavoidable case - raised but there are no hooks attached. This is the unavoidable case -
once a distributor or sysadmin begins adding audit hooks they have once a distributor begins adding audit hooks they have explicitly
explicitly chosen to trade performance for functionality. Performance chosen to trade performance for functionality. Performance import
impact using ``spython`` or with hooks added are not of interest here, with hooks added are not of interest here, since this is considered
since this is considered opt-in functionality. opt-in functionality.
Analysis using the ``performance`` tool shows no significant impact, Analysis using the Python Performance Benchmark Suite [1]_ shows no
with the vast majority of benchmarks showing between 1.05x faster to significant impact, with the vast majority of benchmarks showing
1.05x slower. between 1.05x faster to 1.05x slower.
In our opinion, the performance impact of the set of auditing points In our opinion, the performance impact of the set of auditing points
described in this PEP is negligible. described in this PEP is negligible.
@ -407,7 +413,7 @@ The proposal is to add a new module for audit hooks, hypothetically
Any such module would need to be a built-in module that is guaranteed to Any such module would need to be a built-in module that is guaranteed to
always be present. The nature of these hooks is that they must be always be present. The nature of these hooks is that they must be
callable without condition, as any conditional imports or calls provide callable without condition, as any conditional imports or calls provide
more opportunities to intercept and suppress or modify events. opportunities to intercept and suppress or modify events.
Given its nature as one of the most core modules, the ``sys`` module is Given its nature as one of the most core modules, the ``sys`` module is
somewhat protected against module shadowing attacks. Replacing ``sys`` somewhat protected against module shadowing attacks. Replacing ``sys``
@ -415,7 +421,8 @@ with a sufficiently functional module that the application can still run
is a much more complicated task than replacing a module with only one is a much more complicated task than replacing a module with only one
function of interest. An attacker that has the ability to shadow the function of interest. An attacker that has the ability to shadow the
``sys`` module is already capable of running arbitrary code from files, ``sys`` module is already capable of running arbitrary code from files,
whereas an ``audit`` module can be replaced with a single statement:: whereas an ``audit`` module can be replaced with a single line in a
``.pth`` file anywhere on the search path::
import sys; sys.modules['audit'] = type('audit', (object,), import sys; sys.modules['audit'] = type('audit', (object,),
{'audit': lambda *a: None, 'addhook': lambda *a: None}) {'audit': lambda *a: None, 'addhook': lambda *a: None})
@ -425,28 +432,27 @@ against either ``sys`` or ``audit``, but assignments or insertions to
``sys.modules`` are not audited. ``sys.modules`` are not audited.
This idea is rejected because it makes substituting ``audit`` calls This idea is rejected because it makes substituting ``audit`` calls
throughout all callers near trivial. throughout all callers trivial.
Flag in sys.flags to indicate "secure" mode Flag in sys.flags to indicate "audited" mode
------------------------------------------- --------------------------------------------
The proposal is to add a value in ``sys.flags`` to indicate when Python The proposal is to add a value in ``sys.flags`` to indicate when Python
is running in a "secure" mode. This would allow applications to detect is running in a "secure" or "audited" mode. This would allow
when some features are enabled and modify their behaviour appropriately. applications to detect when some features are enabled or when hooks
have been added and modify their behaviour appropriately.
Currently there are no guarantees made about security by this PEP - this Currently, we are not aware of any legitimate reasons for a program to
section is the first time the word "secure" has been used. Security behave differently in the presence of audit hooks.
**transparency** does not result in any changed behaviour, so there is
no appropriate reason for applications to modify their behaviour.
Both application-level APIs ``sys.audit`` and ``_imp.open_for_import`` Both application-level APIs ``sys.audit`` and
are always present and functional, regardless of whether the regular ``importlib.util.open_for_import`` are always present and functional,
``python`` entry point or some alternative entry point is used. Callers regardless of whether the regular ``python`` entry point or some
cannot determine whether any hooks have been added (except by performing alternative entry point is used. Callers cannot determine whether any
side-channel analysis), nor do they need to. The calls should be fast hooks have been added (except by performing side-channel analysis), nor
enough that callers do not need to avoid them, and the sysadmin is do they need to. The calls should be fast enough that callers do not
responsible for ensuring their added hooks are fast enough to not affect need to avoid them, and the program is responsible for ensuring that
application performance. any added hooks are fast enough to not affect application performance.
The argument that this is "security by obscurity" is valid, but The argument that this is "security by obscurity" is valid, but
irrelevant. Security by obscurity is only an issue when there are no irrelevant. Security by obscurity is only an issue when there are no
@ -459,16 +465,23 @@ This idea is rejected because there are no appropriate reasons for an
application to change its behaviour based on whether these APIs are in application to change its behaviour based on whether these APIs are in
use. use.
Relationship to PEP 551
=======================
Acknowledgments This API was originally presented as part of
=============== `PEP 551 <https://www.python.org/dev/peps/pep-0551/>`_ Security
Transparency in the Python Runtime.
Thanks to all the people from Microsoft involved in helping make the For simpler review purposes, and due to the broader applicability of
Python runtime safer for production use, and especially to James Powell these APIs beyond security, the API design is now presented separately.
for doing much of the initial research, analysis and implementation, Lee
Holmes for invaluable insights into the info-sec field and PowerShell's PEP 551 is an informational PEP discussing how to integrate Python into
responses, and Brett Cannon for the restraining and grounding a secure or audited environment.
discussions.
References
==========
.. [1] Python Performance Benchmark Suite `<https://github.com/python/performance>`_
Copyright Copyright
========= =========