Django坑了我大半天的时间---CVE-2018-14574复现

Django < 2.0.8 任意URL跳转漏洞(CVE-2018-14574)

漏洞分析

Django是一个开放源代码的Web应用框架,由Python写成。

在其默认配置下,如果匹配上的URL路由中最后一位是/,而用户访问的时候没加/,Django默认会跳转到带/的请求中,(由配置项中的django.middleware.common.CommonMiddlewareAPPEND_SLASH来决定)。

在path开头为//example.com的情况下,Django没做处理,导致浏览器认为目的地址是绝对路径,最终造成任意URL跳转漏洞。

该漏洞利用条件是目标URLCONF中存在能匹配上//example.com的规则。

漏洞实现

进入Django的环境

docker -exec -it ID /bin/sh

查看/usr/src/app.py文件

这也就是上文提到的中间件

Django坑了我大半天的时间---CVE-2018-14574复现_第1张图片

进入/usr/local/lib/python3.7/site-packages/django/middleware查看common.py文件

Django坑了我大半天的时间---CVE-2018-14574复现_第2张图片

也就是这个中间件,一个类,类中有定义process_request,precess_response等方法

当我们发起请求时,会先进行检查

Django坑了我大半天的时间---CVE-2018-14574复现_第3张图片

当url不全时会调用request.get_full_path函数,进入get_full_path_with_slash

返回一个完整的路径,此时force_append_slash=True

Django坑了我大半天的时间---CVE-2018-14574复现_第4张图片

查看/usr/local/lib/python3.7/site-packages/django/http/request.py中的get_full_path函数

Django坑了我大半天的时间---CVE-2018-14574复现_第5张图片

当force_append_slash=True时会对path进行补全返回一个新的path,比如这里会输入

192.168.11.147:8000//baidu.com

返回新的path就是192.168.11.147:8000//baidu.com/

以//开头的外部URL将由浏览器翻译为协议,通过绝对URL会实现url跳转

Django坑了我大半天的时间---CVE-2018-14574复现_第6张图片

response_redirect_class函数是HTTP跳转的一个基类,图中HttpResponsePermanentRedirect是在/usr/local/lib/python3.7/site-packages/django/http/response.py实现301跳转的一个类

(我觉得再这样下去就超出我的能力范围了,response.py我猜又有大几百行我怕眼花…)

大概知晓漏洞成因之后,抓包对响应头分析一波,在Repeater模块中发送//baidu.com相应包中实现跳转

Django坑了我大半天的时间---CVE-2018-14574复现_第7张图片

此后我们改成//baidu.com/

Django坑了我大半天的时间---CVE-2018-14574复现_第8张图片

发现并没有进行跳转,个人浅显理解是因为不需要调用get_full_path函数

防御

  1. 确保该函数中的所有URL都是相对路径,即以单个“/”字符开头的路径
  2. 检查重定向过程中HTTP请求头部内的Referrer是否与域名匹配
  3. 增加一个编码函数使其不能构成绝对路径

参考文章

你可能感兴趣的:(漏洞复现,django,python,web,安全,漏洞复现)