在在搞Django 1.3和Uploadify的整合时,被莫名其妙的302困扰,在苦思之后突然发现,原来Uploadify发送请求时是不会发送Cookie信息的。火急火燎地弄了个middleware来将POST中对应字段写到request.COOKIES去。这样一搞,302倒是ok了,但403倒跑了出来。使用抽插,哦不,抽查法找到是Csrf的验证问题,于是天真地把csrfmiddlewaretoken塞到POST里,可是403依旧。甚是火大。
只好乖乖地看源码,看看Django是如何做CSRF验证的。Django是在CsrfViewMiddleware中进行的相关验证,验证过程很简单,从Cookie中拿出token,然后从POST中拿出csrfmiddlewaretoken,然后块俩做一个字符匹配,就哦了。于是明白了,不就再传个cookie嘛,但突然一想,不对呀,csrfmiddlewaretoken的值就是从cookie里拿的,再传同一个值来做验证,这不是和没验证没啥区别么……
于是做了一个试验,结果确实如此,这下Django悲剧了……
实验项目可以在这个地址下载,运行runserver后,用curl来验证
直接GET,无障碍
curl http://127.0.0.1:8000
强制GET,无障碍
curl -G -d test=test http://127.0.0.1:8000
POST,403了,ms没问题?
curl -d test=test http://127.0.0.1:8000
POST,随便加上csrf,靠!!居然过了!!!
curl -d "test=test;csrfmiddlewaretoken=1" -b csrftoken=1 http://127.0.0.1:8000
归根结底,还是这个验证方法有问题,起码post中的token和cookie中的token是用secret_key做过变幻的,这样才能避免伪造,否则,神马都是浮云~~ 望天
P.S. 报bug去了,#15845。不知他们会采用我说的方法不⋯⋯
Updated: 呃,一般情况下大约是不会有问题的,因为这只是可以任意伪造csrf_token,但通常还有需要csrf保护的地方也会需要sessionid来作用户验证。这篇的问题就可以暂时忽略了。


原来是curl惹得祸
好吧,这其实不是CSRF的问题,但暴露了一种攻击方式,嗯
我也遇到这个问题了!
目前暂时用GET ,后端处理def 加上 装饰器@csrf_exempt。
展开回复(1)
CsrfViewMiddleware是不会检查GET的,所以没必要用csrf_exempt,两者用其一就行。
Jay一直关注你的博客, 能否放个友情链接,谢谢! 我的博客:http://2goo.info
谢谢了!
展开回复(1)
客气 :)
博主你理解错了,CSRF解决的不是灌水机、Bot之类的问题,CSRF主要是为了防止跨站请求。
因为HTTP请求默认都会带上Cookie,所以攻击者可以在自己的网站上创建一个隐藏的表单并且用JS偷偷提交,而这个偷偷提交的请求是自动带有被攻击站点有效Cookie的。
但是如果在Cookie里加一个每次登录都改变的csrf,并且在表单里加一个hidden域,提交时验证两者是否匹配,那么以上攻击就没法实现了,因为恶意网站无法读取你的Cookie(因为浏览器的同源策略),所以无法获得Cookie里的CSRF Token,无法伪造出csrf,POST就会失败,这样就不会产生安全问题。
如果还不懂的话,建议博主仔细研究一下csrf是什么意思。