当前位置: 首页 > >

CSRF 跨站攻击

发布时间:

CSRF 跨站攻击


CSRF (Cross Site Request Forgrey).是一种网络的攻击方式,它在 2007 年曾被列为互联网 20 大安全隐患之一。



原理:
站内发送请求一般需要一个登陆了的标志。一般存储在cookies 中。这个cookies会存在浏览器中,而发送请求的时候都会带上这个cookies。hacker 无法拿到这个数据。但是可以通过发送请求都会带上cookies的这个特性,通过另外的网站转而调用需要的请求。这时候就能够成功。(只要cookies没有过期)。
通过这种方式hacker 无需获取cookies,只需要制作一个网站,在其相关cookies没有过期时让他去点击就可以进行危险的行为。


例子

http://bank.example/withdraw?account=bob&amount=1000000&for=bob2 可以使 Bob 把 1000000 的存款转到 bob2 的账号下。通常情况下,该请求发送到网站后,服务器会先验证该请求是否来自一个合法的 session,并且该 session 的用户 Bob 已经成功登陆。黑客 Mallory 自己在该银行也有账户,他知道上文中的 URL 可以把钱进行转帐操作。Mallory 可以自己发送一个请求给银行:http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory。但是这个请求来自 Mallory 而非 Bob,他不能通过安全认证,因此该请求不会起作用。这时,Mallory 想到使用 CSRF 的攻击方式,他先自己做一个网站,在网站中放入如下代码: src=”http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory ”,并且通过广告等诱使 Bob 来访问他的网站。当 Bob 访问该网站时,上述 url 就会从 Bob 的浏览器发向银行,而这个请求会附带 Bob 浏览器中的 cookie 一起发向银行服务器。大多数情况下,该请求会失败,因为他要求 Bob 的认证信息。但是,如果 Bob 当时恰巧刚访问他的银行后不久,他的浏览器与银行网站之间的 session 尚未过期,浏览器的 cookie 之中含有 Bob 的认证信息。这时,悲剧发生了,这个 url 请求就会得到响应,钱将从 Bob 的账号转移到 Mallory 的账号,而 Bob 当时毫不知情。等以后 Bob 发现账户钱少了,即使他去银行查询日志,他也只能发现确实有一个来自于他本人的合法请求转移了资金,没有任何被攻击的痕迹。而 Mallory 则可以拿到钱后逍遥法外。


防御

既然cookies 必须携带,那么就需要有一个方式来感知是从当前发出的请求来避免跨站的一个攻击。



http referer

表示是从哪个网站发出的请求。如果是浏览器一般限制了不允许修改。(个别有漏洞可以修改)。但是有些人认为带上referer有安全位图,没有添加。这样可能导致采取这种策略的网站把正常的请求给拒绝。并且如果是脚本攻击,可以随意的设置http referer的值,所以没有意义。


请求中添加token

为了达到hacker 不能伪造,需要在请求中带上不能伪造的信息。已知cookie 会被获取到,所以不能存在cookie中。那么就之梦放在form 或者a 请求中。



系统可以在添加 token 的时候增加一个判断,如果这个链接是链到自己本站的,就在后面添加 token,如果是通向外网则不加。不过,即使这个 csrftoken 不以参数的形式附加在请求之中,黑客的网站也同样可以通过 Referer 来得到这个 token 值以发动 CSRF 攻击。这也是一些用户喜欢手动关闭浏览器 Referer 功能的原因。



以上一段暂时不太清楚。


XMLHttpRequest

通过使用 XMLHttpRequest 对所有请求增加 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。但是为了使用该类需要重写前端。


Django csrf

Django的CSRF防御方法采用的是在请求中添加toke并验证方法,源码分析如下: 如果有form提交时,验证csrftoken,django在打开这个页面时就会将csrftoken存在cookie中,当用户提交表单时进行匹配,如果相同则证明是一个安全提交。 csrftoken的生成方式如下:


md5_constructor(“%s%s” % (randrange(0, _MAX_CSRF_KEY), settings.SECRET_KEY)).hexdigest()


设置csrftoken:


response.set_cookie(settings.CSRF_COOKIE_NAME, request.META[“CSRF_COOKIE”], max_age = 60 * 60 * 24 * 7 * 52, domain=settings.CSRF_COOKIE_DOMAIN)


csrftoken与cookie中的token比较:


if not constant_time_compare(request_csrf_token, csrf_token):


如果不一致返回403错误 注意:表单内必须加入csrf_token的tag,否则站内提交也会被阻止,除非添加@csrf_exempt装饰器


参考:
Django CSRF 原理分析



友情链接: