术语

术语 解释 备注
跨域 两个 URL 的“协议+主机名+端口”3者只要有一个不一致 http://www.taobao.com/和https://www.taobao.com/
跨站 两个 URL 的 eTLD+1 不相同 a.github.io 和 b.github.io
eTLD effective top level domain (有效顶级域名) .com、.co.uk、.github.io
eTLD+1 有效顶级域名+二级域名 taobao.com
  1. 有效顶级域名,注册于 Mozilla 维护的公共后缀列表(Public Suffix List)中 https://publicsuffix.org/list/public_suffix_list.dat
  2. a.taobao.com和 www.b.taobao.com 是同站,a.github.io 和 b.github.io 是跨站,github.io 在公共后缀列表里,但 taobao.com 不在公共后缀列表里

为什么要有同源策略

同源策略:

浏览器的同源策略是为了限制CSRF攻击,因为我们有些场景确实需要,访问不同域名下的资源,所以需要跨域。

同源策略(Same Origin Policy)是一种约定,它是浏览器最核心最基本的安全功能。所谓的同源是指域名、协议、端口相同。不同源的客户端脚本在没有明确授权的情况下是不允许读写其他网站的资源

如在www.baidu.com的网页下 去访问www.taobao.com 这样则形成了跨域 那么浏览器则会限制响应数据(注意 这里是指限制访问响应的数据 而不是限制访问),也就是拿不到响应的数据,csdn.net域下的页面脚本文件无法拿到baidu.com下的cookies信息

同源策略的限制:

  1. Cookie、LocalStorage 和 IndexDB 会话存储无法读取。
  2. DOM 无法获得。
  3. AJAX 请求不能发送。

同源策略作用:

防止恶意网页可以获取其他网站的本地数据。

防止恶意网站iframe其他网站的时候,获取数据。

防止恶意网站在自已网站有访问其他网站的权利,以免通过cookie免登,拿到数据。

为什么能防csrf

  1. 上文提到不同源无法对cookie里面的数据进行操作访问,为了防止csrf攻击可以让前端把cookie中写入的token放到请求头中每次请求都带过来,然后服务端再对请求头里面的token进行校验。
  2. 因为不同源钓鱼网站拿不到支付宝的cookie里的信息那么钓鱼网站自然不能在请求头上加token这样也很完美的解决了csrf攻击!

csrf攻击的特点

  1. 请求是跨域的,可以看出请求是从恶意网站上发出的
  2. 通过 img, script 等标签来发起一个 GET 请求,因为这些标签不受同源策略的限制
  3. 发出的请求是身份认证后的

Django中csrf token验证原理

问题引入

在这里插入图片描述

解答

  1. django 第一次响应来自某个客户端的请求时,会在服务器端随机生成一个 token,把这个 token 放在 cookie 里。然后每次 POST 请求都会带上这个 token,这样就能避免被 CSRF 攻击。

  2. 官方文档中说到,检验token时,只比较secret是否和cookie中的secret值一样,而不是比较整个token。oken字符串的前32位是salt, 后面是加密后的token, 通过salt能解密出唯一的secret。django会验证表单中的token和cookie中token是否能解出同样的secret,secret一样则本次请求合法。

chatgpt——Q&A

1. django 的csrf可以防御csrf攻击,单前后端分离使用djangorestframework时,drf的as_view却将csrf防御全部屏蔽掉了,这是为什么?

在Django中,CSRF(Cross-Site Request Forgery,跨站请求伪造)保护是通过在表单中添加CSRF令牌来实现的。当浏览器向服务器发送请求时,Django会检查请求中是否包含正确的CSRF令牌。如果请求中没有正确的CSRF令牌,Django将拒绝该请求并返回错误。

然而,当使用Django Rest Framework(DRF)构建API时,通常会将前端(如React、Vue)和后端(使用DRF构建的API)分离。这时候,使用Django提供的默认CSRF保护机制可能会导致问题,因为前端无法自动添加CSRF令牌。

