-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
[아이템 85] 자바 직렬화의 대안을 찾으라
자바 직렬화
- 자바 직렬화란 자바가 객체를 바이트 스트림으로 인코딩하고(직렬화) 그 바이트 스트림으로부터 다시 객체를 재구성하는(역직렬화) 메커니즘
- 직렬화된 객체는 다른 VM에 전송하거나 디스크에 저장한 후 나중에 역직렬화 할 수 있다
- 1997년에 자바에 처음으로 직렬화가 도입되었고, �지금까지 경험한 바로는 직렬화의 장점보다는 보이지 않는 생성자, API와 구현 사이의 모호해진 경계, 정확성 문제, 성능, 보안, 유지보수성 등 위험성이 더 크다
- 직렬화의 근본적인 문제는 공격 범위가 너무 넓고 지속적으로 더 넓어져 방어하기 어렵다는 점
- readObject 메서드는 클래스패스 안의 거의 모든 타입의 객체를 만들어낼 수 있는 마법 같은 생성자
- -> 바이트 스트림을 역직렬화하는 과정에서 이 메서드는 그 타입들 안의 모든 코드를 수행할 수 있다.
- --> 그 타입들의 코드 전체가 공격 범위에 들어간다!
- 신뢰할 수 없는 스트림을 역직렬화하면 원격 코드 실행, 서비스 거부 �등의 공격으로 이어질 수 있다.
- 잘못한 게 아무것도 없는 애플리케이션이라도 이런 공격에 취약해질 수 있다.
폭탄 예시
static byte[] bomb() {
Set<Object> rootSet = new HashSet<>();
Set<Object> set1 = rootSet;
Set<Object> set2 = new HashSet<>();
for (int i = 0; i < 100; i++) {
Set<Object> tempSet1 = new HashSet<>();
Set<Object> tempSet2 = new HashSet<>();
tempSet1.add("foo");
set1.add(tempSet1);
set1.add(tempSet2);
set2.add(tempSet1);
set2.add(tempSet2);
set1 = tempSet1;
set2 = tempSet2;
}
return serialize(rootSet); // 자세한 코드 생략
}- rootSet 에 다른 HashSet 2개가 담기고, 그 HashSet들도 다른 HashSet을 2개씩 가지고 있는 깊이 100단계까지 만들어진 예시
- 역직렬화하려면 2^100 번 hashCode 메서드를 호출해야한다.
결론
- 직렬화는 위험하니 피해야 한다. 직렬화 위험을 회피하는 가장 좋은 방법은 아무것도 역직렬화하지 않는 것이다.
- JSON, 프로토콜 버퍼 같은 대안을 사용하자.
- 신뢰할 수 없는 데이터는 역직렬화하지 말자.
- 현실적으로 꼭 해야 한다면 객체 역직렬화 필터링을 사용하자 ( 자바 9에서 지원해주는 기능)
- 객체 역직렬화 필터링도 모든 공격을 막아줄 수는 없음을 기억하고, 꼭 그렇게 만들어야 한다면 정말 신경써서 작성해야 한다.
- 현실적으로 꼭 해야 한다면 객체 역직렬화 필터링을 사용하자 ( 자바 9에서 지원해주는 기능)
Metadata
Metadata
Assignees
Labels
No labels