简体   繁体   English

如何禁用pickle.loads以确保安全?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM