[英]How to disable pickle.loads for security?
For security reasons I would like to disable pickle.loads
in a Python process. 出于安全原因,我想在Python进程中禁用
pickle.loads
。 I would like to continue being able to use pickle.dumps
however. 我希望继续能够使用
pickle.dumps
。
Is there a standard way to achieve this? 是否有实现此目的的标准方法?
To be clear I am not concerned about my user being malicious. 明确地说,我并不担心我的用户是恶意的。 However I am concerned that they may inadvertently use library code that triggers
pickle.loads
in unexpected ways. 但是,我担心它们可能会无意中使用以意外方式触发
pickle.loads
库代码。
我不知道一种标准方法,但是根据您的用例,想到的一个主意是覆盖该函数:
pickle.loads = '_disabled'
I think that patching like pickle.loads = disabled
where disabled
raises some exception is the easiest. 我认为,像
pickle.loads = disabled
这样的修补最容易实现,而disabled
会引发一些异常。 If you are really worried about the function being cached before you have a chance to clear it, you could patch the function pointer directly with something like: 如果您真的有机会清除函数之前真的担心它会被缓存,则可以使用以下方法直接修补函数指针:
#include <Python.h>
#include <methodobject.h>
/**
Patch the c implementation of a `builtin_function_or_method`.
@param ob The builtin_function_or_method object to patch.
@param new_meth The new C function pointer to use.
@param new_flags The new flags to set.
@param old_meth pointer to store the old function pointer in. If this
function fails, this value will be unchanged. If this value is `NULL`,
it will not be stored.
@param old_meth pointer to store the old function pointer in. If this
function fails, this value will be unchanged.
@param old_flags A pointer to store the old flags in. If this function fails,
this value will be unchanged. If this value is `NULL`, it will not be
stored.
@return zero if the method was patched succesfully, non-zero on failure. If
this function returns non-zero, an exception will be raised.
*/
static int patch_c_function(PyObject* ob,
PyCFunction new_meth,
int new_flags,
PyCFunction* old_meth,
int* old_flags) {
if (!PyCFunction_Check(ob)) {
PyErr_Format(PyExc_TypeError,
"expected builtin_function_or_method object, got: %s",
Py_TYPE(ob)->tp_name);
return -1;
}
PyCFunctionObject* function_object = (PyCFunctionObject*) ob;
if (old_meth) {
*old_meth = function_object->m_ml->ml_meth;
}
function_object->m_ml->ml_meth = new_meth;
if (old_flags) {
*old_flags = function_object->m_ml->ml_flags;
}
function_object->m_ml->ml_flags = new_flags;
return 0;
}
static PyObject* disabled(void) {
PyErr_SetString(PyExc_AssertionError,
"this function is disabled in this process");
return NULL;
}
static PyObject* disable_function(PyObject* self, PyObject* f) {
if (patch_c_function(f,
(PyCFunction) disabled,
METH_VARARGS | METH_KEYWORDS,
NULL,
NULL)) {
return NULL;
}
Py_RETURN_NONE;
}
PyMethodDef methods[] = {
{"disable_function", (PyCFunction) disable_function, METH_O, NULL},
{NULL},
};
PyModuleDef cext_module = {
PyModuleDef_HEAD_INIT,
"cext",
NULL,
-1,
methods,
NULL,
NULL,
NULL,
NULL
};
PyMODINIT_FUNC
PyInit_cext(void) {
return PyModule_Create(&cext_module);
}
This can then be used in a repl like: 然后可以在类似的repl中使用:
In [1]: import pickle
In [2]: loads = pickle.loads
In [3]: from cext import disable_function
In [4]: disable_function(pickle.loads)
In [5]: pickle.loads()
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-5-95a055f9ba4f> in <module>()
----> 1 pickle.loads()
AssertionError: this function is disabled in this process
In [6]: loads()
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-6-73007b0e1946> in <module>()
----> 1 loads()
AssertionError: this function is disabled in this process
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.