游客发表

django漏洞

发帖时间:2026-10-17 05:07:32

Django 的漏洞 DEBUG=True 一上线,基本等于把家钥匙插在门上。漏洞去年有个做电商的漏洞朋友,测试环境跑得好好的漏洞,运维图省事直接把开发配置推到了生产。漏洞结果第二天 Google 就收录了他们的漏洞 /settings.py 报错页,数据库密码、漏洞支付接口密钥、漏洞甚至 Redis 的漏洞连接串全在堆栈信息里躺着。攻击者连扫描器都没用,漏洞手动翻了翻报错就拿到了后台入口。漏洞

这不是漏洞段子。Django 默认的漏洞调试页面会暴露环境变量、已安装应用、漏洞中间件顺序、漏洞甚至 SQL 语句。你只要触发一个 500 错误,比如访问一个不存在的模板变量,它就把整个调用链吐出来。我见过最离谱的案例是某 SaaS 平台,DEBUG=True 跑了三个月没人发现,因为他们的错误日志被 Sentry 吞了,前端只显示“服务器开小差”。后来是一个安全研究员在推特上贴了截图,他们才连夜改配置。

另一个坑是 ALLOWED_HOSTS。很多教程教你填 ['*'] 图省事,尤其在容器化部署里。这玩意儿配合 DEBUG=False 倒不会直接泄露信息,但给了攻击者伪造 Host 头的能力。密码重置链接、缓存键、甚至某些第三方回调校验都会拿 Host 做依据。我试过一个站,把 Host 改成 evil.com 发密码重置请求,收到的邮件里链接域名真变成了 evil.com——用户一点,token 就送到攻击者手里了。

SQL 注入这块 Django ORM 本身防护得不错,但架不住有人非要写原生 SQL。去年审计一个项目,看到 cursor.execute("SELECT * FROM users WHERE name = '%s'" % name),字符串拼接直接怼进去。开发者说“我用了 %s 啊”,可那是 Python 的格式化,不是数据库驱动的参数化。Django 的 raw() 和 extra() 也容易出事,尤其是 extra(where=["id = %s" % user_id]) 这种写法,跟直接拼 SQL 没区别。

文件上传的漏洞更隐蔽。Django 的 FileField 默认不校验文件内容,只检查扩展名。有人上传了一个 .jpg,里面嵌了 PHP 代码,服务器是 Nginx + PHP-FPM 混跑,结果 /media/xxx.jpg 被当成 PHP 执行了。还有更简单的:上传 .html 文件,里面写满钓鱼表单,因为 MEDIA_URL 和主站同域,Cookie 直接带过去。我自己的做法是强制 Content-Disposition: attachment,再单独用一个子域放用户上传的东西。

CSRF 保护经常被开发者自己关掉。@csrf_exempt 一加,接口是方便了,但浏览器里只要用户登录着,攻击者就能用 fetch 发跨站请求。有个金融类 App 的“修改邮箱”接口就是这么中招的——攻击者构造一个自动提交的表单,用户点开链接,邮箱就被换成了攻击者的。Django 的 CSRF token 默认在 Cookie 里叫 csrftoken,CSRF_COOKIE_HTTPONLY 设成 True 能防 XSS 读取,但很多人不知道这个配置项。

版本更新也容易被忽略。Django 2.2 的 django.utils.html.urlize 有个 XSS 漏洞,3.0 之前的 django.contrib.admin 存在开放重定向。我见过一个内部系统还在跑 1.11,Python 2.7 的环境,问就是“重构成本太高”。可攻击者不管这些,CVE 列表一拉,脚本一扫,拿下的就是这种老古董。

说句实在的,Django 本身的安全机制够用了,出问题基本是配置和用法上的疏忽。把 DEBUG 关掉,ALLOWED_HOSTS 写死域名,别碰原生 SQL,上传目录不给执行权限,CSRF 中间件别乱关,版本保持更新。这几条做到,能挡掉九成以上的自动化扫描。剩下的,就看有没有人盯着你的业务逻辑慢慢挖了。

    热门排行

    友情链接