CVE-ID:CVE-2018-14574
漏洞类型:URL跳转
影响范围:1.11.0 <= version < 1.11.15 和 2.0.0 <= version < 2.0.8
当setting中配置了django.middleware.common.CommonMiddleware且APPEND_SLASH为True时漏洞就会触发,而这两个配置时默认存在的,而且APPEND_SLASH不用显示写在setting文件中的。CommonMiddleware是Django中一个通用中间件,实质上是一个类,位于site-packages/django/middleware/common.py,会执行一些HTTP请求的基础操作:
- Forbid access to User-Agents in settings.DISALLOWED_USER_AGENTS
- URL rewriting: Based on the APPEND_SLASH and PREPEND_WWW settings,
append missing slashes and/or prepends missing "www."s.
- If APPEND_SLASH is set and the initial URL doesn't end with a
slash, and it is not found in urlpatterns, form a new URL by
appending a slash at the end. If this new URL is found in
urlpatterns, return an HTTP redirect to this new URL; otherwise
process the initial URL as usual.
This behavior can be customized by subclassing CommonMiddleware and
overriding the response_redirect_class attribute.
- ETags: If the USE_ETAGS setting is set, ETags will be calculated from
the entire page content and Not Modified responses will be returned
appropriately. USE_ETAGS is deprecated in favor of
ConditionalGetMiddleware.
而漏洞就与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()函数
这个函数的作用就是get_full_path()函数给path末尾加上斜杠
返回的new_path就是//baidu.com/ ,然后在68行进入HttpResponseRedirectBase这个类,它是HTTP跳转的一个基类
虽然类的初始化函数里(409行)有对协议的检查,但是scheme根本就不存在,所以会跳过这个判断。
在往后就是正常的301跳转
双斜线是为了告诉浏览器这是绝对路径,否则就会跳转到http://127.0.0.1:8000/baidu.com/ 而不是baidu了。
修补方法就是加了一个编码函数,
对第二个/编码,这样就构不成绝对路径了
https://nvd.nist.gov/vuln/detail?vulnId=2018-14574
https://github.com/django/django/commit/6fffc3c6d420e44f4029d5643f38d00a39b08525#diff-1f8be0eae49a1bf37d52829eaeda6a4eR14