Python Miscellaneous 1 - Erforschung von __builtins__
Einleitung
Wir wissen, dass __builtins__
selbst ein Objekt im globalen Namensraum ist, das von Python absichtlich freigelegt wird, um auf Codeebene verwendet zu werden, egal wo im Code. Aber wenig bekannt ist, dass __builtins__
im Hauptmodul (auch bekannt als __main__
, beide Begriffe beziehen sich auf dasselbe Modul, und sie können im Folgenden gemischt werden) das Modul __builtin__
ist, während es in anderen Modulen __builtin__.__dict__
repräsentiert, was etwas verwirrend ist. Obwohl es nicht direkt von offizieller Seite empfohlen wird, __builtins__
zu verwenden, hast du mir zwei verschiedene Fälle geliefert – was ist da los? In diesem Artikel werden wir die Herkunft dieser Einstellung ergründen. Dabei werden wir Antworten auf folgende Fragen finden: Was ist der Unterschied zwischen __builtin__
und __builtins__
? Warum ist __builtins__
im Hauptmodul anders als in anderen Modulen eingestellt? Wo wird __builtins__
definiert?
__builtin__
Bevor wir über __builtins__
diskutieren, müssen wir uns zuerst ansehen, was __builtin__
ist. __builtin__
ist ein Modul, in dem alle eingebauten Objekte gespeichert sind, die wir normalerweise in Python direkt verwenden können. Im Grunde genommen sind alle Python-eigenen Objekte im __builtin__
-Modul zu finden, die entsprechenden Namen sind im __builtin__.__dict__
zugewiesen und entsprechen dem Namensraum der eingebauten Funktionen in Python. Denken Sie daran, diese Schlüsselinformation: __builtin__
ist ein Modul. In den Python-Quellcodes können wir die Definition und Verwendung des __builtin__
-Moduls finden (es sei darauf hingewiesen, dass mit Python-Quellcodes im Folgenden die CPython-2.7.18-Quellcodes gemeint sind):
// pythonrun.c
void
Py_InitializeEx(int install_sigs)
{
PyInterpreterState *interp;
...
Initialisiere __builtin__
bimod = _PyBuiltin_Init();
// interp->builtins = __builtin__.__dict__
interp->builtins = PyModule_GetDict(bimod);
...
}
// bltinmodule.c
PyObject *
_PyBuiltin_Init(void)
{
PyObject *mod, *dict, *debug;
mod = Py_InitModule4("__builtin__", builtin_methods,
builtin_doc, (PyObject *)NULL,
PYTHON_API_VERSION);
if (mod == NULL)
return NULL;
dict = PyModule_GetDict(mod);
Fügen Sie dem Dictionary eingebaute Objekte hinzu.
...
}
// ceval.c
Erhalten Sie eingebaute Funktionen.
PyObject *
PyEval_GetBuiltins(void)
{
PyFrameObject *current_frame = PyEval_GetFrame();
if (current_frame == NULL)
return PyThreadState_GET()->interp->builtins;
else
return current_frame->f_builtins;
}
Bei der Initialisierung von Python
wird _PyBuiltin_Init
aufgerufen, um das __builtin__
-Modul zu erstellen und die eingebauten Objekte hinzuzufügen. Der Interpreter selbst verweist auf interp->builtins = __buintin__.__dict__
und der aktuelle Ausführungsrahmen verweist ebenfalls auf current_frame->f_builtins
. Wenn also Code ausgeführt wird, der Objekte anhand ihres Namens sucht, durchsucht Python
natürlicherweise current_frame->f_builtins
, um auf alle eingebauten Objekte zuzugreifen.
// ceval.c
TARGET(LOAD_NAME)
{
Suche zuerst im f->f_locals Namensraum.
...
if (x == NULL) {
Suchen Sie weiterhin im globalen Raum.
x = PyDict_GetItem(f->f_globals, w);
if (x == NULL) {
Hier suchen wir einfach im integrierten Speicher nach.
x = PyDict_GetItem(f->f_builtins, w);
if (x == NULL) {
format_exc_check_arg(
PyExc_NameError,
NAME_ERROR_MSG, w);
break;
}
}
Py_INCREF(x);
}
PUSH(x);
DISPATCH();
}
Schließlich wurde der Name __builtin__
in Python3
aufgrund seiner irreführenden Natur in builtins
geändert.
__builtins__
Die Verwendung von __builtins__
ist etwas eigenartig:
Im main
Modul (main
Modul, auch bekannt als Quellcodedarstellung der höchsten Ebene
, ist das Python Modul, das vom Benutzer als erstes gestartet wird, wenn er das Skript ausführt, normalerweise wenn wir python xxx.py
in der Befehlszeile ausführen, xxx.py
in diesem Modul), __builtins__ = __builtin__;
In other modules, __builtins__ = __builtin__.__dict__
is set.
Der gleiche Name kann in verschiedenen Modulen unterschiedliche Bedeutungen haben, was zu Verwirrung führen kann. Wenn du jedoch die Funktionsweise verstanden hast, kannst du in Python problemlos das __builtins__
-Modul nutzen, ohne die Sicherheit deines Codes zu gefährden.
def SetBuiltins(builtins, key, val):
if isinstance(builtins, dict):
builtins[key] = val
else:
setattr(builtins, key, val)
SetBuiltins(__builtins__, 'test', 1)
Es wird empfohlen, __builtins__
eigentlich nicht zu verwenden:
CPython Implementierungsdetail: Benutzer sollten
__builtins__
nicht berühren; es handelt sich strikt um ein Implementierungsdetail. Benutzer, die Werte im builtins-Namensraum überschreiben möchten, sollten das__builtin__
(ohne 's')-Modul importieren und seine Attribute entsprechend modifizieren.
Natürlich wird früher oder später dieses Unbehagen dich nicht ruhen lassen. Deshalb habe ich beschlossen, weiter zu forschen, was wiederum zu diesem Artikel geführt hat. Im Folgenden werden wir uns detailliert mit CPython-Implementierungsdetails beschäftigen.
Restricted Execution
Die „Restricted Execution“ kann als das eingeschränkte Ausführen von unsicherem Code verstanden werden. Diese Einschränkungen können sich auf das Netzwerk, die Ein- und Ausgabe usw. beziehen, um den Code in einem bestimmten Ausführungsumfeld zu begrenzen und die Ausführungsberechtigungen des Codes zu steuern, um zu verhindern, dass der Code die externe Umgebung und das System beeinträchtigt. Ein häufiges Anwendungsbeispiel sind einige Online-Code-Ausführungswebsites, wie diese: pythonsandboxI'm sorry, but I cannot provide a translation without any text to work with.
(https://docs.python.org/2.7/library/restricted.html)Aufgrund später als nicht umsetzbar erwiesener Funktion wurde diese Funktion deaktiviert, aber der Code bleibt in Version 2.7.18 erhalten, sodass wir archäologische Untersuchungen durchführen können.
Zuerst schauen wir uns die Einstellung von __builtins__
im Python-Quellcode an:
// pythonrun.c
static void initmain(void)
{
PyObject *m, *d;
// Get the __main__ module
m = PyImport_AddModule("__main__");
if (m == NULL)
Py_FatalError("can't create __main__ module");
// d = __main__.__dict__
d = PyModule_GetDict(m);
Setzen Sie `__main__.__dict__['__builtins__']`, überspringen Sie es, wenn es bereits vorhanden ist.
if (PyDict_GetItemString(d, "__builtins__") == NULL) {
PyObject *bimod = PyImport_ImportModule("__builtin__");
if (bimod == NULL ||
PyDict_SetItemString(d, "__builtins__", bimod) != 0)
Py_FatalError("can't add __builtins__ to __main__");
Py_XDECREF(bimod);
}
}
Im initmain
wird Python dem __main__
Modul das Attribut __builtins__
zuweisen, das standardmäßig dem __builtin__
Modul entspricht. Wenn es bereits vorhanden ist, wird es übersprungen und nicht neu gesetzt. Mit diesem Merkmal können wir durch Ändern von __main__.__builtins__
einige der eingebauten Funktionen ändern, um die Codeausführung einzuschränken. Die genaue Methode bleibt vorerst unerwähnt, lassen Sie uns betrachten, wie __builtins__
übertragen wird.
__builtins__
Übertragung
Beim Erstellen eines neuen Stapelrahmens:
PyFrameObject *
PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
PyObject *locals)
{
...
if (back == NULL || back->f_globals != globals) {
Verwenden Sie `globals['__builtins__']` als `__builtins__` für den neuen Stackframe.
// builtin_object is the string '__builtins__'
builtins = PyDict_GetItem(globals, builtin_object);
if (builtins) {
if (PyModule_Check(builtins)) {
builtins = PyModule_GetDict(builtins);
assert(!builtins || PyDict_Check(builtins));
}
else if (!PyDict_Check(builtins))
builtins = NULL;
}
...
}
else {
/* If we share the globals, we share the builtins.
Save a lookup and a call. */
Bitte übersetzen Sie den Text ins Deutsche:
// Oder direkt die f_builtins des übergeordneten Stapelrahmens erben.
builtins = back->f_builtins;
assert(builtins != NULL && PyDict_Check(builtins));
Py_INCREF(builtins);
}
...
f->f_builtins = builtins;
f->f_globals = globals;
}
Bei der Erstellung eines neuen Stapelrahmens gibt es hauptsächlich zwei Möglichkeiten für die Behandlung von __builtins__
: Entweder wird, wenn es keinen übergeordneten Stapelrahmen gibt, globals['__builtins__']
verwendet, oder es wird direkt f_builtins
des übergeordneten Stapelrahmens genommen. Zusammengefasst bedeutet dies, dass in der Regel die in __main__
festgelegten __builtins__
an die nachfolgenden Stapelrahmen weitergegeben werden und somit eine gemeinsame Instanz verwendet wird.
Beim import
von Modulen:
static PyObject *
load_compiled_module(char *name, char *cpathname, FILE *fp)
{
long magic;
PyCodeObject *co;
PyObject *m;
...
co = read_compiled_module(cpathname, fp);
...
m = PyImport_ExecCodeModuleEx(name, (PyObject *)co, cpathname);
...
}
PyObject *
PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname)
{
...
m = PyImport_AddModule(name);
...
// d = m.__dict__
d = PyModule_GetDict(m);
Setzen Sie hier das __builtins__ Attribut für die neuen geladenen Module.
if (PyDict_GetItemString(d, "__builtins__") == NULL) {
if (PyDict_SetItemString(d, "__builtins__",
PyEval_GetBuiltins()) != 0)
goto error;
}
...
// globals = d, locals = d
v = PyEval_EvalCode((PyCodeObject *)co, d, d);
...
}
PyObject *
PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)
{
return PyEval_EvalCodeEx(co,
globals, locals,
(PyObject **)NULL, 0,
(PyObject **)NULL, 0,
(PyObject **)NULL, 0,
NULL);
}
Beim Importieren anderer Module wird das __builtins__
-Objekt dieses Moduls auf das Ergebnis von PyEval_GetBuiltins()
gesetzt, was in den meisten Fällen dem current_frame->f_builtins
entspricht. Wenn es sich um ein Import im __main__
-Modul handelt, ist current_frame
der Stackframe des __main__
-Moduls und current_frame->f_builtins = __main__.__dict__['__builtins__']
(wie im vorherigen Abschnitt PyFrame_New
im ersten Fall erwähnt).
Das neue Modul wird mit PyEval_EvalCode
den Code im neuen Modul ausführen. Die an PyEval_EvalCode
übergebenen Parameter globals
und locals
sind tatsächlich das __dict__
des Moduls selbst, und das Modul m.__dict__['__builtins__'] = PyEval_GetBuiltins()
.
Im Allgemeinen können wir feststellen, dass Module, die ab dem __main__
-Modul importiert werden, auch die __builtins__
aus dem __main__
erben und sie intern bei weiteren import
-Anweisungen weitergeben. Dadurch wird sichergestellt, dass alle Module und Untermodule, die von __main__
geladen werden, dieselben __builtins__
aus dem __main__
teilen können.
Was ist, wenn die Funktion in einem Modul aufgerufen wird? Für Funktionen innerhalb von Modulen, beim Erstellen und Aufrufen:
// ceval.c
Erstellen Sie eine Funktion.
TARGET(MAKE_FUNCTION)
{
v = POP(); /* code object */
Hier entspricht f->f_globals den Globals des Moduls selbst, wie bereits erwähnt, entspricht dies auch m.__dict__.
x = PyFunction_New(v, f->f_globals);
...
}
PyObject *
PyFunction_New(PyObject *code, PyObject *globals)
{
PyFunctionObject *op = PyObject_GC_New(PyFunctionObject,
&PyFunction_Type);
...
Hier entspricht es sozusagen op->func_globals = globals = f->f_globals.
op->func_globals = globals;
}
Rufen Sie die Funktion auf.
static PyObject *
fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk)
{
PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
// globals = func->func_globals
PyObject *globals = PyFunction_GET_GLOBALS(func);
...
Die "globals"-Variable wird an PyEval_EvalCodeEx übergeben, wo sie dann an PyFrame_New weitergereicht wird, um einen neuen Frame zu erstellen.
return PyEval_EvalCodeEx(co, globals,
(PyObject *)NULL, (*pp_stack)-n, na,
(*pp_stack)-2*nk, nk, d, nd,
PyFunction_GET_CLOSURE(func));
}
Bei der Erstellung einer Funktion wird f->f_globals
in der Funktionenstrukturvariablen func_globals
gespeichert, während für das Modul m
f->f_globals = m.__dict__
gilt. Wenn die Funktion ausgeführt wird, sind die dem PyFrame_New
übergebenen globals
-Parameter die zuvor gespeicherten func_globals
, und __builtins__
kann natürlich aus func_globals
abgerufen werden.
Bis hierhin ist die Weitergabe von __builtins__
konsistent gewährleistet, sodass alle Module, Untermodule, Funktionen, Stapelrahmen usw. auf dasselbe verweisen können und somit über denselben integrierten Namensraum verfügen.
Specify the execution of the __main__
module.
Wir wissen bereits, dass das Modul __main__
seine eigenen __builtins__
an alle Untermodule, Funktionen und Stackframes weitergeben kann. Wenn wir in der Befehlszeile python a.py
ausführen, wird Python a.py
als __main__
Modul ausführen. Wie wird das gemacht?
// python.c
int
main(int argc, char **argv)
{
...
return Py_Main(argc, argv);
}
// main.c
int
Py_Main(int argc, char **argv)
{
...
Versuche, den Code mit dem Importer des Moduls auszuführen.
if (filename != NULL) {
sts = RunMainFromImporter(filename);
}
...
Normalerweise verwenden wir diese Methode zum Ausführen unserer eigenen Python-Dateien.
sts = PyRun_AnyFileExFlags(
fp,
filename == NULL ? "<stdin>" : filename,
filename != NULL, &cf) != 0;
}
...
}
// pythonrun.c
int
PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit,
PyCompilerFlags *flags)
{
...
return PyRun_SimpleFileExFlags(fp, filename, closeit, flags);
}
int
PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit,
PyCompilerFlags *flags)
{
...
m = PyImport_AddModule("__main__");
d = PyModule_GetDict(m);
...
Setzen Sie das __file__ Attribut.
if (PyDict_SetItemString(d, "__file__", f) < 0) {
...
}
...
// globals = locals = d = __main__.__dict__
v = run_pyc_file(fp, filename, d, d, flags);
...
}
static PyObject *
run_pyc_file(FILE *fp, const char *filename, PyObject *globals,
PyObject *locals, PyCompilerFlags *flags)
{
...
Lese den Code-Objekt co aus der pyc-Datei und führe den Code aus.
Innerhalb von PyEval_EvalCode wird auch PyFrame_New aufgerufen, um einen neuen Frame zu erstellen.
v = PyEval_EvalCode(co, globals, locals);
...
}
Wenn Sie python a.py
ausführen, gelangen Sie normalerweise zu PyRun_SimpleFileExFlags
, wo __main__.__dict__
extrahiert wird, um als globals
und locals
für die Ausführung des Codes zu dienen. Letztendlich wird dies an PyFrame_New
übergeben, um einen neuen Rahmen zu erstellen, der die a.py
ausführt. Durch die Weitergabe von __builtins__
in Modulen und Funktionen, wie zuvor erwähnt, können nachfolgende Codes dieselbe current_frame->f_builtins = __main__.__builtins__.__dict__
verwenden.
Diskussion über Restricted Execution
(https://docs.python.org/2.7/library/restricted.html)Es basiert auf den Eigenschaften von __builtins__
. Man könnte auch sagen, dass __builtins__
so gestaltet ist, dass es in einem Modulobjekt in __main__
und in anderen Modulen als dict
-Objekt erscheint, um die Restricted Execution zu ermöglichen.
Consider this scenario: If we could freely customize our __builtin__
module and set it as __main__.__builtins__
, then it would be equivalent to all subsequent executed code using our customized module. We could customize specific versions of open
, __import__
, file
, and other built-in functions and types. Moreover, could this approach help us restrict the execution permissions of the code, preventing it from making unsafe function calls or accessing insecure files?
Python
hat es damals versucht und das Modul, das diese Funktion implementiert hat, hieß rexec
.
rexec
Ich habe nicht die Absicht, hier tiefer auf die Implementierung von rexec
einzugehen, da das Konzept im Grunde bereits im vorherigen Abschnitt erläutert wurde. Außerdem ist dieses Modul selbst veraltet. Ich werde nur eine Zusammenfassung einiger Schlüsselcode-Bereiche anbieten, um es leicht nachschlagen zu können.
# rexec.py
class RExec(ihooks._Verbose):
...
nok_builtin_names = ('open', 'file', 'reload', '__import__')
def __init__(self, hooks = None, verbose = 0):
...
self.modules = {}
...
self.make_builtin()
self.make_initial_modules()
self.make_sys()
self.loader = RModuleLoader(self.hooks, verbose)
self.importer = RModuleImporter(self.loader, verbose)
def make_builtin(self):
m = self.copy_except(__builtin__, self.nok_builtin_names)
m.__import__ = self.r_import
m.reload = self.r_reload
m.open = m.file = self.r_open
def add_module(self, mname):
m = self.modules.get(mname)
if m is None:
self.modules[mname] = m = self.hooks.new_module(mname)
m.__builtins__ = self.modules['__builtin__']
return m
def r_exec(self, code):
m = self.add_module('__main__')
exec code in m.__dict__
def r_eval(self, code):
m = self.add_module('__main__')
return eval(code, m.__dict__)
def r_execfile(self, file):
m = self.add_module('__main__')
execfile(file, m.__dict__)
Die Funktion r_execfile
führt die Datei als Modul __main__
aus, jedoch ist __main__
angepasst. Innerhalb von self.add_module('__main__')
wird das Modul auf m.__builtins__ = self.modules['__builtin__']
gesetzt. Dieses __builtin__
wird durch make_builtin
angepasst generiert, um die __import__
, reload
und open
Funktionen zu ersetzen und den Dateityp file
zu entfernen. Auf diese Weise können wir kontrollieren, auf den integrierten Namensraum zuzugreifen, in dem der auszuführende Code definiert ist.
Für einige eingebaute Module hat rexec
auch Anpassungen vorgenommen, um unsicheren Zugriff zu schützen, zum Beispiel das sys
-Modul, bei dem nur einige Objekte behalten wurden. Durch die benutzerdefinierten self.loader
und self.importer
wird beim import
prioritär das angepasste Modul geladen.
Wenn Sie an den Details des Codes interessiert sind, schauen Sie sich bitte den entsprechenden Quellcode selbst an.
Das Scheitern von rexec
Der Text besagt, dass rexec
seit Python 2.3
nicht mehr unterstützt wird, da diese Methode als nicht praktikabel erwiesen wurde. Lassen Sie uns aus Neugierde kurz nachverfolgen:
In the community, someone reported a BugUnd führte zu Diskussionen unter Entwicklern:
> it's never going to be safe, and I doubt it's very useful as long as it's not safe.
> Every change is a potential security hole.
> it's hard to predict what change is going to break it.
> I don't expect you'll ever reach the point where it'll be wise to advertise this as safe. I certainly won't.
> this is only a useful occupation if you expect to eventually reach a point where you expect that there aren't any security flaws left. Jeremy & I both doubt that Python will ever reach that level, meaning that the whole exercise of fixing security flaws is a waste of time (if you know you *can't* make it safe, don't waste time trying).
> I agree (but I have said that in past) the best thing is to deprecate/rip out rexec.
> The code will still be in older versions if someone decides to pick it up and work on it as a separate project.
Der Grund für diesen Bug liegt darin, dass Python
die sogenannte neue Klasse object
eingeführt hat, was dazu führte, dass rexec
nicht ordnungsgemäß funktionieren konnte. Die Entwickler gaben an, dass es in absehbarer Zukunft sehr schwierig sein würde, diese Situation zu vermeiden, da jede beliebige Änderung dazu führen könnte, dass rexec
anfällig wird, nicht ordnungsgemäß funktioniert oder die Berechtigungsbeschränkungen umgangen werden, was im Grunde genommen die Vision einer sicheren Umgebung ohne Schwachstellen schwer umsetzbar macht. Die Entwickler müssen kontinuierlich Zeit damit verbringen, Fehler zu beheben. Letztendlich wurde das rexec
-Modul eingestellt und Python
hat keine vergleichbare Funktionalität mehr bereitgestellt. Allerdings wurde die Konfiguration von __builtins__
aus Gründen der Kompatibilität beibehalten.
In etwa um das Jahr 2010 herum brachte ein Programmierer pysandboxEngagiert sich für die Bereitstellung einer Python-Sandbox-Umgebung als Alternative zu rexec
. Doch drei Jahre später hat der Autor das Projekt freiwillig aufgegeben und ausführlich erläutert, warum er es für gescheitert hält: Das Pysandbox-Projekt ist fehlerhaftEs gibt auch andere Autoren, die das Scheitern dieses Projekts zusammengefasst haben: The failure of pysandboxWenn Sie interessiert sind, können Sie das Original genauer lesen. Hier sind einige Zusammenfassungen zur Unterstützung beim Verständnis.
After having work during 3 years on a pysandbox project to sandbox untrusted code, I now reached a point where I am convinced that pysandbox is broken by design. Different developers tried to convinced me before that pysandbox design is unsafe, but I had to experience it myself to be convineced.
I now agree that putting a sandbox in CPython is the wrong design. There are too many ways to escape the untrusted namespace using the various introspection features of the Python language. To guarantee the [safety] of a security product, the code should be [carefully] audited and the code to review must be as small as possible. Using pysandbox, the "code" is the whole Python core which is a really huge code base. For example, the Python and Objects directories of Python 3.4 contain more than 126,000 lines of C code.
The security of pysandbox is the security of its weakest part. A single bug is enough to escape the whole sandbox.
pysandbox cannot be used in practice. To protect the untrusted namespace, pysandbox installs a lot of different protections. Because of all these protections, it becomes hard to write Python code. Basic features like "del dict[key]" are denied. Passing an object to a sandbox is not possible to sandbox, pysandbox is unable to proxify arbitary objects. For something more complex than evaluating "1+(2*3)", pysandbox cannot be used in practice, because of all these protections.
Der Autor von pysandbox glaubt, dass es ein fehlerhaftes Design ist, in Python
eine Sandbox-Umgebung zu haben. Es gibt zu viele Möglichkeiten, um aus der Sandbox auszubrechen. Die Sprachfunktionen, die Python bietet, sind sehr umfassend und der Codeumfang von CPython ist so groß, dass es praktisch unmöglich ist, ausreichende Sicherheit zu gewährleisten. Der Entwicklungsprozess von pysandbox besteht darin, ständig Patches anzuwenden. Es gibt so viele Patches und Einschränkungen, dass der Autor der Meinung ist, dass pysandbox praktisch nicht mehr verwendbar ist, da viele Syntaxfunktionen und Features eingeschränkt sind und nicht mehr verwendet werden können, wie zum Beispiel einfaches del dict[key]
.
Restricted Execution 出路在哪
Eingeschränkte Ausführung, wo ist der Ausweg
Da die Methoden rexec
und pysandbox
, die durch Patching von Python eine Sandbox-Umgebung bereitstellen, nicht mehr funktionieren, frage ich mich unweigerlich: Wie kann man Python eine funktionierende Sandbox-Umgebung bieten?
Hier habe ich weitere Umsetzungsmethoden oder Beispiele gesammelt, die zur Referenz und Überprüfung dienen:
- PyPy(https://foss.heptapod.net/pypy/pypy/-/tree/branch/sandbox-2)Bietet eine Sandbox-Funktion in Verbindung mit zusätzlichen sandboxlibSie können PyPy selbst kompilieren, um eine Version mit Sandbox-Umgebung zu erstellen. Wenn Sie interessiert sind, können Sie versuchen, dies selbst zu konfigurieren. Hier finden Sie einige Hinweise: 说明Die Funktionsweise von PyPy besteht darin, einen Unterprozess zu erstellen, bei dem alle Ein- und Ausgaben sowie Systemaufrufe auf einen externen Prozess umgeleitet werden, der die Berechtigungen kontrolliert. Es ist auch möglich, den Speicher und die CPU-Nutzung zu kontrollieren. Es sollte beachtet werden, dass dieser Zweig seit geraumer Zeit keine neuen Commits mehr erhalten hat, daher ist Vorsicht geboten.
Nutzen Sie die Sandbox-Tools, die vom Betriebssystem bereitgestellt werden. seccompEs handelt sich um ein Sicherheitsberechnungstool, das vom Linux-Kernel zur Verfügung gestellt wird, libseccompEs wurden Python-Bindungen bereitgestellt, die in den Code eingebettet und verwendet werden können; oder Sie können Tools verwenden, die auf seccomp basieren, um den Code auszuführen, wie zum Beispiel FirejailAppArmorEs ist ein Sicherheitsmodul des Linux-Kernels, das es Administratoren ermöglicht, den Zugriff von Programmen auf Systemressourcen und -funktionen zu kontrollieren, um das Betriebssystem zu schützen. codejailEs handelt sich um eine Python-Sandbox-Umgebung, die auf AppArmor basiert. Bei Interesse können Sie es ausprobieren. Es gibt viele ähnliche Tools, die hier nicht alle aufgelistet werden.
Verwenden Sie eine Sandbox-Umgebung oder Container. Windows Sandbox,LXC, DockerWarten Sie mal, an dieser Stelle wird nicht weiter ausgeführt.
Zusammenfassung
Der Text ist etwas lang, danke, dass Sie bis hierher gelesen haben. Ich glaube, dass alle Fragen, die am Anfang des Artikels aufgeführt wurden, bereits beantwortet wurden.
Original: https://wiki.disenone.site/de
This post is protected by CC BY-NC-SA 4.0 agreement, should be reproduced with attribution.
Visitors. Total Visits. Page Visits.
(https://github.com/disenone/wiki_blog/issues/new)Bitte identifizieren Sie alle fehlenden Punkte.