85. 자바 직렬화의 대안을 찾으라

"승리하는 유일한 길은 전쟁하지 않는 것이다." 자바 직렬화는 그 전쟁이다. 사용하지 않는 것이 최선이다.


📌 핵심 요약

  • 🔥 자바 직렬화(Java Serialization) 는 보안, 성능, 유지보수 면에서 매우 위험하다.

  • 🚫 신규 시스템에서는 사용을 지양하고, JSON, Protocol Buffers 등 크로스-플랫폼 구조화된 데이터 표현을 대안을 채택하라.

  • 🔒 레거시 시스템에서 불가피하게 사용해야 한다면, → ObjectInputFilter를 활용한 역직렬화 필터링을 반드시 적용하라.

  • 😈 신뢰할 수 없는 데이터는 절대 역직렬화하지 말라


🧠 필수 개념

개념
설명

Serialization

객체 → 바이트 스트림으로 변환

Deserialization

바이트 스트림 → 객체로 복원

Serializable

직렬화 가능 클래스임을 표시하는 마커 인터페이스

readObject()

역직렬화 시 실행되는 위험한 메서드


⚠️ 자바 직렬화의 위험성

  • ObjectInputStream.readObject()는 클래스패스 내 거의 모든 타입의 객체를 생성할 수 있다.

  • 이 과정에서 가젯(Gadget) 이라 불리는 악의적인 메서드 실행이 가능하다.

  • 또한, 짧은 바이트 스트림만으로도 서비스 거부(DoS) 공격이 가능한 역직렬화 폭탄이 존재한다.

📎 예제: 역직렬화 폭탄

// 코드 85-1 역직렬화 폭탄 - 이 스트림의 역직렬화는 영원히 계속된다.
static byte[] bomb() {
    Set<Object> root = new HashSet<>();
    Set<Object> s1 = root;
    Set<Object> s2 = new HashSet<>();
    for (int i = 0; i < 100; i++) {
        Set<Object> t1 = new HashSet<>();
        Set<Object> t2 = new HashSet<>();
        t1.add("foo"); // t1을 t2와 다르게 만든다
        s1.add(t1); s1.add(t2);
        s2.add(t1); s2.add(t2);
        s1 = t1;
        s2 = t2;
    }
    return serialize(root); // 간결하게 하기 위해 이 메서드의 코드는 생략함
}

이 구조는 2ⁱ⁰⁰ 수준의 hashCode() 연산을 유도 → 역직렬화가 영원히 끝나지 않음


🔄 대안: 구조화된 데이터 표현

대안
특징

JSON

텍스트 기반, 가독성 높음, 거의 모든 언어에서 지원

Protocol Buffers

이진 기반, 성능 우수, 스키마 기반, 구글 개발

  • 둘 다 단순하고 안전한 구조의 데이터를 주고받음

  • 자동 객체 그래프 직렬화 X → 보안 취약점 제거

  • 크로스 플랫폼, 높은 호환성, 커뮤니티 활발


🛡 자바 직렬화가 필요한 경우

  1. 신뢰할 수 없는 데이터는 절대 역직렬화하지 마세요 ❌

  2. ObjectInputFilter를 활용한 필터링 적용 (Java 9+)

    ObjectInputFilter filter = ObjectInputFilter.Config.createFilter("com.example.*;!*");
    ObjectInputStream ois = new ObjectInputStream(inputStream);
    ois.setObjectInputFilter(filter);
  3. 화이트리스트 방식 추천 → 알려진 안전한 클래스만 허용

  4. SWAT(Serial Whitelist Application Trainer) 도구로 필터 자동 생성 가능


📚 자바 버전별 변화

  • 🏷️ Java 9부터 ObjectInputFilter 정식 지원

  • 🔄 이전 버전에서는 백포트 라이브러리 사용 가능

  • ✅ 필터링은 역직렬화 폭탄, 메모리 초과 등도 일부 방어 가능


✍️ 느낀 점

직렬화는 단순한 기술이 아니라 위험한 기능이란 걸 알게 되었습니다. JSON이나 protobuf 같은 대안 사용이 필수이며, 레거시 시스템에서도 최소한의 방어책은 적용해야 합니다.


📌 반드시 알아야 할 점

  1. ⚠️ 자바 직렬화는 보안상 매우 취약하므로 신중히 사용해야 합니다.

  2. ✅ 새로운 시스템은 JSON / Protocol Buffers로 설계하세요.

  3. 🔐 레거시 시스템에서는:

    • 신뢰할 수 없는 데이터는 역직렬화 금지

    • ObjectInputFilter 필수 적용

    • 화이트리스트 기반 필터링 권장

  4. 🔄 위험 징후 발견 시 패치 및 마이그레이션 계획 수립 필수

  5. 📖 직렬화 폭탄, 가젯 체인 공격 사례를 꼭 학습하고 대비하세요.


🧾 결론

  • 자바 직렬화는 사용하지 않는 것이 가장 안전한 선택입니다.

  • 구조화된 데이터 표현(JSON, protobuf 등)은 더 안전하고, 호환성도 뛰어나며, 관리도 쉬움.

  • 부득이한 경우에도 철저한 필터링과 검증이 필요합니다.

Last updated