Django内置的错误电子邮件管理员功能(参见https://docs.djangoproject.com/en/dev/howto/error-reporting/)非常方便。
但是,这些回溯电子邮件包含完整的环境变量转储。
正如django docs& amp;其他地方(例如https://docs.djangoproject.com/en/dev/howto/deployment/checklist/)我已经将一些秘密/密钥/密码移动到环境变量中,这是一种让它们远离代码库的简单方法。在部署中改变它们。不幸的是,这意味着当有崩溃报告时,这些秘密会以明确的方式发送到一组电子邮件帐户。不是一个好习惯。
django ExceptionReporter具有基本过滤功能,可以提取“危险或令人反感”的设置,例如settings.py中名称包含字符串“pass”或“key”的任何项的值将替换为**** s。因此,settings.py中的密钥被删除。但是此过滤器不适用于环境变量,这些变量出现在这些错误报告的Traceback-> Local vars->请求和Request Information-> Meta部分中。
显然还有其他方法来管理机密,但unix环境对于小型网站来说是一种非常常见的解决方案,因为在这些网站中无法创建更复杂的配置系统。
在基本的django文档中推荐的这两种做法在一起应用时也是不安全的,这似乎也是有问题的。
通过电子邮件发送站点调试信息总会带来泄露信息的风险,但这似乎是一个重要的遗漏,可以通过扩展过滤来解决,也许可以通过某些设置来控制。
有没有人已经修改了这个(大概是扩展了django / views / debug.py中的过滤)以进行部署和/或向django团队提交补丁?或者我错过了其他一些明显的方法来解决这个问题?
答案 0 :(得分:3)
好的,在我之前的检查中错过了这个,但显然django团队记录了大约这个错误&关闭它6年前将无法修复:
https://code.djangoproject.com/ticket/7472
我将与他们接触,因为我相信django在这段时间内已经取得了实质性的安全进展,现在可能想要并且有一些简单的方法来解决这个问题。 :)
与此同时,如果您使用此电子邮件管理员功能,请认识到风险。如果您发送这些电子邮件,我强烈建议您将所有秘密/密码/密钥/证书/等放在python配置文件中,并确保您正在清理传递给您的django Web服务的(unix)环境。
答案 1 :(得分:1)
我遇到了同样的问题,并通过创建自定义中间件来解决它,如Django docs中所述。此方法假定您知道要从错误页面/电子邮件中隐藏的env变量的名称,并且实际上并不需要在每个请求中都存在这些变量。然后,您可以在生成错误响应之前从request.META字典中过滤掉它们:
class RequestSafetyMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
request.META.pop('TOP_SECRET', None)
response = self.get_response(request)
return response
我希望这有帮助!我希望Django将相同的安全混淆规则应用于env变量,因为它适用于设置,所以这甚至都不是问题。
答案 2 :(得分:0)
此类问题涉及处理潜在敏感信息的所有应用程序。如果错误报告系统不构成隐私增强机制(大多数情况),则报告此类应用程序的错误可能会泄漏敏感信息,这显然是Django的情况。
使用专用解决方案可以实现错误报告中的隐私保护,例如:
http://www.gsd.inesc-id.pt/~romanop/files/papers/ESOP14.pdf
http://research.microsoft.com/en-us/projects/betterbug/castro08better.pdf
这些系统可以与错误报告系统集成,以允许在要求用户授权传输之前清理生成的错误报告的内容。
未来几个月将推出更多近期作品,其中包括开源实施。我们会在这些帖子出现后对其进行更新。
希望这会有所帮助。
答案 3 :(得分:0)
在Apache中使用mod_wsgi
的情况下,环境变量(通过Apache SetEnv
指令或其他方式设置)将传递给第一个application
中的environ
函数参数。
为了能够在settings.py
(或其他地方)访问这些环境变量,可以使用例如将它们复制到os.environ
。
os.environ['TOP_SECRET'] = environ['TOP_SECRET']
在此之后,environ
会传递给django.core.handlers.wsgi.WSGIHandler
(通过django.core.wsgi.get_wsgi_application
),最终会使其显示错误报告。
TOP_SECRET
密钥在复制到environ
后不需要保留在os.environ
中,因此将上面的行更改为os.environ['TOP_SECRET'] = environ.pop('TOP_SECRET', '')
会将其从错误中移除报告。
总而言之,我的wsgi.py
文件如下:
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "App.settings")
env_variables_to_pass = ['TOP_SECRET']
def application(environ, start_response):
# pass the WSGI environment variables on through to os.environ
for var in env_variables_to_pass:
os.environ[var] = environ.pop(var, '')
return get_wsgi_application()(environ, start_response)
这意味着所需的环境变量在os.environ
中可用,但不会显示在错误报告中。
我可能在这里遗漏了一些东西,但这似乎对我有用。如果有理由不这样做,请发表评论。首先创建environ
字典的副本可能更安全,即my_environ = copy.deepcopy(environ)
,然后直接使用该字典而不是environ
。
另请注意,其他敏感变量(例如POST
次请求中的密码)应为filtered。