Django 的安全策略¶
Django的开发团队致力于负责地报告和披露与安全相关的问题。因此,我们采用并遵循了一套符合这种理想的策略,以便及时向Django的官方发行版和第三方发行版发布安全更新。
报告安全问题¶
简而言之:请通过电子邮件security@djangoproject.com报告安全问题。
Django 中的大多数普通错误都会报告到 我们的公共 Trac 实例,但由于安全问题的敏感性质,我们要求不要以这种方式公开报告它们。
相反,如果您认为在 Django 中发现了具有安全影响的问题,请通过电子邮件发送问题描述至 security@djangoproject.com
。发送到该地址的邮件将会传达给 安全团队。
Once you've submitted an issue via email, you should receive an acknowledgment from a member of the security team within 3 working days. After that, the security team will begin their analysis. Depending on the action to be taken, you may receive followup emails. It can take several weeks before the security team comes to a conclusion. There is no need to chase the security team unless you discover new, relevant information. All reports aim to be resolved within the industry-standard 90 days. Confirmed vulnerabilities with a high severity level will be addressed promptly.
发送加密报告
如果您想发送加密邮件(可选),security@djangoproject.com
的公钥 ID 是 0xfcb84b8d1d17f80b
,并且这个公钥可以从大多数常用的密钥服务器获取。
Reporting guidelines¶
Include a runnable proof of concept¶
Please privately share a minimal Django project or code snippet that demonstrates the potential vulnerability. Include clear instructions on how to set up, run, and reproduce the issue.
Please do not attach screenshots of code.
User input must be sanitized¶
Reports based on a failure to sanitize user input are not valid security vulnerabilities. It is the developer's responsibility to properly handle user input. This principle is explained in our security documentation.
For example, the following is not considered valid because email
has
not been sanitized:
from django.core.mail import send_mail
from django.http import JsonResponse
def my_proof_of_concept(request):
email = request.GET.get("email", "")
send_mail("Email subject", "Email body", email, ["admin@example.com"])
return JsonResponse(status=200)
Developers must always validate and sanitize input before using it. The
correct approach would be to use a Django form to ensure email
is properly
validated:
from django import forms
from django.core.mail import send_mail
from django.http import JsonResponse
class EmailForm(forms.Form):
email = forms.EmailField()
def my_proof_of_concept(request):
form = EmailForm(request.GET)
if form.is_valid():
send_mail(
"Email subject",
"Email body",
form.cleaned_data["email"],
["admin@example.com"],
)
return JsonResponse(status=200)
return JsonResponse(form.errors, status=400)
Similarly, as Django's raw SQL constructs (such as extra()
and
RawSQL
expression) provide developers with full control over the
query, they are insecure if user input is not properly handled. As explained in
our security documentation, it is the
developer's responsibility to safely process user input for these functions.
For instance, the following is not considered valid because query
has
not been sanitized:
from django.shortcuts import HttpResponse
from .models import MyModel
def my_proof_of_concept(request):
query = request.GET.get("query", "")
q = MyModel.objects.extra(select={"id": query})
return HttpResponse(q.values())
Request headers and URLs must be under 8K bytes¶
To prevent denial-of-service (DoS) attacks, production-grade servers impose limits on request header and URL sizes. For example, by default Gunicorn allows up to roughly:
Other web servers, such as Nginx and Apache, have similar restrictions to prevent excessive resource consumption.
Consequently, the Django security team will not consider reports that rely on request headers or URLs exceeding 8K bytes, as such inputs are already mitigated at the server level in production environments.
runserver
should never be used in production
Django's built-in development server does not enforce these limits because it is not designed to be a production server.
The request body must be under 2.5 MB¶
The DATA_UPLOAD_MAX_MEMORY_SIZE
setting limits the default maximum
request body size to 2.5 MB.
As this is enforced on all production-grade Django projects by default, a proof of concept must not exceed 2.5 MB in the request body to be considered valid.
Issues resulting from large, but potentially reasonable setting values, should be reported using the public ticket tracker for hardening.
Code under test must feasibly exist in a Django project¶
The proof of concept must plausibly occur in a production-grade Django application, reflecting real-world scenarios and following standard development practices.
Django contains many private and undocumented functions that are not part of its public API. If a vulnerability depends on directly calling these internal functions in an unsafe way, it will not be considered a valid security issue.
Content displayed by the Django Template Language must be under 100 KB¶
The Django Template Language (DTL) is designed for building the content needed to display web pages. In particular its text filters are meant for that kind of usage.
For reference, the complete works of Shakespeare have about 3.5 million bytes in plain-text ASCII encoding. Displaying such in a single request is beyond the scope of almost all websites, and so outside the scope of the DTL too.
Text processing is expensive. Django makes no guarantee that DTL text filters are never subject to degraded performance if passed deliberately crafted, sufficiently large inputs. Under default configurations, Django makes it difficult for sites to accidentally accept such payloads from untrusted sources, but, if it is necessary to display large amounts of user-provided content, it’s important that basic security measures are taken.
User-provided content should always be constrained to known maximum length. It should be filtered to remove malicious content, and validated to match expected formats. It should then be processed offline, if necessary, before being displayed.
Proof of concepts which use over 100 KB of data to be processed by the DTL will be considered invalid.
Django 如何评估报告¶
以下是安全团队在评估报告是否需要安全发布时使用的标准:
漏洞在 Django 的 受支持版本 中。
The vulnerability does not depend on manual actions that rely on code external to Django. This includes actions performed by a project's developer or maintainer using developer tools or the Django CLI. For example, attacks that require running management commands with uncommon or insecure options do not qualify.
The vulnerability applies to a production-grade Django application. This means the following scenarios do not require a security release:
安全团队可能会得出结论,漏洞的根源在于 Python 标准库,在这种情况下,报告者将被要求向 Python 核心团队报告漏洞。更多详细信息,请参阅 Python 安全指南。
有时,可能会发布安全版本来帮助解决流行第三方包中的安全漏洞。这些报告应来自包维护者。
如果你不确定你的发现是否符合这些标准,请仍然 通过电子邮件 security@djangoproject.com 私下报告。安全团队将审查你的报告并推荐正确的行动方案。
支持的版本¶
Django团队在任何时候都会为几个版本的Django提供官方安全支持。
在 GitHub 上托管的 主开发分支,将成为 Django 的下一个主要版本,会接收安全支持。仅影响主开发分支而不影响任何稳定发布版本的安全问题将在公开中修复,无需经过 披露流程。
两个最新的Django发行版系列都提供了安全支持。例如,在Django 1.5发布之前的开发周期中,将支持Django 1.4和Django 1.3。在Django 1.5发布后,Django 1.3的安全支持将结束。
长期支持版本 将在指定的期限内接收安全更新。
当出于安全原因发布新版本时,附带的通知将包括受影响的版本列表。此列表仅包含*支持*的Django版本:旧版本也可能受到影响,但我们不会调查这一点,也不会为这些版本发布补丁或新版本。
Security issue severity levels¶
The severity level of a security vulnerability is determined by the attack type.
Severity levels are:
高
远程代码执行
SQL 注入
中等
跨站脚本攻击(XSS)
跨站请求伪造(CSRF)
拒绝服务攻击
损坏的认证
低
敏感数据暴露
会话管理损坏
未验证重定向
需要不常见的配置选项的问题
Django 如何披露安全问题¶
我们将一个安全问题从私下讨论到公开披露的过程涉及多个步骤。
在公开披露前大约一周,我们会发送两个通知:
First, we notify django-announce of the date and approximate time of the upcoming security release, as well as the severity of the issues. This is to aid organizations that need to ensure they have staff available to handle triaging our announcement and upgrade Django as needed.
其次,我们会通知一份 个人和组织名单,主要由操作系统供应商和其他 Django 分发商组成。此电子邮件由 Django 发布团队 的某人使用 PGP 密钥签名,内容包括:
问题的完整描述以及受影响的Django版本
我们将采取的补救措施。
补丁(如果有的话)将应用于Django。
Django 团队将应用这些补丁、发布新版本并公开披露问题的日期。
在披露当天,我们将采取以下步骤:
将相关的补丁应用到 Django 的代码库中。
发布相关版本,将新的软件包放在 Python Package Index 和 djangoproject.com 网站 上,并在 Django 的 Git 存储库中标记新版本。
在 官方 Django 开发博客 上发布一篇公开文章,详细描述问题及其解决方案,指向相关的补丁和新版本,并署名问题的报告者(如果报告者希望公开身份)。
在 django-announce 和 oss-security@lists.openwall.com 邮件列表上发布一则通知,其中包含指向博客文章的链接。
如果认为报告的问题特别紧急——例如,由于已知有野外利用,提前通知和公开披露之间的时间可能会大大缩短。
此外,如果我们有理由相信报告给我们的问题影响了 Python/web 生态系统中的其他框架或工具,我们可能会与适当的维护者私下联系并讨论这些问题,并协调我们自己的披露和解决方案与他们的一起进行。
Django 团队还维护着一个 Django 中披露的安全问题的档案。
谁会收到提前通知¶
接收安全问题提前通知的个人和组织的完整名单不会被公开。
我们还希望将这个列表尽可能保持较小的规模,以更好地管理披露前的机密信息流动。因此,我们的通知列表并不仅仅是 Django 用户的列表,成为 Django 用户并不足以理由放置在通知列表上。
广义上来说,安全通知的接收者分为三类:
操作系统供应商和其他 Django 分发商,他们提供了一个适合报告他们的 Django 包的问题或用于一般安全报告的通用(即不是个人的个人电子邮件地址)联系地址。在任何情况下,这些地址 不得 转发到公共邮件列表或 bug 跟踪器。转发到个人维护人员或安全响应联系人的私人电子邮件的地址是可以接受的,尽管私人安全跟踪器或安全响应组更可取。
根据具体情况,已经表现出对回应和负责任地采取行动的个别包维护者。
根据具体情况,根据 Django 开发团队的判断,其他需要了解即将到来的安全问题的实体。通常,该组成员将包括一些最大的和/或最有可能受到严重影响的已知 Django 用户或分发商,他们需要表现出负责任地接收、保密和采取行动的能力。
安全审计和扫描实体
作为政策,我们不会将这些类型的实体添加到通知列表中。
请求通知¶
如果您认为自己或您有授权代表的组织属于上述任何一组,您可以通过发送电子邮件至 security@djangoproject.com
来请求加入 Django 的通知列表。请在主题行中使用 "Security notification request"。
您的请求 必须 包含以下信息:
您的全名和您所代表的组织的名称(如果适用),以及您在该组织中的角色。
详细解释您或您的组织如何符合上述至少一组标准。
详细解释您为什么要请求安全通知。请再次注意,这并不仅仅是给 Django 用户使用的列表,绝大多数用户应该订阅 django-announce 以提前收到安全发布的通知,而不是请求详细的通知。
您希望添加到我们通知列表的电子邮件地址。
解释谁将接收/审查发送到该地址的邮件,以及关于将采取的任何自动操作的信息(例如,在 bug 跟踪器中提出机密问题)。
对于个人,与您的地址关联的可用于验证从您那里接收的电子邮件和根据需要加密发送给您的电子邮件的公钥的 ID。
提交后,您的请求将由 Django 开发团队考虑;您将在30天内收到回复,通知您请求的结果。
请您也要记住,对于任何个人或组织来说,接收安全通知是由 Django 开发团队完全自行决定的特权,而且这个特权可以在任何时候被撤销,有或无需解释。
提供所有必要的信息
如果您在初始联系中未提供所需的信息,将影响我们是否批准您的请求的决定。