为了解决这个问题,DRF使用了一种不同的方式来保护API免受CSRF攻击,即通过使用SessionAuthentication来验证用户的身份,而不是使用Django的默认CSRF保护机制。这种方法的基本思想是将用户的身份信息保存在会话(Session)中,并在每个请求中发送会话ID。当服务器接收到请求时,它会检查会话ID并验证用户的身份。

但是,这也意味着DRF的as_view方法将默认的CSRF保护屏蔽掉了,因为DRF使用了自己的身份验证和保护机制。因此,如果你想使用DRF构建API,并保护免受CSRF攻击,你需要确保在使用DRF的情况下使用正确的身份验证和保护机制。通常,使用SessionAuthentication来验证用户身份并保护免受CSRF攻击是一个很好的选择。

PS: drf的原生校验组件我们在项目中也是不使用的,需要自己实现基于jwt的校验。

2. 如果攻击者获取到了正确的token是否可以伪造请求?

如果攻击者获得了正确的JWT Token,他们就可以使用该Token来伪装成已认证的用户向服务器发送请求。这种攻击被称为Token劫持或令牌盗用(Token Hijacking)。

为了防止Token劫持攻击,应该使用一些技术来加强JWT Token的安全性,包括:

  1. 设置Token的有效期。JWT Token应该有一个适当的过期时间,当Token过期后,攻击者将无法继续使用该Token。

  2. 避免将敏感信息存储在Token中。应该将敏感信息存储在服务器端,并仅将其在必要时编码到Token中。

  3. 在传输过程中使用HTTPS协议。HTTPS可以加密通信,防止Token在传输过程中被拦截和篡改。

  4. 使用密钥来保护Token的签名或加密信息。密钥应该足够长和随机,以防止攻击者通过暴力破解或字典攻击猜测出密钥。

  5. 对Token进行仅限于特定IP地址或用户代理的限制。这可以确保Token只能从特定的IP地址或用户代理进行访问,从而减少被盗用的风险。

  6. 在每个请求中进行Token验证。服务器应该在每个请求中验证Token的签名或加密信息,以确保Token是有效的。

以上措施可以帮助增强JWT Token的安全性,并减少Token劫持攻击的风险。

3. 对于auth请求返回来的token是存储在cookies中的,那么攻击者的伪造网站是否能获取到正规网站cookie中的token?

是的,如果攻击者能够伪造网站或者注入恶意脚本,他们可能会尝试获取存储在Cookie中的Token信息,从而进行令牌劫持或令牌泄露攻击。

攻击者可以使用一些技术来窃取存储在Cookie中的Token,包括:

  1. 使用XSS(跨站脚本攻击)来窃取Cookie信息。攻击者可以注入恶意脚本来窃取Cookie信息并将其发送到自己的服务器上。

  2. 使用CSRF(跨站请求伪造攻击)来伪造请求。攻击者可以在自己的网站上创建一个伪造的请求,然后诱使用户在登录到受害网站后点击该请求,从而将Token发送到攻击者的服务器上。

  3. 在公共WiFi网络中进行中间人攻击。攻击者可以在公共WiFi网络上拦截和篡改流量,从而窃取存储在Cookie中的Token信息。

为了减少令牌泄露的风险,可以采取以下措施:

  1. 使用HttpOnly标记来防止XSS攻击。HttpOnly标记可以防止JavaScript通过document.cookie获取到Cookie信息。

  2. 对Cookie进行加密。加密Cookie可以使攻击者无法理解其中的内容,从而减少令牌泄露的风险。

  3. 在Cookie中设置secure标记。设置secure标记可以确保Cookie只能通过HTTPS协议进行传输。

  4. 对请求进行CSRF防护。可以在服务器端生成CSRF Token,并将其嵌入到表单中,以防止攻击者使用伪造的请求来窃取Token。

  5. 避免在Cookie中存储敏感信息。敏感信息应该尽可能地存储在服务器端,而不是在Cookie中。

  6. 使用VPN或HTTPS协议访问网络。这可以确保网络连接的加密性,防止中间人攻击和窃取Cookie信息。

