Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
Tags
- Props
- Websocket
- 문서번호
- 서버리스 #
- 컴포넌튼
- literal
- npm
- github
- 당근마켓
- 0.5px border
- font-size
- 0.75px border
- 0.25px border
- jwt
- 전역변수
- 10px
- angular
- 클론코딩
- entity
- 타입스크립트
- ZOOM
- 1px border
- Strict
- TS
- TypeScript
- 데이터베이스 #try #이중
- es6
- 으
- ES5
- &연산
Archives
- Today
- Total
복잡한뇌구조마냥
[JAVA] Effective Java - readObject 메서드는 방어적으로 작성하라 (88) 본문
요약약
- readObject는 사실상 숨은 생성자다.
- 따라서 공격자가 임의로 만든 바이트 스트림을 넣을 수 있다는 전제로 방어적으로 작성해야 한다.
- 원칙:
- 방어적 복사를 가장 먼저 수행
- 불변식 검사 후 위배되면 InvalidObjectException 던지기
- 필요 시 ObjectInputValidation으로 객체 그래프 전체 유효성 검사
- 재정의 가능한 메서드 호출 금지 (생성자와 동일한 원칙)
- 더 안전한 방법: 직렬화 프록시 패턴을 활용하라.
1. 왜 readObject가 위험한가?
- 직렬화/역직렬화는 바이트 스트림으로 객체를 주고받는 메커니즘.
- 하지만 공격자는 이 스트림을 임의로 조작해,
- 불변식이 깨진 객체
- 내부 상태가 노출되거나 수정 가능한 객체
를 만들 수 있다.
- 즉, readObject는 단순히 “저장된 객체 복원”이 아니라 보안 구멍이 될 수 있다.
2. 방어적으로 작성하는 방법
① 방어적 복사
- 역직렬화 과정에서 가변 객체 참조를 그대로 저장하면 위험.
- 반드시 방어적 복사를 수행해야 한다.
private Date start;
private Date end;
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {
in.defaultReadObject();
// 방어적 복사 (원본 참조를 그대로 두지 않는다)
start = new Date(start.getTime());
end = new Date(end.getTime());
if (start.after(end)) {
throw new InvalidObjectException("시작 시간이 종료 시간보다 늦습니다.");
}
}
✅ 방어적 복사는 유효성 검사보다 먼저 수행해야 한다.
(안 그러면 공격자가 참조를 바꿔치기해 검사 후 다시 값을 조작할 수 있음)
② 불변식 검사
- 모든 불변식을 확인하고, 깨져 있다면 InvalidObjectException 던지기.
- 생성자에서 하는 불변식 검증과 동일하게 생각해야 한다.
③ 객체 그래프 전체 검사
- 복잡한 객체 그래프라면 개별 클래스 단위 검사만으로 부족할 수 있다.
- 이 경우 ObjectInputValidation 인터페이스를 활용해 역직렬화가 끝난 후 전체 유효성 검사를 수행할 수 있다.
④ 재정의 가능한 메서드 호출 금지
- 생성자와 마찬가지로 readObject 내부에서도 재정의 가능한 메서드 호출 금지.
- 역직렬화 과정에서 하위 클래스 상태가 완전히 복원되기 전, 오버라이드된 메서드가 실행되어 예기치 않은 동작을 일으킬 수 있다.
3. 직렬화 프록시 패턴 (Serialization Proxy Pattern)
- 가장 안전한 방법: 직렬화 프록시 패턴 사용.
- 프록시 객체를 통해 직렬화/역직렬화 과정을 제어하면,
- 불변식 위반 방지
- 보안성 강화
- readObject의 방어 코드 작성 부담 감소
- 단점: 약간의 성능 비용이 있지만, 안전성과 유지보수성 측면에서 권장된다.
4. 지켜야 할 규칙 요약
- 방어적 복사: private 참조 필드는 역직렬화 시 반드시 복사
- 불변식 검사: 깨져 있으면 InvalidObjectException
- 객체 그래프 검사: 필요하면 ObjectInputValidation 활용
- 재정의 가능한 메서드 호출 금지
- 직렬화 프록시 패턴 고려
✅ 결론
readObject는 단순한 역직렬화 메서드가 아니라 숨은 생성자다.
따라서 생성자처럼 방어적으로 작성해야 하며, 절대 바이트 스트림을 신뢰해서는 안 된다.
방어적 복사 → 불변식 검사 → 필요 시 전체 유효성 검사 순서로 작성하고,
안전성을 더 높이려면 직렬화 프록시 패턴을 활용하라.
LIST
'BE > JAVA' 카테고리의 다른 글
[JAVA] Effective Java - 프로그램의 동작을 스레드 스케줄러에 기대지 말라 (84) (0) | 2025.09.07 |
---|---|
[JAVA] Effective Java - 표준 예외를 사용하라 (72) (0) | 2025.09.04 |
[JAVA] Effective Java - 일반적으로 통용되는 명명 규칙을 따르라 (68) (2) | 2025.09.01 |
[JAVA] Effective Java - 지역변수의 범위를 최소화하라 (57) (1) | 2025.08.31 |
[JAVA] Effective Java - 다중정의는 신중히 사용하라 (52) (0) | 2025.08.24 |