[Zope] cookie problem

Toby Dickenson tdickenson@geminidataloggers.com
Tue, 01 Feb 2000 16:55:52 +0000


On Tue, 01 Feb 2000 10:00:12 +1100, Terry Kerr
<terry@adroitnet.com.au> wrote:

> I am having problems trying to set a cookie when the cookie is a pickled
> object.

I'm sure you know this, but you need to take care to avoid opening a
security hole. The default unpickler can create an instance of _any_
class, including potentially dangerous ones.

Pickling isn't inherently unsafe, you just need to be careful when
unpickling. I've included an unpickler below that will only create
simple types which are all safe (as far as I can tell... no
warranty.... use at your own risk... etc...)

Hope this helps,

Toby Dickenson


import pickle
from cStringIO import StringIO

__version__ = "1.0"

if pickle.format_version!="1.3":
    # Maybe the format changed, and opened a security hole
    raise 'Invalid pickle version'


class MiniUnpickler(pickle.Unpickler):
    """An unpickler that can only handle simple types.
    """
    def refuse_to_unpickle(self):
        raise pickle.UnpicklingError, 'Refused'

    dispatch = pickle.Unpickler.dispatch.copy()

    dispatch[pickle.GLOBAL] = refuse_to_unpickle
    dispatch[pickle.OBJ]    = refuse_to_unpickle
    dispatch[pickle.INST]   = refuse_to_unpickle
    dispatch[pickle.REDUCE] = refuse_to_unpickle
    dispatch[pickle.BUILD]  = refuse_to_unpickle


def _should_succeed(x):
    if x != MiniUnpickler(StringIO(pickle.dumps(x,1))).load():
        raise ValueError(x)

def _should_fail(x):
    try:
        MiniUnpickler(StringIO(pickle.dumps(x,1))).load()
        raise ValueError(x)
    except pickle.UnpicklingError, e:
        if e!='Refused': raise ValueError(x)

class _junk_class: pass

def _test():
    _should_succeed('hello')
    _should_succeed(1)
    _should_succeed(1L)
    _should_succeed(1.0)
    _should_succeed((1,2,3))
    _should_succeed([1,2,3])
    _should_succeed({1:2,3:4})
    _should_fail(open)
    _should_fail(_junk_class)
    _should_fail(_junk_class())


if __name__=='__main__':
    _test()
    print "OK"

Toby Dickenson
tdickenson@geminidataloggers.com