본문 바로가기
개념 노트장

[python] pickle 모듈 간단 사용법 및 취약점

by jwcs 2024. 2. 12.
728x90

https://docs.python.org/ko/3.9/library/pickle.html

 

pickle — 파이썬 객체 직렬화 — Python 3.9.18 문서

pickle — 파이썬 객체 직렬화 소스 코드: Lib/pickle.py pickle 모듈은 파이썬 객체 구조의 직렬화와 역 직렬화를 위한 바이너리 프로토콜을 구현합니다. “피클링(pickling)”은 파이썬 객체 계층 구조가

docs.python.org

 

pickle : pickle 모듈은 파이썬 객체를 바이트 스트림으로 직렬화, 역직렬화하는 기능을 제공한다.

 

직렬화, 역직렬화가 필요한 이유 : 복잡한 형태의 데이터(예: 객체)를 저장하는 것을 구현하기는 상당히 어렵다. 이것을 바이트 스트림 형태로 변환하면 수월하게 저장할 수 있다.

 

pickle 모듈 간단 사용법

  • pickle.dumps(): 파이썬 객체를 입력으로 받아 바이트 객체로 직렬화하여 반환한다. `pickle.dump`도 있는데, 차이점이 있다면 열린 파일에 저장한다. 
import pickle

# 직렬화할 파이썬 객체
data = {'key': 'value', 'number': 42}

# 객체를 바이트 스트림으로 직렬화
serialized_data = pickle.dumps(data)

print(serialized_data)  # 바이트 스트림 출력

 

  • pickle.loads(): `pickle.dumps()` 함수를 통해 생성된 바이트 스트림을 입력으로 받아 원래의 파이썬 객체로 역직렬화한다. 마찬가지로 `pickle.load`가 있는데, 파일을 입력받아 원래의 파이썬 객체로 역직렬화한다.
import pickle

# 바이트 스트림을 파이썬 객체로 역직렬화
deserialized_data = pickle.loads(serialized_data)

print(deserialized_data)  # 원래의 파이썬 객체 출력

 

  • __reduce__(): 직렬화에 사용될 클래스에 들어가는 메서드이다. 직렬화될 때, 객체를 어떻게 저장하고 어떻게 복원할지에 대한 정보를 제공한다. 반환 값에는 호출 가능한 객체와 인자가 포함될 수 있는데, 이 호출 가능한 객체가 함수나 실행 코드일 수 있다. 따라서 공격자가 악의적인 코드를 포함시키면, 역직렬화 과정에서 해당 코드가 실행될 수 있는 원격 코드 실행(RCE) 취약점이 존재한다.. `__reduece__()` 외에도 `__reduce_ex__`와 `__setstate__`도 있다.
import pickle

class Example:
    def __init__(self, value):
        self.value = value

    def __reduce__(self):
        # 객체를 복원하는 데 사용될 생성자와 인자를 반환
        return (self.__class__, (self.value,))

# Example 클래스의 인스턴스 생성
obj = Example(42)

# obj를 직렬화
serialized_obj = pickle.dumps(obj)

# 직렬화된 데이터를 다시 역직렬화하여 새 객체 생성
new_obj = pickle.loads(serialized_obj)

print(new_obj.value)  # 42

위는 기본적인 사용법 예시다.

 

import pickle,base64

class exploit():
  def __reduce__(self):
    return (eval,("open('./flag.txt', 'r').read()",))

위는 공격으로 사용한 예시다.

 

방어 전략

외부의 입력값을 unpickle하는 것을 삼가해야한다.

 

728x90
반응형