파이썬 직렬화와 역직렬화 안전하게 사용하기

파이썬에서의 직렬화와 역직렬화

파이썬 객체를 일련의 바이트들로 변환하는 것을 직렬화(Serialization)라 하고, 다시 바이트들을 파이썬 객체로 메모리 상에 복원하는 것을 역직렬화(Deserialization)라고 합니다.


파이썬에서 직렬화(Serialization)와 역직렬화(Deserialization)를 사용하기 위해서는 pickle 모듈을 주로 사용합니다.

pickle.dumps() #pickling (serialize)
pickle.loads() #unpickling (deserialize)


어떤 위험이 있을까요?

pickle 모듈을 사용해서 역직렬화 할 때는 주의해야 할 점이 있습니다. 바로 pickle 모듈 문서에 다음과 같이 나와 있는데요.

파이썬 객체 직렬화

pickle 모듈은 안전하지 않습니다. 신뢰할 수 있는 데이터만 언 피클 하십시오.

무슨 뜻일까요?


다음 예제를 한번 살펴보겠습니다. 다음 예제는 “id” 명령을 os.system 함수로 실행하는 함수를 직렬화해서, “test_id.data” 파일에 저장하는 예제입니다.

import pickle
import os

class TestPickle(object):
  def __reduce__(self):
    return (os.system, ('id', ))

pickle_data = pickle.dumps(TestPickle())

with open("test_id.data", "wb") as file:
  file.write(pickle_data)


예제 실행 후, 생성된 “test_id.data” 파일을 살펴보면, 직렬화에 성공한 모습입니다.

cat test_id.data
���posix��system����id���R�.


그럼 이 파일을 역직렬화 시도해보겠습니다. 파이썬 코드로 아래와 같이 명령줄에 입력합니다.

python -c 'import pickle;pickle.loads(open("test_id.data","rb").read())'


결과는 어떨까요? 다음과 같습니다.

uid=1000(user) gid=1000(user) groups=1000(user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),100(users)


os.system 함수를 통해 “id”라는 명령이 실행된 결과 값이 나오는 것을 확인할 수 있습니다. 이것은 무엇을 의미할까요?


직렬화된 데이터를 입력 받아, 서버에서 역직렬화를 수행한다면 사용자는 서버에 특정 명령을 실행할 수도 있다는 얘기가 됩니다.


그럼 어떻게 안전하게 사용할까요?

JSON 모듈을 사용해서 직렬화와 역직렬화를 수행한다면, 위와 같은 위험성은 피할 수 있습니다.

import json
data = {"key":"value"}
json_data = json.dumps(data) #serialize
d_data = json.loads(json_data) #deserialize


실제 사례

MkDocs에서 안전하지 않은 역직렬화 취약점이 발견되었습니다. 해당 위험성을 이해하는데 도움이 될 수 있으니 이 문서를 참고하세요.


참고

Scroll to Top