본문 바로가기
일반IT/IT보안

🎁 "선물 상자를 열었더니 폭탄이!" OWASP A8:2017 - 안전하지 않은 역직렬화

by gasbugs 2025. 8. 16.

안녕하세요! 👋 웹 보안의 깊은 곳을 파헤치는 여러분, 오늘은 2017년 OWASP Top 10에 새로 등장하며 많은 개발자를 긴장하게 만든 A8: 안전하지 않은 역직렬화(Insecure Deserialization)에 대해 알아보겠습니다.

 

https://github.com/OWASP-Seoul/owasp/raw/master/OWASP%20Project/OWASP_Top_10-2017-ko.pdf

 

조금은 생소하게 들릴 수 있는 '역직렬화'라는 과정에 숨겨진 위험이 어떻게 시스템 전체를 장악하는 원격 코드 실행(RCE)까지 이어질 수 있는지, 그 무서운 잠재력을 지금부터 쉽게 풀어드리겠습니다. 💣


🤔 직렬화? 역직렬화? 그게 뭔가요?

이 취약점을 이해하려면 먼저 직렬화(Serialization)역직렬화(Deserialization)의 개념을 알아야 합니다.

  • 직렬화 (Serialization) 📦: 프로그램이 사용하는 객체(Object)를 파일에 저장하거나 네트워크로 전송하기 쉬운 형태, 즉 연속적인 바이트 스트림(Byte Stream)이나 문자열로 변환하는 과정을 말합니다. 마치 살아있는 복잡한 로봇을 배송하기 쉽게 분해해서 상자에 담는 것과 같습니다.
  • 역직렬화 (Deserialization) 🤖: 직렬화된 바이트 스트림을 다시 원래의 객체 형태로 메모리에 복원하는 과정입니다. 상자에 담긴 부품들을 꺼내 원래의 로봇으로 재조립하는 것과 같죠.

이 기능은 여러 시스템 간에 데이터를 주고받거나, 현재 상태를 저장했다가 나중에 복원하는 등 매우 유용하게 사용됩니다.

안전하지 않은 역직렬화는 바로 이 '재조립' 과정에서 발생합니다. 만약 공격자가 보낸 악의적으로 조작된 '부품 상자(직렬화된 데이터)'를 애플리케이션이 아무런 의심 없이 받아서 재조립(역직렬화)한다면 어떻게 될까요? 원래의 로봇이 아닌, 공격자의 명령을 따르는 파괴용 로봇이 조립될 수 있습니다.


공격 시나리오: 어떻게 시스템을 장악하는가

안전하지 않은 역직렬화 공격의 가장 큰 특징은 데이터만 보내는 것처럼 보이지만, 실제로는 코드(로직)를 주입한다는 것입니다.

원격 코드 실행 (RCE, Remote Code Execution)

가장 치명적인 공격 형태입니다. 많은 프로그래밍 언어에서 객체가 역직렬화될 때 특정 메서드(생성자, 소멸자 등)가 자동으로 호출되는 경우가 있습니다. 공격자는 이 점을 악용하여, 역직렬화 과정에서 시스템 명령어를 실행하는 코드가 담긴 '가짜 객체'를 만들어 전달합니다.

 

예시: Java 애플리케이션 공격

  1. Java는 직렬화된 객체를 다루는 라이브러리(예: Apache Commons Collections)에 알려진 취약점들이 존재합니다.
  2. 공격자는 이 취약점을 이용해, 역직렬화될 때 Runtime.getRuntime().exec("공격 명령어");와 같은 코드를 실행하도록 조작된 객체를 생성하고 직렬화합니다.
  3. 이 직렬화된 데이터를 쿠키, HTTP 파라미터 등 애플리케이션이 받아들이는 경로를 통해 서버에 전송합니다.
  4. 서버는 이 데이터를 받아 역직렬화를 수행하는 순간, 내부에 숨겨진 악성 코드가 실행됩니다. 공격자는 이를 통해 웹쉘을 업로드하거나 시스템을 완전히 장악할 수 있습니다.

이 공격은 방화벽이나 다른 보안 장치를 우회하여 직접 서버 내부에서 코드가 실행되기 때문에 매우 탐지하기 어렵고 파괴적입니다.

그 외 공격 유형

  • 권한 상승: 낮은 권한을 가진 사용자의 객체를 역직렬화하는 과정에서 권한을 확인하는 필드를 조작하여 관리자 권한을 획득합니다.
  • 서비스 거부(DoS): 역직렬화 과정에서 많은 리소스를 소모하거나 무한 루프에 빠지도록 조작된 객체를 보내 시스템을 마비시킵니다.
  • 데이터 조작: 애플리케이션 로직에서 중요한 역할을 하는 객체의 상태(예: 결제 금액, 사용자 등급)를 조작하여 비즈니스 로직을 공격합니다.

🛡️ 역직렬화 폭탄, 어떻게 막을 수 있을까요?

이 취약점의 핵심은 신뢰할 수 없는 출처의 데이터를 역직렬화하는 것입니다. 따라서 방어의 핵심도 여기에 있습니다.

1. 신뢰할 수 없는 데이터의 역직렬화 금지 (가장 좋은 방법)

가장 확실한 방법은 외부로부터 받은 데이터를 역직렬화하는 기능 자체를 사용하지 않는 것입니다. 특히 사용자 입력이 직접 닿는 곳에서는 절대 역직렬화를 수행해서는 안 됩니다.

2. 안전한 데이터 포맷 사용

객체를 직접 주고받는 대신, JSON이나 XML과 같이 데이터 구조만 표현하는 단순한 포맷을 사용하는 것이 훨씬 안전합니다. 이런 포맷들은 실행 가능한 코드를 포함하지 않기 때문에 역직렬화 공격의 위험이 없습니다. (단, XML의 경우 XXE 취약점에 주의해야 합니다.)

3. 데이터 무결성 검증

부득이하게 직렬화된 객체를 사용해야 한다면, 데이터가 전송 중에 변조되지 않았음을 보장하기 위해 **디지털 서명(예: HMAC)**을 사용해야 합니다. 데이터를 직렬화할 때 서명을 함께 생성하고, 역직렬화하기 전에 서명이 유효한지 반드시 검증해야 합니다.

4. 역직렬화 과정 모니터링 및 제한

  • 타입 제한: 역직렬화가 가능한 클래스를 화이트리스트 방식으로 엄격하게 제한하여, 예상치 못한 클래스의 객체가 생성되는 것을 막습니다.
  • 로깅 및 감시: 역직렬화 실패나 예외가 발생할 경우, 이를 기록하고 모니터링하여 공격 시도를 탐지해야 합니다.

5. 라이브러리 최신 상태 유지

사용하는 라이브러리나 프레임워크에 알려진 역직렬화 취약점이 있는지 항상 확인하고, 최신 보안 패치를 적용해야 합니다.


2021년 OWASP Top 10에서는 이 취약점이 **A08: 소프트웨어 및 데이터 무결성 실패(Software and Data Integrity Failures)**라는 더 넓은 카테고리에 포함되었습니다. 이는 단순히 역직렬화뿐만 아니라, 소프트웨어 업데이트나 CI/CD 파이프라인에서 신뢰할 수 없는 코드를 가져와 실행하는 모든 위험을 포괄하는 개념입니다.

 

안전하지 않은 역직렬화는 한번 터지면 그 파급력이 엄청난 '시한폭탄'과 같습니다. 개발 편의성을 위해 사용하는 기능이 시스템의 심장을 겨누는 칼날이 될 수 있다는 점을 명심하고, 데이터 교환 시에는 항상 안전성을 최우선으로 고려해야 합니다.