|
| 1 | +# [아이템 88] readObject 메서드는 방어적으로 작성하라 |
| 2 | + |
| 3 | +## 직렬화된 코드는 언제든 역직렬화가 가능하다. |
| 4 | + |
| 5 | +- 부제목의 컨셉을 이용해서 역직렬화를 통한 참조가 가능하다 . 아래는 해당 메커니즘을 이용한 공격 방식이다. |
| 6 | + |
| 7 | +```java |
| 8 | +class Period { |
| 9 | + Date startDate; |
| 10 | + Date endDate; |
| 11 | + |
| 12 | +} |
| 13 | +``` |
| 14 | + |
| 15 | +```java |
| 16 | +import java.io.ByteArrayInputStream; |
| 17 | +import java.io.ByteArrayOutputStream; |
| 18 | +import java.io.ObjectInputStream; |
| 19 | +import java.io.ObjectOutputStream; |
| 20 | +import java.util.Date; |
| 21 | + |
| 22 | +public class AttackPeriod { |
| 23 | + |
| 24 | + Period period; |
| 25 | + Date startDate; |
| 26 | + Date endDate; |
| 27 | + |
| 28 | + public void serialize() { |
| 29 | + ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| 30 | + ObjectOutputStream os = new ObjectOutputStream(); |
| 31 | + |
| 32 | + os.write(new Period(new Date(), new Date())); |
| 33 | + |
| 34 | + //ByteCode 를 통한 참조 진행.... |
| 35 | + |
| 36 | + // 참조 설정 후 |
| 37 | + ObjectInputStream ois = new ObjectInputStream(); |
| 38 | + period = (Period) ois.readObject(); |
| 39 | + startDate = (Date) ois.readObject(); |
| 40 | + endDate = (Date) ois.readObject(); |
| 41 | + } |
| 42 | +} |
| 43 | +``` |
| 44 | + |
| 45 | +```java |
| 46 | +public static void main(String[]args){ |
| 47 | + AttackPerioid at = new AttackPeriod(); |
| 48 | + Period p = at.period; |
| 49 | + Date pEnd = at.endDate; |
| 50 | + |
| 51 | + pEnd.setYear(91); |
| 52 | + System.out.println(pEnd); |
| 53 | + } |
| 54 | +``` |
| 55 | + |
| 56 | +위와 같이하면 91년도로 년도가 바뀌게 된다. 위와 같이 역직렬화 간의 참조를 통한 공격이 가능하므로, |
| 57 | +참조가 일어날 수 있는 부분은 방어적 가변복사를 시행해야 한다. |
| 58 | + |
| 59 | +```java |
| 60 | +private void readObject(ObjectInputStream s) { |
| 61 | + s.defaultReadObject(); |
| 62 | + |
| 63 | + start = new Date(start.getTime()); |
| 64 | + end = new Date(end.getTime()); |
| 65 | + } |
| 66 | +``` |
0 commit comments