同源政策
它是什么?
同源策略是浏览器之间标准化的安全措施。“起源”主要是指“域”。它可以防止不同的来源相互交互,以防止诸如跨站请求伪造之类的攻击。
CSRF 攻击如何运作?
浏览器允许网站以 cookie 的形式将信息存储在客户的计算机上。这些 cookie 附有一些信息,例如 cookie 的名称、创建时间、过期时间、设置 cookie 的人员等。cookie 看起来像这样:
Cookie: cookiename=chocolate; Domain=.bakery.com; Path=/ [// ;otherDdata]
所以这是一个巧克力饼干,应该可以从http://bakery.com及其所有子域访问。
此 cookie 可能包含一些敏感数据。在这种情况下,该数据是chocolate
...... 如您所见,高度敏感。
所以浏览器存储了这个cookie。每当用户向可以访问此 cookie 的域发出请求时,cookie 就会被发送到该域的服务器。快乐的服务器。
这是一件好事。服务器在客户端存储和检索信息的超酷方式。
但问题是这允许http://malicious-site.com在用户不知情的情况下将这些 cookie 发送到http://bakery.com !例如,考虑以下场景:
# malicious-site.com/attackpage
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://bakery.com/order/new?deliveryAddress="address of malicious user"');
xhr.send();
如果你访问恶意网站,上面的代码执行,并且没有同源策略,恶意用户会代表你下订单,并在他的地方下订单......你可能不喜欢这样.
发生这种情况是因为您的浏览器将您的巧克力 cookie 发送到http://bakery.com,这使http://bakery.com认为您在知情的情况下提出了新订单的请求。但你不是。
简单来说,这就是 CSRF 攻击。跨站点发出伪造请求。“跨站点请求伪造”。由于同源政策,它不会起作用。
同源策略如何解决这个问题?
它阻止恶意站点.com 向其他域发出请求。简单的。
换句话说,浏览器不允许任何站点向任何其他站点发出请求。它将防止不同来源通过此类请求(如 AJAX)相互交互。
但是,从其他主机(如图像、脚本、样式表、iframe、表单提交等)加载资源不受此限制。我们需要另一堵墙来保护我们的面包店免受恶意网站的攻击,使用CSRF 令牌。
CSRF 代币
如前所述,恶意站点仍然可以在不违反同源策略的情况下执行以下操作:
<img src='http://bakery.com/order/new?deliveryAddress="address of malicious user"'/>
并且浏览器将尝试从该 url 加载图像,从而导致对该 url 发送所有 cookie 的 GET 请求。为了阻止这种情况发生,我们需要一些服务器端保护。
基本上,我们将一个随机的、具有适当熵的唯一令牌附加到用户的会话中,将其存储在服务器上,并通过表单将其发送给客户端。提交表单时,客户端会将该令牌与请求一起发送,服务器会验证该令牌是否有效。
现在我们已经这样做了,恶意网站再次发送请求,它总是会失败,因为恶意网站没有可行的方法知道用户会话的令牌。
CORS
当需要跨站点请求时,可以绕过该策略。这称为CORS。跨域资源共享。
这是通过让“域”告诉浏览器冷静并允许此类请求来实现的。这个“告诉”的事情可以通过传递一个标题来完成。就像是:
Access-Control-Allow-Origin: //comma separated allowed origins list, or just *
因此,如果http://bakery.com将此标头传递给浏览器,并且创建对http://bakery.com的请求的页面存在于原始列表中,那么浏览器将放开请求以及 cookie .
有一些规则可以根据这些规则定义原点1。例如,同一个域的不同端口不是同一个源。因此,如果端口不同,浏览器可能会拒绝此请求。与往常一样,我们亲爱的 Internet Explorer 是个例外。IE 以相同的方式处理所有端口。这是非标准的,没有其他浏览器以这种方式运行。不要依赖这个。
JSONP
当 CORS 不是一个选项时,带有 Padding的 JSON 只是一种规避同源策略的方法。这是有风险的,也是不好的做法。避免使用这个。
该技术涉及的是向其他服务器发出请求,如下所示:
<script src="http://badbakery.com/jsonpurl?callback=cake"></script>
由于同源策略不会阻止这2 个请求,因此该请求的响应将被加载到页面中。
这个 url 很可能会响应 JSON 内容。但是仅仅在页面上包含 JSON 内容并没有帮助。当然,这会导致错误。因此http://badbakery.com接受一个回调参数,并修改 JSON 数据,将其包装在传递给回调参数的任何内容中发送。
所以与其返回,
{ user: "vuln", acc: "B4D455" }
这是无效的 JavaScript 抛出错误,它会返回,
cake({user: "vuln", acc:"B4D455"});
这是有效的 JavaScript,它会被执行,并且可能会根据cake
函数存储在某个地方,以便页面上的其余 JavaScript 可以使用数据。
这主要由 API 用于将数据发送到其他域。同样,这是一种不好的做法,可能有风险,应该严格避免。
为什么 JSONP 不好?
首先,它非常有限。如果请求失败,您将无法处理任何错误(至少不是以理智的方式)。您无法重试请求等。
它还要求您cake
在全局范围内拥有一个不是很好的功能。如果您需要使用不同的回调执行多个 JSONP 请求,请让厨师为您节省。这可以通过各种库的临时函数来解决,但仍然是一种骇人听闻的方式。
最后,您将在 DOM 中插入随机 JavaScript 代码。如果您不能 100% 确定远程服务会返回安全的蛋糕,那么您不能依赖这个。
参考
1. https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Definition_of_an_origin
2. https://www.w3.org/Security/wiki/Same_Origin_Policy#Details
其他值得一读
http://scarybeastsecurity.blogspot.dk/2009/12/generic-cross-browser-cross-domain.html
https://www.rfc-editor.org/rfc/rfc3986(对不起:p)
https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)