본문으로 건너뛰기

Ruby Array#pack 취약점: 메모리 누출

Ruby Array Pack Bleed – Impacts Ruby 1.6.7 to 4.0.0

작성자
HackerNews
발행일
2025년 12월 25일

핵심 요약

  • 1 Ruby Array#pack 메서드에서 부호 없는 정수를 부호 있는 변수에 저장할 때 음수 반복 횟수가 발생하여 메모리 경계를 넘어선 읽기가 가능한 취약점이 발견되었습니다.
  • 2 취약점은 'X' 지시자와 결합하여 문자열이 의도치 않게 확장되도록 하여 할당된 버퍼 외부의 메모리 내용을 노출시킵니다.
  • 3 이 취약점은 Ruby 4.0.0 및 이전 버전에 영향을 미치며, 특정 조건에서 문자열 길이를 조절하여 보호 장치를 우회하고 메모리 누출을 유발할 수 있습니다.

도입

Ruby 4.0.0 출시와 함께 Ruby MRI의 정수 처리 버그 재조사 중, 할당된 문자열 버퍼 경계를 넘어선 메모리 읽기가 가능한 취약점이 발견되었습니다. 이 취약점은 Ruby 4.0.0 및 이전 버전에 영향을 미치며, 잠재적으로 Ruby 1.6.7까지 거슬러 올라갈 수 있습니다. 메모리 누출은 심각한 보안 영향을 미치지만, 해당 메서드는 실제 Ruby 애플리케이션에서 드물게 사용되며 공격자가 인수를 제어할 가능성 또한 낮습니다.

Array

pack 메서드의 취약점 상세

이 취약점은 Array 클래스의 인스턴스 메서드인 pack 내부에 존재합니다. pack 메서드는 배열 요소를 이진 문자열로 변환하는 데 사용되는 템플릿 문자열 인수를 받습니다.

템플릿 문자열 및 지시자

  • 템플릿 문자열은 ‘H’(높은 니블 우선의 헥스 문자열) 또는 ‘m’(base64 인코딩 문자열)과 같은 지시자로 구성됩니다.

  • 지시자 뒤에는 해당 지시자가 소비해야 할 양을 지정하는 반복 횟수가 올 수 있습니다 (예: H2는 두 개의 헥스 문자를 소비).

음수 반복 횟수 발생 원인

  • pack 메서드의 반복 횟수 처리 코드는 ruby/pack.c에 있습니다.

  • STRTOUL 매크로는 unsigned long 값을 반환하지만, 이 값을 저장하는 len 변수는 signed long입니다.

  • 이러한 부호 불일치로 인해 매우 큰 부호 없는 값이 len에 저장될 때 음수 값으로 해석될 수 있습니다.

‘X’ 지시자를 이용한 익스플로잇

  • ‘X’ 지시자는 “바이트 뒤로 이동”하는 기능을 하며, 문자열의 길이를 줄이는 데 사용됩니다.

  • rb_str_set_len 함수는 plen - len을 통해 문자열 길이를 조정합니다.

  • len이 음수가 되면 plen - (음수)plen + (양수)가 되어 문자열이 의도치 않게 확장됩니다.

  • 예시: `[“414243”].pack(“H6X

{2**64 - 1}”)`는 원래 문자열에 널 바이트를 추가하여 메모리 누출을 시연합니다.

보호 장치 및 우회

  • ruby/string.crb_str_set_len 함수에는 len > capa 또는 len < 0일 때 “probable buffer overflow” 버그를 발생시키는 보호 장치가 있습니다.

  • 그러나 문자열의 길이를 2의 거듭제곱으로 조절하면, 할당된 용량(capacity)이 다음 2의 거듭제곱으로 반올림되는 특성을 이용하여 보호 장치를 트리거하지 않고 가장 많은 메모리를 누출할 수 있습니다.

결론

Ruby `Array#pack` 메서드의 취약점은 `unsigned long` 값을 `signed long` 변수에 저장할 때 발생하는 정수 오버플로우로 인해 음수 반복 횟수가 생성되고, 이를 'X' 지시자와 결합하여 문자열 버퍼 경계를 넘어선 메모리 읽기를 가능하게 합니다. 비록 해당 메서드의 사용 빈도와 공격자 제어 가능성이 낮지만, 메모리 관련 취약점은 심각한 보안 위험을 내포합니다. 이 발견은 Ruby MRI의 정수 처리 로직에 대한 면밀한 검토와 안전한 타입 변환의 중요성을 다시 한번 상기시키며, 향후 유사한 유형의 취약점 방지를 위한 개발자들의 주의를 요구합니다.

댓글 0

댓글 작성

댓글 삭제 시 비밀번호가 필요합니다.

이미 계정이 있으신가요? 로그인 후 댓글을 작성하세요.

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