[CVE-2018-14574] Django Open redirect possibility in CommonMiddleware
今天在刷RSS的时候看到了Django发了个新版本,修了个CVE,然后简单的看了下。
先放上release note和github的commit。
https://www.djangoproject.com/weblog/2018/aug/01/security-releases/
https://github.com/django/django/commit/a656a681272f8f3734b6eb38e9a88aa0d91806f1
看描述是修复了一个CommonMiddleware+APPEND_SLASH选项的任意URL跳转,根据github上修改的几个文件,可以看出来,主要变动是在django/middleware/common.py
这个文件中,对获取到的path
进行了一次编码。
众所周知,漏洞中提到的这个APPEND_SLASH
的选项,默认为True,且默认没有在settings.py
中显示的设置。这个设置的作用也比较简单,当请求的URL在路由表中无法匹配时,并且请求的URL末尾不是以/
结尾的,那么Django会自动在请求的URL末尾添加一个/
,并且再次匹配路由表,然后进行正常的处理流程;
也就是说,在这个过程中,会发生一次跳转,那么这个任意URL跳转漏洞应当也是在这块出现的,我们新建一个Django项目,使用2.0.7
版本。
urls.py
from django.urls import path
from vuln.views import VulnView
urlpatterns = [
path("<path:jump_url>/", VulnView.as_view(), name="vuln_view"),
]
views.py
from django.views import View
from django.http import HttpResponse
class VulnView(View):
def get(self, request, jump_url):
return HttpResponse(jump_url)
然后我们在CommonMiddleware
这个类中的process_request
方法下断:
然后请求http://localhost:8000//lightless.me
,注意末尾不能加/
,调试的时候建议将浏览器的cache关掉,否则会影响我们调试。
向下走会遇到一个should_redirect_with_slash
方法,这个方法是用来判断上面提到过的逻辑:是否需要添加/
后重新匹配路由表,如果需要添加,会继续调用self.get_full_path_with_slash
方法,实际上就是对request.get_full_path
的一层封装。
然后我们会拿到处理过后的path//lightless.me/
,接着就会将这个path传给self.response_redirect_class
方法,这个实际上就是用来处理重定向的一个类。
跟进之后,会看到在这里设置了Response的Location属性为前面得到的path,并且设置了状态码为301
虽然这里会检查跳转目标URL的协议,但是并没有什么用,这里的scheme
不存在,自然是可以绕过这个限制,后面就是正常跳转流程。
让程序继续跑下去,回过来看浏览器,页面已经跳走了。
整个流程还是比较简单的,但是利用条件也比较苛刻,可能会在一些大型的CMS或其他的系统中出现吧,例如某些CMS会接管Django的路由并且使用自己的路由系统,感觉可能也不太常见。通常情况下我们的路由很有可能是写成这个样子:
path('vuln/<path:jump_url>/', VulnView.as_view(), name="vuln_view"),
很有可能中间还会有个路径,而不是直接就接收参数,这种情况下我目前还没有想到好的利用方法。
Crawlergo
Crawlergo
Crawlergo
CRLF-Header:CRLF-Value
'+(40920*40136)+'
Crawlergo%0d%0aCRLF-Header:CRLF-Value
Crawlergo\r\nCRLF-Header:CRLF-Value
Crawlergo
Crawlergo
Crawlergo
Crawlergo
Crawlergo
Crawlergo
Crawlergo
Crawlergo
Crawlergo
Crawlergo
Crawlergo
Crawlergo
Crawlergo
Crawlergo
Crawlergo
Crawlergo
Crawlergo