[시큐어코딩 가이드] 2-5-3. 신뢰할 수 없는 데이터의 역직렬화

신뢰할 수 없는 데이터의 역직렬화

정의

송신자가 네트워크를 이용해 직렬화된 정보를 수신자에게 전달하는 과정에서 공격자가 전송한 데이터 또는 저장된 스트림을 조작할 수 있는 경우, 신뢰할 수 없는 역직렬화로 인해 무결성 침해, 원격코드실행, 서비스 거부 공격 등이 발생할 수 있는 보안약점입니다.

 

*직렬화(Serialization)는 프로그램에서 특정 클래스의 현재 인스턴스 상태를 다른 서버로 전달하기 위해 클래스의 인스턴스 정보를 바이트 스트림으로 복사하는 작업으로, 메모리 상에서 실행되고 있는 객체의 상태를 그대로 복제해 파일로 저장하거나 수신 측에 전달하게 됩니다.

*역직렬화(Deserialization)는 반대 연산으로 바이너리 파일(Binary File) 이나 바이트 스트림(Byte Stream) 으로부터 객체 구조로 복원하는 과정입니다.

 

안전한 코딩기법

  • 모든 변수를 사용 전에 반드시 올바른 초기 값을 할당해야합니다.
  • 신뢰할 수 없는 데이터를 역직렬화 하지 않도록 응용 프로그램을 구성합니다.
  • 민감정보 또는 중요정보 전송시 암호화 통신을 적용할 수 없는 경우, 최소한 송신 측에서 서명을 추가하고 수신 측에서 서명을 확인하여 데이터 무결성을 검증해야합니다.

 

코드예제

다음은 안전하지 않은 코드예제로, 신뢰할 수 없는 사용자로부터 입력받은 코드를 역직렬화 하고 있는 코드입니다.

#신뢰할 수 없는 데이터의 역직렬화(안전X)
def dump_user_object(request):
    user = User.objects.first()
    #user.username
    with open('userinfo.dat', 'wb') as f:
        pickle.dump(user, f)
    return HttpResponse(f"User 데이터 직열화")

def load_user_object(request):
    #return HttpResponse()
    user = None
    with open('userinfo.dat', 'rb') as f:
        user = pickle.load(f)
    return HttpResponse(f"{user.name}")

 

secure/dump_user_object 실행

 

userinfo.dat 생성됨

 

secure/load_user_object 실행

 

다음은 안전한 코드예제로, 사용자로부터 전달받은 데이터를 HMAC를 이용하여 안전한 사용자로부터 온 것인지 검증한 후 역직렬화를 하는 코드입니다.

#신뢰할 수 없는 데이터의 역직렬화(안전O)
def get_user_object(request, id):
    hash_pickle = request.GET.get('hash_pickle', '')
    #print(hash_pickle)
    user = get_object_or_404(User, pk=id)
    # 그것을 직열화해서 저장, 역직열화
    pikcled_userinfo = pickle.dumps(user)

    m = hmac.new(key='secret_key'.encode('utf-8'), digestmod=hashlib.md5)
    m.update(pikcled_userinfo)
    print(str(m.digest())) # b'$\xd4\xb7\r!hE\xec\xb1\xff\xeaAT\x9c=\xf9'

    if hmac.compare_digest(str(m.digest()), hash_pickle):
        user_obj = pickle.loads(pikcled_userinfo)
        return render(request, 'success.html', {'msg': user_obj})
    else:
        return render(request, 'error.html', {'msg': '신뢰할 수 없는 데이터입니다.'})

 

secure/get_user_object/1?hash_pickle=b%27$\xd4\xb7\r!hE\xec\xb1\xff\xeaAT\x9c=\xf9%27

 

secure/get_user_object/1?hash_pickle=b%27$\xd4\xb7%27

 

 

 

코드오류/신뢰할 수 없는 데이터의 역직렬화

[참고문헌] Python 시큐어코딩 가이드(2022) / KISA(한국인터넷진흥원)