flawopen.com/Ruby YAML/Ruby YAML
신뢰할 수 없는 입력에 YAML.load를 사용해도 안전한가요?
애플리케이션이 실제로 불러오는 Psych 버전을 확인하세요. Ruby 3.1에 포함된 Psych 4는 YAML.load가 기본적으로 안전하게 역직렬화하도록 변경했습니다. 이전 Psych 버전은 제한 없이 객체를 생성했고, Psych는 Ruby와 별도로 업그레이드할 수도 있습니다. YAML.unsafe_load와 Marshal.load는 Ruby 객체를 역직렬화하므로 신뢰할 수 없는 입력에 사용하면 안 됩니다.
# Psych < 4: YAML.load used unsafe # object construction by default. YAML.load(params[:config]) # Every Psych version: explicitly unsafe. YAML.unsafe_load(user_input) Psych.unsafe_load(user_input) # Marshal has no restricted safe-load API. Marshal.load(cookie_value)
# Explicit restricted types; keep this list minimal. require "yaml" require "date" data = YAML.safe_load( input, permitted_classes: [Date], permitted_symbols: [], aliases: false ) # For ordinary external data, prefer JSON and # validate its shape, values, and input size. data = JSON.parse(input)
YAML이 위험할 수 있는 이유
YAML 태그는 Psych를 통해 Ruby 객체로 변환될 수 있습니다. 안전하지 않은 로드에서는 태그가 붙은 문서가 클래스를 생성하고 직렬화된 상태의 값을 지정할 수 있습니다. 영향은 사용 가능한 클래스와 동작에 따라 달라지며, 이것이 역직렬화 gadget chain의 기반입니다. 신뢰할 수 없는 YAML에는 안전한 로드를 사용하고 반환된 데이터도 별도로 검증하세요. 유사한 일반 위험은 Python pickle, PHP unserialize, Ruby Marshal.load에도 있습니다.
Rails 등은 많은 의존성을 불러올 수 있어 안전하지 않은 역직렬화 체인이 활용할 수 있는 클래스와 동작이 늘어날 수 있습니다. 이는 배포 환경에 따라 달라지며 모든 Rails 애플리케이션이나 YAML 문서에 해당하지 않습니다.
버전 변경이 혼란을 일으킨 이유
Psych 4는 YAML.load를 기본 안전 로드로 바꾸고 이전 객체 생성 동작을 위한 unsafe_load를 추가했습니다. Ruby 3.1에 Psych 4가 포함됐지만 앱은 다른 Psych gem 버전을 선택할 수 있습니다. Ruby 버전만 보지 말고 실제 해결된 의존성과 런타임을 확인하세요. 안전 로드가 앱 전용 클래스나 alias를 거부할 수 있지만 unsafe_load로 전환하지 말고 최소 명시적 허용 목록으로 이전하세요.
업그레이드로 unsafe_load가 도입되면 입력이 신뢰된 배포 경계 밖에서 영향을 받을 수 있을 때 보안 문제로 처리하세요. 최소한의 permitted_classes만 지정한 safe_load를 우선하고, 호환성 오류를 숨기려고 허용 범위를 넓히지 마세요.
FAQ
YAML.safe_load는 완전히 안전한가요?
직접 관리하는 설정 파일은 어떤가요?
Marshal은 사용해도 되나요?
별도의 Ruby 위험: Marshal.load
YAML과 별개로 Ruby 문서는 Marshal.load가 프로세스에 로드된 거의 모든 클래스를 복원할 수 있으며, 신뢰할 수 없는 데이터에서는 원격 코드 실행으로 이어질 수 있다고 경고합니다. Marshal 데이터는 신뢰 경계 안에 두고, 사용자 제공 또는 공격자 영향을 받은 바이트를 역직렬화하지 마세요.
참고 자료
- Ruby documentation — Psych (YAML)
- Psych 4.0 — Ruby 3.1 API documentation
- Ruby documentation — Marshal security considerations
- CVE-2024-35221 — YAML alias denial of service in RubyGems metadata
- CWE-502 — Deserialization of Untrusted Data
- Is Python's pickle safe for untrusted data?
- Is PHP's unserialize() safe on user input?
- Ruby 문서 — Marshal.load 보안 경고