1. Serialization & Deserialization
ํ์ด์ฌ์ pickle ๋ชจ๋์ ๊ฐ์ฒด ๊ตฌ์กฐ์ ์ง๋ ฌํ(serialization)์ ์ญ์ง๋ ฌํ(deserialization)๋ฅผ ์ํ ๋ฐ์ด๋๋ฆฌ ํ๋กํ ์ฝ์ ๊ตฌํํ๊ธฐ ์ํด ์ฌ์ฉํ๋ค. ์ฝ๊ฒ ๋งํด, pickle ๋ชจ๋์ ํ์ด์ฌ ๊ฐ์ฒด๋ฅผ ์ ์ฅํ๊ฑฐ๋ ์ ์กํ๊ธฐ ์ํด ๋ณํํ๊ณ , ๋ค์ ๊ทธ ๊ฐ์ฒด๋ก ๋ณต์ํ๋ ๋ฐ ์ฌ์ฉ๋๋ ๋๊ตฌ์ด๋ค.
- serialization : ํ์ด์ฌ ๊ฐ์ฒด ๊ณ์ธต ๊ตฌ์กฐ -> ๋ฐ์ดํธ ์คํธ๋ฆผ = pickling
- deserialize : ๋ฐ์ดํธ ์คํธ๋ฆผ -> ํ์ด์ฌ ๊ฐ์ฒด ๊ณ์ธต ๊ตฌ์กฐ = unpickling
์ฆ, ์ง๋ ฌํ๋ฅผ ํ๋ ์ด์ ๋ ๋ฐ์ดํฐ๋ฅผ ํ์ผ/DB์ ์ ์ฅํ๊ฑฐ๋ ๋๋ ์ธ์ ์ ๊ฑธ์ณ ํ๋ก๊ทธ๋จ์ ์ํ๋ฅผ ์ ์งํ๊ฑฐ๋, ๋คํธ์ํฌ๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด์์ด๋ค.
2. Pickle ๋ชจ๋
pickle ๋ชจ๋์ ์ธํฐํ์ด์ค
- pickle.dump(obj, file)
- ๊ฐ์ฒด obj๋ฅผ ํผํด๋ง(pickling)ํ์ฌ ์ด๋ฆฐ ํ์ผ ๊ฐ์ฒด file์ ์ด๋ค.
- ์ฆ, ๊ฐ์ฒด๋ฅผ ํ์ผ๋ก ์ ์ฅํ๋ค.
- pickle.dumps(obj)
- ๊ฐ์ฒด obj๋ฅผ ํผํด๋งํ์ฌ ํ์ผ์ ์ฐ๋ ๋์ ๋ฐ์ดํธ ๊ฐ์ฒด(bytes)๋ก ๋ฐํํ๋ค.
- ์ฆ, ๊ฐ์ฒด๋ฅผ ๋ฉ๋ชจ๋ฆฌ ๋ด์์ ๋ฐ์ด๋๋ฆฌ ๋ฐ์ดํฐ๋ก ๋ณํํ๋ค.
- pickle.load(file)
- ์ด๋ฆฐ ํ์ผ ๊ฐ์ฒด file์์ ํผํด๋ง๋ ํํ์ ์ฝ๊ณ , ๊ทธ ์์ ์ง์ ๋ ๊ฐ์ฒด ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ์ฌ๊ตฌ์ฑํ์ฌ ๋ฐํํ๋ค.
- ์ฆ, ํ์ผ์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด ์๋ ๊ฐ์ฒด๋ก ๋ณต์ํ๋ค.
- pickle.loads(data)
- ํผํด๋ ๋ฐ์ดํฐ(data)๋ฅผ ์ฝ์ด ์๋ ๊ฐ์ฒด ๊ณ์ธต ๊ตฌ์กฐ๋ก ๋ณต์ํ๋ค
- ์ฆ, ๋ฉ๋ชจ๋ฆฌ ๋ด์์ ๋ฐ์ด๋๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด ์๋ ๊ฐ์ฒด๋ก ๋ณต์ํ๋ค.
ํผํด๋ง ๋ ๊ฒฐ๊ณผ๋ pickletools๋ก ๋์ค์ด์ ๋ธํ์ฌ ๊ตฌ์กฐ๋ฅผ ์ฝ๊ฒ ํ์ ํด๋ณผ ์ ์๋ค.
- 0: \x80 PROTO 4 -> ํ๋กํ ์ฝ ๋ฒ์ 4(ํ์ด์ฌ ๋ฒ์ )๋ฅผ ์ฌ์ฉํ์ฌ ์ง๋ ฌํ๋์์์ ๋ํ๋
- \x80๋ PROTO opcode์ด๊ณ , 4๋ ํ๋กํ ์ฝ ๋ฒ์
- 2: FRAME 8 -> ๋ค์์ ์ค๋ 8๋ฐ์ดํธ๊ฐ ํ๋์ ํ๋ ์์ ํ์ฑํจ
- ์ด๋ ๋ฐ์ดํฐ ์คํธ๋ฆผ์ ๋๋จธ์ง ๋ถ๋ถ์ ํฌํจํ๋ ํ๋ ์์ ์์์ ํ์ํ๋ค.
- 11: \x8c SHORT_BINUNICODE ‘mnzy’ -> ์งง์ ์ ๋์ฝ๋ ๋ฌธ์์ด์ ๋ํ๋.
- \x8c๋ SHORT_BINUNICODE opcode์ด๊ณ , 'mnzy'๋ ์ง๋ ฌํ๋ ์ ๋์ฝ๋ ๋ฌธ์์ด์ด๋ค.
- ์ด opcode๋ 255๋ฐ์ดํธ ์ดํ์ ์ ๋์ฝ๋ ๋ฌธ์์ด์ ํจ์จ์ ์ผ๋ก ์ง๋ ฌํํ๋ ๋ฐ ์ฌ์ฉ๋๋ค.
- 17: \x94 MEMOIZE (as 0) -> ์ง๋ ฌํ๋ ๊ฐ์ฒด๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ํน์ ์์น(0๋ฒ ์ธ๋ฑ์ค)์ ์ ์ฅํ๋ค.
- ์ด๋ ์ดํ์ ํด๋น ๊ฐ์ฒด๋ฅผ ๋ค์ ์ฌ์ฉํ ๋ ๋ฉ๋ชจ๋ฆฌ์์ ๊ฐ์ ธ์ค๊ธฐ ์ํด ์ฌ์ฉ๋๋ค.
- 18: . STOP -> ์ง๋ ฌํ ๋ฐ์ดํฐ์ ๋์ ๋ํ๋ธ๋ค.
- ์ด๋ ์ง๋ ฌํ๋ ๋ฐ์ดํฐ ์คํธ๋ฆผ์ ๋์ ํ์ํ๋ค.
3. Deserialize ์ทจ์ฝ์
pickle ๋ชจ๋์ ๋ค์ํ ๋ฉ์๋๋ฅผ ์ง์ํ๋๋ฐ, ์ด ์ค object.__reduce__() ๋ฉ์๋์์ ์ทจ์ฝ์ ์ด ๋ฐ์ํ ์ ์๋ค.
__reduce__() ๋ฉ์๋
- __reduce__() ๋ฉ์๋๋ ํ์ด์ฌ ๊ฐ์ฒด ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ์ญ์ง๋ ฌํ(unpickling)ํ ๋ ๊ฐ์ฒด๋ฅผ ์ฌ๊ตฌ์ฑํ๋ ๋ฐ ์ฌ์ฉ๋๋ ํํ์ ๋ฐํํ๋ ๋ฉ์๋์ด๋ค.์ด๋ ๊ฐ์ฒด๋ฅผ ์ด๋ป๊ฒ ์ฌ๊ตฌ์ฑํ ์ง์ ๋ํ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ค.
pickling๋ ๋ฐ์ดํธ ์คํธ๋ฆผ์ unpickleํ ๋, pickle ๋ชจ๋์ ๋จผ์ original object์ ์ธ์คํด์ค๋ฅผ ๋ง๋ค๊ณ ๋์ ๊ทธ ์ธ์คํด์ค๋ฅผ ์ฌ๋ฐ๋ฅธ ๋ฐ์ดํฐ๋ก ์ฑ์ด๋ค.
์ด๋ฅผ ์ํด์ ๋ฐ์ดํธ ์คํธ๋ฆผ์๋ original object ์ธ์คํด์ค์ ํน์ ๋ ๋ฐ์ดํฐ๋ง์ ํฌํจํ๋ค.
์ด๋, unpickle์ ์ฑ๊ณต์ ์ผ๋ก ํ๊ธฐ ์ํด์๋ ๊ฐ์ฒด๋ฅผ ์ด๋ป๊ฒ ์ฌ๊ตฌ์ฑํ ์ง๋ฅผ ์ ์ํ๋ ๋ช ๋ น ํผ์ฐ์ฐ์(operations)์ ๋ช ๋ น์ด๋ค์ด ํฌํจ๋์ด ์์ด์ผ ํ๋๋ฐ, ์ด ๋ช ๋ น ํผ์ฐ์ฐ์์ ๋ช ๋ น์ด๋ค์ __reduce__() ๋ฉ์๋์์ ๋ฐํ๋๋ ์ ๋ณด๋ค์ด๋ค.
__ruduce__() ๋ฉ์๋์ ๋ฆฌํด๊ฐ์ ๋ณดํต 2๊ฐ์ ์ธ์๋ฅผ ๊ฐ์ง๊ณ ์๋ค. (unpickleํ ๋ ์ฌ์ฉํ ์ ๋ณด)
- ํธ์ถ ๊ฐ๋ฅํ ๊ฐ์ฒด
- ํธ์ถ ๊ฐ๋ฅํ ๊ฐ์ฒด์ ๋ํ ์ธ์. ํธ์ถ ๊ฐ๋ฅํ ๊ฐ์ฒด๊ฐ ์ธ์๋ฅผ ๋ฐ์๋ค์ด์ง ์์ผ๋ฉด ๋น ํํ์ ์ ๊ณตํด์ผ ํ๋ค.
์ด๋, __ruduce__() ๋ฉ์๋์์ ํธ์ถ ๊ฐ๋ฅํ ๊ฐ์ฒด์ eval ๋๋ os์ ๊ฐ์ด ๋ช ๋ น์ด๋ฅผ ์คํํ ์ ์๋๋ก ํด๋์ค๋ฅผ ์์๋ก ์ง์ ํ ์ ์๋ค๋ฉด,
์ด๋ก ์ธํด RCE์ ๊ฐ์ ๋ณด์ ์ทจ์ฝ์ ์ด ๋ฐ์ํ ์ ์๋ค.
์์
(1) ExploitClass ํด๋์ค์ __reduce__() ๋ฉ์๋๋ฅผ ํตํด os.system ํจ์๋ฅผ ํธ์ถํ๊ณ , ์ธ์๋ก echo "This is a RCE vulnerability!" ๋ช ๋ น์ ์ ๋ฌํ๋ค. __reduce__()๋ ๊ฐ์ฒด๋ฅผ ์ง๋ ฌํํ ๋ ํธ์ถ๋๋ค.
(2) ExploitClass ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ , ์ด๋ฅผ pickle.dumps() ํจ์๋ฅผ ์ฌ์ฉํด ์ง๋ ฌํํ๋ค. ์ง๋ ฌํ๋ ๋ฐ์ดํธ ์คํธ๋ฆผ์ด serialized_exploit_obj์ ์ ์ฅ๋๋ค.
(3) pickle.loads() ํจ์๋ฅผ ์ฌ์ฉํด ์ง๋ ฌํ๋ ๊ฐ์ฒด๋ฅผ ์ญ์ง๋ ฌํํ๋ค. ์ด ๊ณผ์ ์์ __reduce__() ๋ฉ์๋๊ฐ ํธ์ถ๋๊ณ , os.system('echo "This is an RCE vulnerability!"')์ด ์คํ๋๋ค.
5. ๊ฒฐ๊ณผ์ ์ผ๋ก, "This is a RCE vulnerability!" ๋ฉ์์ง๊ฐ ์ถ๋ ฅ๋๋ค.
import pickle
import pickletools
import os
class ExploitClass:
def __reduce__(self):
# os.system์ ์ฌ์ฉํ์ฌ ์์์ ๋ช
๋ น์ ์คํํฉ๋๋ค.
return (os.system, ('echo "This is a RCE vulnerability!"',))
# ๊ฐ์ฒด ์์ฑ ๋ฐ ์ง๋ ฌํ
exploit_obj = ExploitClass()
serialized_exploit_obj = pickle.dumps(exploit_obj)
print("Serialized exploit object:", serialized_exploit_obj)
pickletools.dis(serialized_exploit_obj)
# ๊ฐ์ฒด ์ญ์ง๋ ฌํ (์
์์ ์ธ ๋ช
๋ น ์คํ)
pickle.loads(serialized_exploit_obj)
์ฆ, pickle์ด ๊ฐ์ฒด๋ฅผ ์ฌ๊ตฌ์ฑํ ๋, __reduce__() ๋ฉ์๋์์ ๋ฐํ๋ ์ฒซ ๋ฒ์งธ ์์(os.system)๋ฅผ ํธ์ถํ๊ณ , ๋ ๋ฒ์งธ ์์ ('echo "This is an RCE vulnerability!"',) ๋ฅผ ๊ทธ ์ธ์๋ก ์ ๋ฌํ๋ ๊ฒ์ด๋ค. ๊ทธ ๊ฒฐ๊ณผ ์์์ ๋ช ๋ น์ด๊ฐ ์คํ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
[์ฐธ๊ณ ]
https://rootable.tistory.com/entry/python-deserialize-vulnerability-in-pickle-modulehttps://docs.python.org/ko/3/library/pickle.html