使用 ruamel.yaml 中的默认加载是否安全
我可以使用 ruamel.yaml 加载和转储带有标签的 YAML 文件,并且标签会被保留。
如果我让我的客户编辑 YAML 文档,他们是否能够因为任意 python 模块代码执行而利用 YAML 漏洞?据我了解,ruamel.yaml 源自 PyYAML,根据其文档,该漏洞存在此类漏洞。
I can load and dump YAML files with tags using ruamel.yaml, and the tags are preserved.
If I let my customers edit the YAML document, will they be able to exploit the YAML vulnerabilities because of arbitrary python module code execution? As I understand it ruamel.yaml is derived from PyYAML that has such vulnerabilities according to its documentation.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
从您的问题中我推断您在
YAML()
实例上使用.load()
方法,如下所示:而不是与旧的 PyYAML
load
兼容函数(无法处理未知标签,并且可能不安全)。简短的回答是,是的,这是安全的,因为在不调用任何标签相关代码的情况下不会对标签进行解释,标签只是被分配(作为字符串)到已知类型(CommentedMap
、CommentedSeq< /code>,
TaggedScalar
分别用于映射、序列和标量)。PyYAML 中的漏洞来自其
Constructor
,它是不安全的Loader
的一部分。这是 PyYAML 最长的默认设置,大多数人甚至在他们可以使用安全加载器时也使用它,因为他们没有使用任何标签(或者可以根据 SafeLoader/Constructor 注册他们需要的标签) >)。不安全的Constructor
是SafeConstructor
的子类,它不安全的原因是为解释python/{name,module,object,apply 注册的多种方法,new):....
标签,本质上是动态解释这些标签来加载模块和运行代码(即执行函数/方法/实例化类)。ruamel.yaml
背后的最初想法是它的RoundTripConstructor
,它也是SafeConstructor
。您过去使用现已弃用的round_trip_load
函数来获取此信息,现在使用YAML(typ='rt')
后通过.load()
方法获取此信息>,这也是没有typ
参数的YAML()
实例的默认值。RoundTripConstructor
确实不注册任何标签,也没有任何代码可以解释SafeConstructor
使用的正常标签之外的标签。只有使用
typ='unsafe'
的旧 PyYAMLload
和 ruamel.yaml 可以通过!!python/ 执行代码,在篡改的 YAML 输入上执行任意 Python 代码..
标签。当您使用
typ='rt'
时,即使未注册标签,节点上的标签也会被保留。这是可能的,因为在处理节点时(在往返模式下),这些标签将仅作为字符串分配给标记节点的构造类型(映射、序列或标量,标记的除外)上的属性空
)。当转储这些类型时,如果它们有标签,它会被重新插入到表示处理代码中。 在任何时候都不会评估标签、用于导入代码等。From your question I deduct you are using
.load()
method on aYAML()
instance as in:and not the old PyYAML
load
compatible function (which cannot handle unknown tags, and which can be unsafe). The short answer is that yes that is safe as no interpretation of tags is done without calling any tag dependent code, the tags just get assigned (as strings) to known types (CommentedMap
,CommentedSeq
,TaggedScalar
for mapping, sequence and scalar respectively).The vulnerability in PyYAML comes from its
Constructor
, that is part of the unsafeLoader
. This was the default for PyYAML for the longest time and most people used it even when they could have used the safeloader because they were not using any tags (or could have regeistred the tags they needed against theSafeLoader/Constructor
). That unsafeConstructor
is a subclass ofSafeConstructor
and what makes it unsafe are the multi-methods registered for the interpretation ofpython/{name,module,object,apply,new):....
tags, essentially dynamically interpreting these tags to load modules and run code (i.e. execute functions/methods/instantiate classes).The initial idea behind
ruamel.yaml
was itsRoundTripConstructor
, which is also a subclass of theSafeConstructor
. You used to get this using the now deprecatedround_trip_load
function and nowadays via the.load()
method after usingYAML(typ='rt')
, this is also the default for aYAML()
instance withouttyp
argument. ThatRoundTripConstructor
does not registers any tags or have any code that interprets tags above and beyond the normal tags that theSafeConstructor
uses.Only the old PyYAML
load
and ruamel.yaml usingtyp='unsafe'
can execute arbitrary Python code on doctored YAML input by executing code via the!!python/..
tags.When you use
typ='rt'
the tag on nodes is preserved, even when a tag is not registered. This is possible because while processing nodes (in round-trip mode), those tags will just be assigned as strings to an attribute on the constructed type of the tagged node (mapping, sequence, or scalar, with the exception of taggednull
). And when dumping these types, if they have a tag, it gets re-inserted into the representation processing code. At no point is the tag evaluated, used to import code, etc.