Ruby Oj JSON 파서의 객체 역직렬화 취약점

Object deserialization attacks using Ruby's Oj JSON parser

작성자
HackerNews
발행일
2025년 07월 26일

핵심 요약

  • 1 Ruby의 Oj JSON 파서는 기본 설정에서 콜론으로 시작하는 문자열을 심볼로 변환하여 객체 역직렬화 취약점을 유발할 수 있습니다.
  • 2 이 취약점은 SQL 쿼리 조작을 통한 정보 유출 및 잠재적인 원격 코드 실행(RCE)으로 이어질 수 있습니다.
  • 3 즉각적인 완화책으로는 `Oj.default_options = { mode: :strict }` 설정 적용 또는 `Oj.safe_load` 함수 사용이 권장됩니다.

도입

이 글은 Ruby의 Oj JSON 파서에서 발견된 심각한 보안 취약점에 대해 다룹니다. 필자는 PG::UndefinedColumn 예외를 통해 알 수 없는 데이터베이스 컬럼 이름이 외부로부터 주입되고 있음을 발견했습니다. JSON 요청 본문에 `:xyzzydeadbeef`와 같이 Ruby 심볼 형태의 문자열이 포함되어 있었고, 이것이 Sequel 라이브러리에서 데이터베이스 컬럼 이름으로 해석되면서 예기치 않은 오류가 발생했습니다. 이 문제는 결국 Oj JSON 파서의 기본 동작 방식에서 기인한 것으로 밝혀졌으며, 이는 객체 역직렬화 취약점으로 이어질 수 있는 위험성을 내포하고 있습니다.

Oj는 Ruby 생태계에서 ‘가장 빠른 JSON 파서 및 객체 직렬 변환기’로 알려져 있으며, 많은 프로젝트에서 성능 향상을 위해 사용됩니다. 그러나 Oj의 ‘객체 직렬화’ 기능은 보안 관점에서 심각한 문제를 야기할 수 있습니다. 기본적으로 Oj는 콜론으로 시작하는 모든 문자열을 Ruby 심볼로 자동 변환하는데, 이는 Oj.load('{"name":":xyzzydeadbeef"}')와 같은 간단한 코드를 통해 확인할 수 있습니다. 이러한 기본 동작은 공격자가 임의의 심볼을 주입하여 애플리케이션의 동작을 조작할 수 있는 길을 열어줍니다.

필자는 이러한 ‘기본적으로 안전하지 않은(Insecure By Default)’ 소프트웨어 설계 관행을 강력히 비판합니다. 소프트웨어 개발자는 사용자가 올바르고 안전한 방식으로 소프트웨어를 사용하도록 유도할 책임이 있으며, 위험한 기능은 명확하게 경고하거나 unsafe_load와 같이 명시적인 이름을 부여해야 한다고 주장합니다. 현재 Oj의 문서화는 이러한 위험성을 충분히 강조하지 않아, 개발자들이 무심코 취약한 코드를 작성할 수 있게 합니다.

이 취약점의 악용 사례는 다양합니다. 예를 들어, 공격자가 {"name":":admin_notes"}와 같은 JSON을 전송하면, Oj는 이를 {"name"=>:admin_notes}로 변환합니다. 만약 애플리케이션이 이 값을 사용하여 SQL 쿼리를 구성한다면, UPDATE users SET name=admin_notes WHERE id=42와 같은 쿼리가 실행되어 admin_notes 컬럼의 내용이 name 컬럼으로 복사될 수 있습니다. 이로 인해 공격자는 일반적으로 접근할 수 없는 민감한 정보를 읽을 수 있게 됩니다. 더욱 심각하게는, Oj의 객체 직렬화 기능을 통해 공격자가 임의의 Ruby 객체를 생성하고, 이를 통해 원격 코드 실행(RCE)을 유발할 가능성도 있습니다. 이는 공격자가 시스템에 대한 완전한 제어권을 얻을 수 있음을 의미합니다.

이러한 위험을 완화하기 위한 몇 가지 전략이 제시됩니다. 첫째, 프로젝트의 Gemfile.lock을 확인하여 oj gem이 사용되고 있는지 확인해야 합니다. 둘째, 가능하다면 oj 대신 JSON.parse와 같이 안전한 json gem을 사용하는 것이 좋습니다. 셋째, oj를 반드시 사용해야 한다면, 모든 Oj.load 호출을 Oj.safe_load로 변경해야 합니다. 넷째, 객체 역직렬화를 위해 oj를 사용하는 것은 매우 위험하므로, Psych.loadpermitted_classes와 같이 안전 기능이 있는 다른 라이브러리로 전환하는 것을 강력히 권장합니다. 마지막으로, 종속성 내에서 안전하지 않은 Oj.load 사용을 방지하기 위해 애플리케이션 초기화 코드에 Oj.default_options = { mode: :strict }를 설정하여 기본 파싱 모드를 엄격하게 제한하는 것이 중요합니다.

결론

결론적으로, Ruby의 Oj JSON 파서에서 발생하는 객체 역직렬화 취약점은 SQL 쿼리 조작 및 원격 코드 실행으로 이어질 수 있는 심각한 보안 문제입니다. 이는 소프트웨어의 '기본적으로 안전하지 않은' 설계 관행이 초래하는 전형적인 예시입니다. 개발자는 이러한 위험을 인지하고, `Oj.default_options = { mode: :strict }`, `Oj.safe_load` 사용, 또는 보다 안전한 대안 라이브러리로의 전환과 같은 적극적인 완화 전략을 적용하여 잠재적인 RCE 취약점으로부터 애플리케이션을 보호해야 합니다. 이 글이 독자들이 자신의 소프트웨어에서 이러한 유형의 취약점을 식별하고 해결하는 데 도움이 되기를 바랍니다.

댓글 0

댓글 작성

0/1000
정중하고 건설적인 댓글을 작성해 주세요.

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!