简体   繁体   English

使用跨域JavaScript调用防止CSRF

[英]Preventing CSRF with a cross-domain JavaScript call

I'd like to protect my site against cross-site request forgery . 我想保护我的网站免遭跨站点伪造 I'm trying to follow these recommendations , by sending a session-specific token along with all requests that need to be protected. 我正在尝试通过发送特定于会话的令牌以及所有需要保护的请求来遵循这些建议

The catch is that I have some requests that are designed to be called by third-party sites, on a different domain. 问题是,我有一些请求被设计为由不同域上的第三方站点调用。 Most of them use JSONP : they make a request to our server using a <script> tag, and the response is JavaScript code that calls a function on their page. 他们大多数使用JSONP :他们使用<script>标记向我们的服务器发出请求,并且响应是JavaScript代码,该代码调用其页面上的函数。

My question is, how to I pass the token in these requests? 我的问题是,如何在这些请求中传递令牌? It seems like the third-party site would need to know the token. 似乎第三方站点需要知道令牌。 I could provide another request that returns the token as JSON, but then untrusted sites could make the same request, get the token, and use it to forge requests to our server. 我可以提供另一个将令牌返回为JSON的请求,但是不受信任的站点可以发出相同的请求,获取令牌,然后将其用于伪造对我们服务器的请求。

Is there a better way to do this? 有一个更好的方法吗?

XSRF tokens are usually cookies on your domain that you generate. XSRF令牌通常是您生成的域上的cookie。 You really don't want to introduce a mechanism to allow other sites to set those. 您真的不想引入允许其他站点进行设置的机制。 Verifying that a message comes from a trusted party is better treated as a signature verification problem. 验证消息来自受信任方最好被视为签名验证问题。

You can have each partner site generate and keep a private/public signature key pair. 您可以让每个合作伙伴站点生成并保留一个私有/公共签名密钥对。 Then they can send you their public key. 然后他们可以向您发送其公共密钥。

They can then sign their messages to you. 然后,他们可以将其消息签名给您。

So their request would look like 所以他们的要求看起来像

 <script src="https://.../yourservice?partnerid=foobar&signedquerystring"></script>

and then you can signature check that the signed query string was properly signed using the public key you looked up by the key foobar . 然后您可以使用您通过键foobar查找的公钥来签名检查签名的查询字符串是否正确签名。

You now know to trust the request if it either has your XSRF token or it is properly signed using the private key of a partner you've established a relationship with. 现在,您将知道该请求是否具有您的XSRF令牌,或者已使用与您建立关系的合作伙伴的私钥正确签名的请求。

This won't stop someone who can observe a logged in user viewing the partner site from replaying the request, so the partner site and your script should both be loaded via a secure channel ( https ), just as you would with multiple-use XSRF tokens. 这不会阻止可以观察到登录用户查看合作伙伴站点的用户重播请求,因此,应该像使用多次使用XSRF一样,通过安全通道( https )加载合作伙伴站点和您的脚本。令牌。

The solution to this problem that I am using is to embed an IFRAME inside the UI of an external widget I am creating. 我正在使用的此问题的解决方案是将IFRAME嵌入到要创建的外部窗口小部件的UI内。 The only drawback here is the possibility of others using this iframe in a clickjacking attack. 唯一的缺点是其他人可能在点击劫持攻击中使用此iframe。 You could read about that here: https://security.stackexchange.com/questions/13341/security-issues-using-iframes . 您可以在这里阅读有关内容: https : //security.stackexchange.com/questions/13341/security-issues-using-iframes

I have the simplest solution to the JSONP CSRF problem, Add the "While(1);" 对于JSONP CSRF问题,我有最简单的解决方案,请添加“ While(1);”。 or "for(,,);" 或“ for(,,);” or throw "F*** U"; 或抛出“ F *** U”; in start of your json response data. 在您的json响应数据的开头。

Now Any JSONP request end up in a infinite loop. 现在,任何JSONP请求都将陷入无限循环。 Because you aren't using a JSONP request, you have the ability to modify the response by this code 由于您未使用JSONP请求,因此可以通过此代码修改响应

JSON.parse(this.responseText.slice("while(1);".length));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM