1. 역직렬화 취약점의 위험성
직렬화(Serialization)는 객체 상태를 바이트 스트림으로 변환하는 과정이며, 역직렬화(Deserialization)는 이를 다시 객체로 복원하는 과정입니다. CWE-502는 외부에서 전달된 신뢰할 수 없는 바이트 스트림을 검증 없이 역직렬화할 때 발생합니다. 공격자는 바이트 스트림 내의 객체 정보를 조작하여, 역직렬화 과정에서 실행되는 readObject() 등의 메서드를 악용해 시스템 명령어를 실행(RCE)하거나 파일을 삭제하는 등 서버를 완전히 장악할 수 있습니다.
2. 흔히 발생하는 취약한 패턴
주로 분산 시스템 간의 통신, 세션 공유, 캐시 저장소 등에 객체를 전달할 때 발생합니다.
-
Java Native Deserialization:
ObjectInputStream.readObject()를 사용하여 필터링 없이 데이터를 읽는 경우. -
취약한 라이브러리 사용: 구버전의 Apache Commons Collections 등 '가젯(Gadget) 클래스'가 포함된 라이브러리가 클래스패스에 존재하는 경우 공격이 용이해집니다.
-
JSON/XML 라이브러리 오설정: Jackson이나 Fastjson 등에서 타입 정보를 포함하여 역직렬화하도록 설정(
enableDefaultTyping)된 경우.
3. 실무적 대응: 직렬화 지양과 화이트리스트 검증
가장 좋은 방법은 자바 직렬화 자체를 사용하지 않는 것이지만, 필요하다면 다음과 같은 방어벽을 세워야 합니다.
-
데이터 포맷 변경: 가능하면 자바 직렬화 대신 JSON, XML, Protobuf와 같은 순수 데이터 포맷을 사용하십시오.
-
화이트리스트 기반 필터링: Java 9 이상에서 제공하는
ObjectInputFilter를 사용하여, 허용된 클래스만 역직렬화되도록 제한합니다. -
라이브러리 최신화: 역직렬화 공격에 악용될 수 있는 가젯 클래스들이 패치된 최신 버전의 라이브러리를 사용하십시오.
-
민감 정보 제외: 직렬화되는 객체 내의 비밀번호나 API 키 등은
transient키워드를 사용하여 직렬화 대상에서 제외합니다.
4. CWE-502 대응 및 안전한 역직렬화 자바 코드 예시
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
public class SecureDeserializer {
private static final Logger logger = LoggerFactory.getLogger(SecureDeserializer.class);
// [CWE-502 조치] ObjectInputFilter를 사용하여 허용된 클래스만 역직렬화
public Object deserializeSafe(byte[] data) {
try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
ObjectInputStream ois = new ObjectInputStream(bais)) {
// 1. 역직렬화 필터 설정 (화이트리스트 방식)
// MySafeClass 클래스 및 java.lang 패키지 등 꼭 필요한 것만 허용
ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(
"com.example.MySafeClass;java.base/*;!*");
ois.setObjectInputFilter(filter);
logger.debug("Attempting to deserialize data with whitelist filter.");
return ois.readObject();
} catch (InvalidClassException ice) {
// 허용되지 않은 클래스 역직렬화 시도 시 발생
logger.debug("Security Violation: Untrusted class deserialization attempted!");
} catch (Exception e) {
logger.debug("Deserialization error: {}", e.getMessage());
}
return null;
}
}
코멘트: 역직렬화 취약점은 코드 한 줄로 서버 전체를 넘겨줄 수 있는 매우 위험한 공격입니다. 외부에서 온 바이트 뭉치는 독이 든 성배와 같습니다. 반드시 화이트리스트 필터를 적용하고, 가급적이면 객체 자체를 주고받기보다 JSON 형태의 텍스트 데이터로 통신하는 구조를 지향하십시오. logger.debug()를 통해 부적절한 클래스 로드 시도를 기록하고 모니터링하는 것이 시큐어 코딩의 핵심입니다.
댓글 달기