综上所述,采取以上措施可以帮助减少令牌泄露的风险,并保护用户的身份和隐私。

4. 跨域资源共享(cors)不是说,不同域之间无法获取cookie吗?

CORS(跨域资源共享)是一种安全机制,它确实可以限制浏览器在不同域之间共享敏感信息,例如Cookie。

具体来说,浏览器实现CORS时,会在发送跨域请求前,自动向目标服务器发送一个预检请求(OPTIONS请求),以确定该请求是否安全。如果目标服务器允许跨域请求,则浏览器可以在请求中包含相关的Cookie信息,否则浏览器将阻止Cookie的发送。

然而需要注意的是,CORS只能在浏览器层面上限制跨域请求。攻击者可以使用其他方式来绕过这种限制,例如在服务器端发起跨域请求或使用非浏览器环境进行请求。此时,即使CORS机制限制了Cookie的发送,攻击者仍然可能通过其他方式窃取Cookie信息。

因此,在设计安全的系统时,不能仅仅依赖于CORS机制来保护敏感信息。还需要采用其他措施,例如对Cookie进行加密、设置HTTPOnly标记等,来增加攻击者窃取Cookie信息的难度。

5. 现代浏览器基本都实现了cors,也就说用户在A网站登录获取token放到cookies中,然后在B网站(是个钓鱼网站)访问钓鱼请求,是无法携带A网站的token的?

是的,现代浏览器会在发送跨域请求前自动向目标服务器发送预检请求(OPTIONS请求),以确定该请求是否安全,从而限制了浏览器跨域请求中携带Cookie信息。如果目标服务器不允许跨域请求,则浏览器将阻止Cookie的发送,避免了跨站点请求伪造(CSRF)攻击等安全问题。

但是需要注意的是,这种限制仅仅是在浏览器层面上生效的,如果攻击者使用其他方式(例如在服务器端发起跨域请求)绕过了浏览器的限制,则依然可能窃取到用户的Cookie信息,造成安全威胁。因此,在开发时应该采取多种措施,例如限制Cookie的作用域、使用安全的传输协议(如HTTPS)、对Cookie进行加密等,来保护用户的安全。

6. 如果目标服务器允许跨域呢? 是不是cookies就在A和B之间共享了?

如果目标服务器允许跨域请求,并且在响应中设置了Access-Control-Allow-Credentials头部并将其值设置为true,浏览器就会在跨域请求中携带源站点的Cookie信息,从而实现在A和B之间共享Cookie。

但是需要注意的是,仅仅依靠跨域请求的限制是不够的,因为攻击者可能通过其他手段窃取到用户的Cookie信息,例如使用钓鱼网站欺骗用户输入用户名和密码等敏感信息,从而获取用户的Cookie。因此,需要采取其他安全措施,例如使用HTTPS协议传输Cookie、将Cookie设置为HttpOnly等,来增加攻击者窃取Cookie信息的难度,保护用户的安全。

7. django-cors-middleware库中的跨域配置,Access-Control-Allow-Credentials一般不会设置,是否默认为false?

是的,**django-cors-middleware 库中的跨域配置默认是不开启 Access-Control-Allow-Credentials 的,**也就是默认为 false。如果需要在跨域请求中携带 Cookie,需要将 CORS_ALLOW_CREDENTIALS 设置为 True,并在客户端请求时设置 withCredentials 为 true,以便在请求头中携带 Cookie。

8. 前后端分离携带cookies显然没有什么用。 所以,cookies仅仅用于前端js存取token的地方,从这个角度来看token+cors是可以防御csrf的吗?

是的,前后端分离下,由于浏览器的同源策略限制,无法在跨域请求中携带 Cookie。因此,前端通常会将 token 存储在本地(如 LocalStorage 或 SessionStorage)中,并在每次发送跨域请求时在请求头中携带该 token。同时,服务端可以通过 CORS 配置限制跨域访问,从而防止 CSRF 攻击。这种方式称为 token + CORS 防御 CSRF 攻击,已经成为现代 web 应用程序中广泛使用的方式之一。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