flawopen.com/Ruby YAML/Ruby YAML
Безопасен ли YAML.load для недоверенных данных?
Проверьте фактически загруженную версию Psych: Psych 4, входящий в Ruby 3.1, изменил 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. При небезопасной загрузке документ с тегом может запросить создание класса и задать значения его сериализованного состояния; последствия зависят от доступных классов и их поведения. Так строятся цепочки гаджетов десериализации. Загружайте недоверенный YAML безопасно и отдельно проверяйте полученные данные. Аналогичный общий риск есть у Python pickle, PHP unserialize и Ruby Marshal.load.
Rails и другие приложения могут загружать множество зависимостей, расширяя набор классов и поведения, доступных небезопасной цепочке десериализации. Это зависит от конкретного развертывания и не является свойством каждого Rails-приложения или YAML-документа.
Почему смена версии вызвала путаницу
В Psych 4 метод YAML.load по умолчанию стал использовать безопасную загрузку, а unsafe_load сохранил прежнее поведение с созданием объектов. Psych 4 входил в Ruby 3.1, но приложение может выбрать другую версию gem Psych. Проверяйте разрешённую зависимость и runtime, а не только Ruby. Безопасная загрузка может отклонять классы приложения или aliases; мигрируйте с минимальным явным списком разрешённых классов, а не переходите на unsafe_load.
Если после обновления появился unsafe_load, считайте вызов проблемой безопасности, если ввод может контролироваться за пределами доверенной границы развёртывания. Используйте safe_load с минимальным списком permitted_classes; не расширяйте его только ради подавления ошибок совместимости.
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