安全公告:通过docutils实现任意文件包含

发表于 Markus Holtermann 2015年4月21日

docutils 包是渲染reStructuredText (reST) 的标准包。reST 的一项功能是在文档中包含其他文件。相应的指令默认情况下是启用的,这对于docutils的原始用例(渲染文档)来说是有效的。

Django ≤ 1.5 包含一个包contrib.markup它依赖于docutils,并提供一个模板过滤器,用于按需将reST渲染为HTML。这会在不禁用有问题的文件包含指令的情况下发生。如果docutils的渲染使用了未经消毒的用户输入且未禁用指令,攻击者可以访问主机上的任意文件(至少是运行WSGI容器的用户可以访问的文件)。这最终可能导致安全信息的泄露,例如项目设置。这种情况已在文档中说明

在Django 1.6中,contrib.markup该应用已被移除。但是,Django宇宙中的许多第三方应用程序仍然依赖于docutils,并且也复制了Django用于允许禁用指令的模式。

docutils_settings = getattr(settings, 'RESTRUCTUREDTEXT_FILTER_SETTINGS', {})
parts = publish_parts(
    source=smart_bytes(value),
    writer_name="html4css1",
    settings_overrides=docutils_settings
)
return force_text(parts["fragment"])

这些软件包可能不包含Django文档中包含的相同警告,无论如何,最好默认禁用文件包含,以便实现“默认安全”,而不是依赖用户显式禁用它。

为了解决任意文件包含问题,软件包维护者应该采用以下模式

docutils_settings = {
    'raw_enabled': False,
    'file_insertion_enabled': False,
}
docutils_settings.update(getattr(settings, 'RESTRUCTUREDTEXT_FILTER_SETTINGS', {}))
parts = publish_parts(
    source=smart_bytes(value),
    writer_name="html4css1",
    settings_overrides=docutils_settings
)
return force_text(parts["fragment"])

使用上述模式的软件包的用户应更新其项目设置以包含

RESTRUCTUREDTEXT_FILTER_SETTINGS = {
    'raw_enabled': False,
    'file_insertion_enabled': False,
}
返回顶部