漏洞介绍
Django是一个高级的Python Web框架,支持快速开发和简洁实用的设计。
Django 2.0.8和1.11.15版本之前存在一个任意URL跳转漏洞,当同时启用django.middleware.common.CommonMiddleware中间件和APPEND_SLASH设置时,如果项目中存在接受以斜杠结尾的任意路径的URL模式,攻击者可以构造恶意URL导致重定向到任意外部网站,从而可能导致钓鱼等攻击。
漏洞范围
1.11.0 <= Django< 1.11.15
2.0.0 <= Django < 2.0.8
漏洞靶场
使用vulhub的靶场:
vulhub-master/django/CVE-2018-14574
启动靶场环境:
1 | docker-compose up -d |
服务启动后,访问http://your-ip:8000即可查看到Django的登录页面。
漏洞原理
当setting中配置了django.middleware.common.CommonMiddleware且APPEND_SLASH为True时漏洞就会触发,而这两个配置时默认存在的,而且APPEND_SLASH不用显示写在setting文件中的。CommonMiddleware是Django中一个通用中间件,实质上是一个类,位于site-packages/django/middleware/common.py,会执行一些HTTP请求的基础操作:
1 | - Forbid access to User-Agents in settings.DISALLOWED_USER_AGENTS |
django/middleware/common.py#L20-L37
而漏洞就与URL rewriting有关:如果设置了APPEND_SLASH=True并且初始URL没有以斜杠结尾,并且在urlpatterns中找不到它,则通过在末尾附加斜杠来形成新的URL。如果在urlpatterns中找到此新URL,则将HTTP重定向返回到此新URL。换句话说就是对那些末尾没加/的url自动填补/然后重新发起请求。比如
但是当发起当发起类似这样的请求http://127.0.0.1:8000//baidu.com 程序就会进行设定的跳转,首先会执行process_request()函数,在61行进入get_full_path_with_slash()函数
django/middleware/common.py#L61
这个函数的作用就是get_full_path()函数给path末尾加上斜杠
django/middleware/common.py#L83-L102
返回的new_path就是//baidu.com/ ,然后在68行进入HttpResponseRedirectBase这个类,它是HTTP跳转的一个基类
django/middleware/common.py#L68
虽然类的初始化函数里(409行)有对协议的检查,但是scheme根本就不存在,所以会跳过这个判断。
django/http/response.py#L409
在往后就是正常的301跳转
双斜线是为了告诉浏览器这是绝对路径,否则就会跳转到http://127.0.0.1:8000/baidu.com/ 而不是baidu了。
漏洞复现
访问以下URL触发任意URL跳转漏洞:
1 | http://your-ip:8000//www.example.com |
服务器将重定向到//www.example.com/,浏览器会将其解释为绝对URL,从而实现对外部站点的重定向:
访问http://192.168.159.132:8000//baidu.com

返回301跳转码
参考
Django 任意url跳转漏洞(CVE-2018-14574)-CSDN博客
https://xz.aliyun.com/news/2939
https://github.com/vulhub/vulhub/blob/master/django/CVE-2018-14574/README.zh-cn.md