I read quickly the PEP, I'm not sure that I understood it correctly, so here are some early questions more about the usage of the PEP, than its implementation.
This is not sandboxing, as this proposal does not attempt to prevent malicious behavior (though it enables some new options to do so). See the `Why Not A Sandbox`_ section below for further discussion.
I don't understand well the overall security model. If malicious behaviors can still occur, what is the the purpose of auditing? For example, if an audit hook writes events into a local log file, the attacker can easily remove this log file, no?
While you say that it's not a sandbox, you designed multiple protections to protect auditing, and the design is very close to a sandbox.
"``_PyObject_GenericSetAttr``, ``check_set_special_type_attr``, ``object_set_class``, ``func_set_code``, ``func_set_[kw]defaults``"," ``object.__setattr__``","``(object, attr, value)``","Detect monkey patching of types and objects. This event is raised for the ``__class__`` attribute and any attribute on ``type`` objects.
It reminds me Python 2 Bastion module which has simply been removed because it was unsafe: https://docs.python.org/2/library/bastion.html
For example, using ctypes, you can access directly the underlying dictionary of a type and modify "private" attributes. It's just an example.
I wrote pysandbox in the past, and it was broken by default, as you wrote in the PEP :-)
The failure of pysandbox (2013) https://lwn.net/Articles/574215/
If you want to secure Python, run Python in a sandbox, don't try to "add" a sandbox "on top" of Python (I know that it's more complicated in practice).
Or use PyPy sandbox which has a very different design.
Le jeu. 28 mars 2019 à 23:39, Steve Dower firstname.lastname@example.org a écrit :
This PEP describes additions to the Python API and specific behaviors for the CPython implementation that make actions taken by the Python runtime visible to auditing tools. Visibility into these actions provides opportunities for test frameworks, logging frameworks, and security tools to monitor and optionally limit actions taken by the runtime.
Is it possible to implement these features without adding a new API or modifying Python?
Short example adding logs to open(): --- import builtins import functools
def add_log(name, func): @functools.wraps(func) def wrapper(*args): print(name, args) return func(*args) return wrapper
builtins.open = add_log("open", builtins.open)
Verified Open Hook
Most operating systems have a mechanism to distinguish between files that can be executed and those that can not. For example, this may be an execute bit in the permissions field, a verified hash of the file contents to detect potential code tampering, or file system path restrictions. These are an important security mechanism for preventing execution of data or code that is not approved for a given environment. Currently, Python has no way to integrate with these when launching scripts or importing modules.
In my experience, it doesn't work just because Python has too many functions opening files indirectly or call external C libraries which open files.
I vaguely recall an exploit in my pysandbox project which uses the internal code of Python which displays a traceback... to read the content of an arbitrary file on the disk :-( Game over. I would never expect that there are so many ways to read a file in Python...
Even when I restricted pysandbox to the bare minimum of the Python language (with no import), multiple exploits have been found. Moreover, at the end, Python just became useful.
More generally, there are a lot of codes in Python which allow arbitrary code injection :-( (Most of them are now fixed, hopefully!)
I did my best to modify as much functions as possible to implement the PEP 446 "Make newly created file descriptors non-inheritable", but I know that *many* functions call directly open() or fopen() and so create inheritable file descriptors. For example, the Python ssl module takes directly filenames and OpenSSL open directly files. It's just one example.
You will never be able to cover all cases.
Having a single function which allows to open an arbitrary file without triggering an audit event would defeat the whole purpose of auditing, no? Again, maybe I didn't understand well the overall purpose of the PEP, sorry.
Table 2 provides further examples that are not required, but are likely to be available in CPython. (...) Performance Impact ==================
The important performance impact is the case where events are being raised but there are no hooks attached. This is the unavoidable case - once a developer has added audit hooks they have explicitly chosen to trade performance for functionality.
(The Linux kernel uses advance tooling to inject hooks: it has no impact on performances when no hook is used. Machine code of functions is patched to inject a hook. Impressive stuff :-))
Here I expect a small overhead. But the global overhead will be proportional to the number of hooks, no? Maybe it's not significant with the proposed list of events, but it will be more significant with 100 or 1000 events?
I'm not saying that it's a blocker issue, I'm just thinking aloud to make sure that I understood correctly :-)
Victor -- Night gathers, and now my watch begins. It shall not end until my death.