Django错误报告电子邮件:env vars泄漏信息

时间:2014-12-10 21:42:02

标签: python django logging environment-variables

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团队提交补丁?或者我错过了其他一些明显的方法来解决这个问题?

4 个答案:

答案 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