Re: widget example of CORS and UMP
On Fri, 14 May 2010 03:40:12 +0200, Dirk Pranke dpra...@chromium.org wrote: Exactly, so the off-domain IFRAME is the only option here. iframe srcdoc=... sandbox=allow-scripts is an alternative solution, if you want everything in the same document. -- Anne van Kesteren http://annevankesteren.nl/
Re: widget example of CORS and UMP
On May 14, 2010, at 1:17 AM, Anne van Kesteren wrote: On Fri, 14 May 2010 03:40:12 +0200, Dirk Pranke dpra...@chromium.org wrote: Exactly, so the off-domain IFRAME is the only option here. iframe srcdoc=... sandbox=allow-scripts is an alternative solution, if you want everything in the same document. That's right, the new iframe features in HTML5 will make it easier and more robust to do the off-domain iframe pattern. But I'm not sure srcdoc= is terribly useful in this case, because it's unlikely you will want the markup for all of the user's gadgets to be served inline in the main gadget host document. That doesn't seem like a good fit for the idea that the user would dynamically add/remove/reposition their gadgets. Regards, Maciej
Re: widget example of CORS and UMP
On Thu, May 13, 2010 at 7:53 PM, Ian Hickson i...@hixie.ch wrote: On Thu, 13 May 2010, Dirk Pranke wrote: The initial, insecure CORS solution is straightforward ... a gadget running on My Yahoo! sends an XHR with the users' credentials to http://finance.yahoo.com/api/v1/my_portfolio; and gets some JSON back. If I understand this right, you are saying that the user visits my.yahoo.com, and that page does an XHR to finance.yahoo.com, right? Yes. One interesting aspect of the CORS solution is that there is no way for the CORS-based gadget to get another user's data; it is simply not possible to request it, since a different set of cookies cannot be included in the request. The CORS solution requires you to believe in the security of proper cookie handling. With an HttpOnly cookie, cookies can be handled pretty safely but I imagine all of us are fairly aware that cookies get exposed all the time and hence this is hardly a perfect solution, maybe just good enough. One could also observe that with the naive implementation of the CORS API, *any* site could trivially fetch the user's portfolio data, which is presumably not desirable, and so Yahoo! Finance would also need to check the Origin: header. Actually it just needs to send back a header saying that only my.yahoo.com is allowed to read it, and the client will take care of it. True, with a trusted client (which is generally what we're assuming). And an untrusted client could of course forge the Origin header. Now suppose that My Yahoo! allows the user to install third-party gadgets. Suddenly neither Yahoo! Finance nor the browser can distinguish a safe request from a trusted gadget from an unsafe request from an untrusted gadget. If my.yahoo.com is running _untrusted_ script in the context of my.yahoo.com, then forget XHR -- the game is already over long before we get to CORS. For example, the script could do a convincing phishing attack trivially, get the user's credentials, and then send them to the attacker for use offline. UMP or CORS are irrelevant here. If you want to run untrusted script, you can use iframe sandbox, and then CORS is neutralised (since the Origin is unguessable and unforgable), which seems to me to be what we want in that scenario. True. -- Dirk
Re: widget example of CORS and UMP
On Fri, May 14, 2010 at 1:15 AM, Maciej Stachowiak m...@apple.com wrote: OK, so there's two vulnerability scenarios: Actually, there is at least one other kind of vulnerability in the CORS design that has not been mentioned by anyone yet and that does not require XSS or untrusted code. Before I describe the attack, I want to remind everyone that the purpose of this particular scenario was to study the usability of CORS and UMP in a benign situation. This example only has a page from Yahoo talking to servers also operated by Yahoo. There are also no side-effects in this example; it's purely a data presentation example. Given that CORS and UMP are new protocols and that this is the most benign scenario we can conjure, I think it's fair to expect a solution with strong security properties. It should be damning if the solution to this very simple scenario introduces complex security problems. First I'll explain a concrete attack against the concrete example, and then I'll generalize it to explain why we should expect this problem to be recurring. The CORS solution to the scenario creates a widely known URL, http://finance.yahoo.com/api/v1/my_portfolio;, that is treated specially when the request happens to come from the my.yahoo.com origin. If you have tunnel vision on only the portfolio widget, then you might see no problem, but there are also other pages with other content on the my.yahoo.com domain. What happens if they make a request to this same URL, could something unexpected and wrong happen? Let's say myYahoo also has a page that fetches the HotTrade of the Day and posts its current price to my public activity stream, letting my friends know what investment I'm researching at the moment. The code for this content is audited by Yahoo and is not malicious. The HotTrade of the day can be on any market in the world and for anything. It might be hog futures in China or rice in Chicago. The page is used by momentum traders who just want to invest in anything that's moving quickly. Since no site lists the price of everything that can be traded, HotStocks returns the URL to GET the current price. The page content was created by a trading firm that wants to boost trades and attract new customers interested in trading on all of the world's markets. The page content makes the following requests: GET http://hottrades.foo/hotnow HTTP/1.0 Origin: my.yahoo.com HTTP/1.0 200 OK Content-Type: text/plain http://finance.yahoo.com/stock/goog/instaprice and then: GET http://finance.yahoo.com/stock/goog/instaprice HTTP/1.0 Origin: my.yahoo.com HTTP/1.0 200 OK Content-Type: text/plain 510.88 and then: POST http://my.yahoo.com/stream/append HTTP/1.0 Origin: my.yahoo.com Content-Type: text/plain I got my tip at 510.88. Find your price at: http://finance.yahoo.com/stock/goog/instaprice HTTP/1.0 204 OK Later, an attacker causes an unexpected URL to get into the HotTrades tip stream, resulting in the my.yahoo.com page doing the following: GET http://hottrades.foo/hotnow HTTP/1.0 Origin: my.yahoo.com HTTP/1.0 200 OK Content-Type: text/plain http://finance.yahoo.com/api/v1/portfolio/mine and then: GET http://finance.yahoo.com/api/v1/portfolio/mine HTTP/1.0 Origin: my.yahoo.com HTTP/1.0 200 OK Content-Type: application/json { /* all my portfolio data */ } and then: POST http://my.yahoo.com/stream/append HTTP/1.0 Origin: my.yahoo.com Content-Type: text/plain I got my tip at { /* all my portfolio data */ }. Find your price at: http://finance.yahoo.com/api/v1/portfolio/mine HTTP/1.0 204 OK If the Yahoo Finance portfolio was designed to use UMP instead of CORS, this hack would not compromise any private portfolio data since the attacker doesn't know the unguessable secret for anyone's private portfolio. The fundamental problem with the CORS design is that it attaches ambient permission to a well-known URL, the portfolio URL, so code that thinks it is just fetching public data might inadvertently fetch private data and reveal it. What URLs refer to private data versus public data is unknowable by the web content. Any content that fetches public data and then publishes a report on it could fall victim to this kind of attack in a CORS world. For example, earlier Nathan was interested in building a client-side web app that fetched Semantic Web data from a variety of sources, computed on it and produced a result. This app could very easily fall victim to this kind of Confused Deputy attack in a CORS world. How is the app to know which URLs it accesses have ambient permission attached to them that results in private data being returned? In an UMP world, the app can fetch data without attaching any credentials, so knows that anything that comes back must not be user private data. Considered only in isolation, the CORS solution might seem simple and secure[1]. When you consider the effect this code has on the rest of the origin and all the other code running on that origin, it clearly not secure. How is every
Re: widget example of CORS and UMP
On Fri, May 14, 2010 at 1:15 AM, Maciej Stachowiak m...@apple.com wrote: On May 13, 2010, at 6:40 PM, Dirk Pranke wrote: On Thu, May 13, 2010 at 6:13 PM, Maciej Stachowiak m...@apple.com wrote: ; you're right. If you don't run the code in an off-domain iframe or through a sanitizer like Caja, then everything on your site is vulnerable, not just resources protected via CORS. Using different-origin iframes with postMessage to communicate to the container seems like a fine solution for third-party gadgets. What goal is it defeating? Why would embedding gadgets inline without a frame be a goal? One could argue that maintaining off-domain iframes is a hack, or is a maintenance burden. You are correct of course that if you don't do either, you are vulnerable. Hack: not sure why it would be a hack. Embedding self-contained pieces of interactive content is *exactly* what iframes are designed for. The case where using iframes is a bit of ahack (in my opinion) is when you use an invisible iframe as a way to implement a cross-site data API, where visual embedding is not an issue. I think the idea of running untrusted JavaScript code from your own origin is terrifying, no matter how much you have tried to verify and restrict it. So even if I were using a Caja-style tool, I would still want to put the untrusted content in an off-domain iframe. Maintenance burden: I don't see that either. You could either host the iframe content on the domain of the gadget provider, in which case it reduces burden on the hosting site, or else it's easy to support an unbounded number of subdomain hostnames from a single server. Wheres the burden? Speaking from the viewpoint of a (fairly naive) content developer, it still seems like a hassle, but you're right that it's not much of one. And, as others have pointed out the sandbox attribute in HTML 5 makes this pretty painless (as well as making the intent obvious). At any rate, I grant that best practice would probably be to run any third-party code in a sandboxed iframe unless you really needed to not do that. Alternately, tools like Caja would block all use of XHR other than the anonymous kind. Exactly, so the off-domain IFRAME is the only option here. I'm not following you. Wrapping untrusted third-party widgets with Caja would not prevent my.yahoo.com from doing XHR on its own behalf. I guess it is I who am not following you. Why is that an issue? Even if non-cajoled code is doing credentialled XHRs on the page, the cajoled code can't make use of that fact. Thus, any of the reasonably secure ways to embed a third-party widget would not be vulnerable. What about the UMP-based solution; is it vulnerable? If the page containing the third-party gadget does not also contain the Yahoo!-provided portfolio gadget, then the $UNGUESSABLE_ID is not easily obtained, and so, not really. Actually, if any page served off of my.yahoo.com contains $UNGUESSABLE_ID, and the widget is embedded on the My Yahoo origin and not protected with a tool like Cja, then the third-party gadget can trivially get the unguessable ID. It doesn't even have to use it right away while the My Yahoo site is embedding widgets in an insecure way - it can exfiltrate it for later use at the time and place of its choosing. True. I did not consider this interestingly different, but in retrospect I was perhaps wrong. It makes it more clear why tools like Caja have to restrict the networking that Cajoled content is allowed to do. This is the main risk of UMP compared to CORS. Because secret tokens are the only security tool you have, you have the problem of maintaining confidentiality of a shared secret. If that shared secret is embedded in Web pages you serve, and/or embedded in a URL, that is hard to do. Agreed. In this particular use case, protecting that URL is probably not difficult, but it is a general problem. Why do you think so? URLs tend to leak. Browsers store them all over and do not generally treat them like secure information. Users share them freely. If you want to keep something secret, the last thing you want to do is put it in a URL. If I were designing a secret token based defense, at minimum I would use POST and put the secret token in the POST body instead of in the URL. While it is true that users share URLs freely, they don't tend to share URLs that aren't trivially exposed to them (in the URL bar, when you hover over a link). There are plenty of ways to create the URL that a regular user will never see. In my experience, they are a fairly safe way of protecting confidentiality if used properly by page authors. Although, I do not want to downplay this concern too much. There are also more subtle risks to shared secrets. If you are creating your secrets with a bad random number generator, then they will not in fact be unguessable and you have a huge vulnerability. Even security experts can make this mistake, here is an
Re: widget example of CORS and UMP
On Fri, May 14, 2010 at 1:17 AM, Anne van Kesteren ann...@opera.com wrote: On Fri, 14 May 2010 03:40:12 +0200, Dirk Pranke dpra...@chromium.org wrote: Exactly, so the off-domain IFRAME is the only option here. iframe srcdoc=... sandbox=allow-scripts is an alternative solution, if you want everything in the same document. HTML 5 to the rescue! -- Dirk
Re: widget example of CORS and UMP
On Fri, May 14, 2010 at 11:00 AM, Dirk Pranke dpra...@chromium.org wrote: On Fri, May 14, 2010 at 1:15 AM, Maciej Stachowiak m...@apple.com wrote: There are also more subtle risks to shared secrets. If you are creating your secrets with a bad random number generator, then they will not in fact be unguessable and you have a huge vulnerability. Even security experts can make this mistake, here is an example that impacted a huge number of people: http://www.debian.org/security/2008/dsa-1571. Sure. Is someone claiming that the CORS cookie solution does not require use of a random number generator? What's in the cookie and where did it come from? Access to a good random number generator is a requirement for either solution and so is not relevant to this discussion. --Tyler -- Waterken News: Capability security on the Web http://waterken.sourceforge.net/recent.html
Re: widget example of CORS and UMP
On Fri, May 14, 2010 at 10:18 AM, Tyler Close tyler.cl...@gmail.com wrote: On Fri, May 14, 2010 at 1:15 AM, Maciej Stachowiak m...@apple.com wrote: OK, so there's two vulnerability scenarios: Actually, there is at least one other kind of vulnerability in the CORS design that has not been mentioned by anyone yet and that does not require XSS or untrusted code. Before I describe the attack, I want to remind everyone that the purpose of this particular scenario was to study the usability of CORS and UMP in a benign situation. This example only has a page from Yahoo talking to servers also operated by Yahoo. There are also no side-effects in this example; it's purely a data presentation example. Given that CORS and UMP are new protocols and that this is the most benign scenario we can conjure, I think it's fair to expect a solution with strong security properties. It should be damning if the solution to this very simple scenario introduces complex security problems. We are talking about enabling a class of functionality (cross-origin messaging) that isn't currently possible on the web. Obviously if it is possible to do so securely and easily, that's a good thing. If that is not possible, and the options are to enable things that have relative degrees of security or ease of use, then it becomes much more debatable. Damning is a strong word to use in this situation, especially since I think most people would see the interchange between Maciej and I that neither solution (CORS or UMP) makes things trivially securable. Another conclusion could be that doing this stuff is just hard. First I'll explain a concrete attack against the concrete example, and then I'll generalize it to explain why we should expect this problem to be recurring. The CORS solution to the scenario creates a widely known URL, http://finance.yahoo.com/api/v1/my_portfolio;, that is treated specially when the request happens to come from the my.yahoo.com origin. If you have tunnel vision on only the portfolio widget, then you might see no problem, but there are also other pages with other content on the my.yahoo.com domain. What happens if they make a request to this same URL, could something unexpected and wrong happen? Let's say myYahoo also has a page that fetches the HotTrade of the Day and posts its current price to my public activity stream, letting my friends know what investment I'm researching at the moment. The code for this content is audited by Yahoo and is not malicious. The HotTrade of the day can be on any market in the world and for anything. It might be hog futures in China or rice in Chicago. The page is used by momentum traders who just want to invest in anything that's moving quickly. Since no site lists the price of everything that can be traded, HotStocks returns the URL to GET the current price. The page content was created by a trading firm that wants to boost trades and attract new customers interested in trading on all of the world's markets. The page content makes the following requests: GET http://hottrades.foo/hotnow HTTP/1.0 Origin: my.yahoo.com HTTP/1.0 200 OK Content-Type: text/plain http://finance.yahoo.com/stock/goog/instaprice and then: GET http://finance.yahoo.com/stock/goog/instaprice HTTP/1.0 Origin: my.yahoo.com HTTP/1.0 200 OK Content-Type: text/plain 510.88 and then: POST http://my.yahoo.com/stream/append HTTP/1.0 Origin: my.yahoo.com Content-Type: text/plain I got my tip at 510.88. Find your price at: http://finance.yahoo.com/stock/goog/instaprice HTTP/1.0 204 OK Later, an attacker causes an unexpected URL to get into the HotTrades tip stream, resulting in the my.yahoo.com page doing the following: GET http://hottrades.foo/hotnow HTTP/1.0 Origin: my.yahoo.com HTTP/1.0 200 OK Content-Type: text/plain http://finance.yahoo.com/api/v1/portfolio/mine and then: GET http://finance.yahoo.com/api/v1/portfolio/mine HTTP/1.0 Origin: my.yahoo.com HTTP/1.0 200 OK Content-Type: application/json { /* all my portfolio data */ } and then: POST http://my.yahoo.com/stream/append HTTP/1.0 Origin: my.yahoo.com Content-Type: text/plain I got my tip at { /* all my portfolio data */ }. Find your price at: http://finance.yahoo.com/api/v1/portfolio/mine HTTP/1.0 204 OK If the Yahoo Finance portfolio was designed to use UMP instead of CORS, this hack would not compromise any private portfolio data since the attacker doesn't know the unguessable secret for anyone's private portfolio. If the code had been audited, then it is reasonable to assume that someone would have caught that allowing the HotTrades service to tell the user to fetch *any url at all* was a bad idea, and the API should have been restricted to GET http://finance.yahoo.com/stock/%s/instaprice; instead of GET %s. This is also what Maciej said in his Don't Be a Deputy Slides - Guarantee that requests on behalf of a third party look different than your
Re: widget example of CORS and UMP
On Fri, May 14, 2010 at 12:00 PM, Tyler Close tyler.cl...@gmail.com wrote: On Fri, May 14, 2010 at 11:27 AM, Dirk Pranke dpra...@chromium.org wrote: You are correct that it is possible to use CORS unsafely. It is possible to use UMP unsafely, Again, that is broken logic. It is possible to write unsafe code in C++, but it is also possible to write unsafe code in Java, so there's no security difference between the two languages. Please, this illogical argument needs to die. This feels like a legal proceeding. Taken out of context, this sounds illogical, in the context of the rest of the paragraph Dirk's point makes perfect sense. In the same way that CORS has security problems, so does UMP. For example, I don't understand how UMP can ever work with GET requests. Specifically, how do you deal with users sharing URLs with malicious parties? Or is that not considered a problem? Ojan
Re: widget example of CORS and UMP
On Fri, May 14, 2010 at 12:00 PM, Tyler Close tyler.cl...@gmail.com wrote: On Fri, May 14, 2010 at 11:27 AM, Dirk Pranke dpra...@chromium.org wrote: On Fri, May 14, 2010 at 10:18 AM, Tyler Close tyler.cl...@gmail.com wrote: On Fri, May 14, 2010 at 1:15 AM, Maciej Stachowiak m...@apple.com wrote: OK, so there's two vulnerability scenarios: Actually, there is at least one other kind of vulnerability in the CORS design that has not been mentioned by anyone yet and that does not require XSS or untrusted code. Before I describe the attack, I want to remind everyone that the purpose of this particular scenario was to study the usability of CORS and UMP in a benign situation. This example only has a page from Yahoo talking to servers also operated by Yahoo. There are also no side-effects in this example; it's purely a data presentation example. Given that CORS and UMP are new protocols and that this is the most benign scenario we can conjure, I think it's fair to expect a solution with strong security properties. It should be damning if the solution to this very simple scenario introduces complex security problems. We are talking about enabling a class of functionality (cross-origin messaging) that isn't currently possible on the web. Obviously if it is possible to do so securely and easily, that's a good thing. If that is not possible, and the options are to enable things that have relative degrees of security or ease of use, then it becomes much more debatable. Damning is a strong word to use in this situation, If the introduced security problems are complex and therefore hard or infeasible to solve, then damning is the right word. If the simple, benign scenario is made infeasible, that's damning. especially since I think most people would see the interchange between Maciej and I that neither solution (CORS or UMP) makes things trivially securable. Another conclusion could be that doing this stuff is just hard. There's a big difference between trivially and infeasible. What are the issues with UMP where we cannot provide concrete guidance to developers? As I've shown, there are hard unknowns in the CORS solution. You've shown that there are cases where CORS is not secure. I don't know that I would agree with your assessment that you've shown that there are hard unknowns. As Maciej has shown, simply saying make sure the URL can't be easily obtained is not that easy. If the Yahoo Finance portfolio was designed to use UMP instead of CORS, this hack would not compromise any private portfolio data since the attacker doesn't know the unguessable secret for anyone's private portfolio. If the code had been audited, then it is reasonable to assume that someone would have caught that allowing the HotTrades service to tell the user to fetch *any url at all* was a bad idea, and the API should have been restricted to GET http://finance.yahoo.com/stock/%s/instaprice; instead of GET %s. You've changed the scenario so that now HotTrades can only happen on Yahoo listed securities, instead of those listed on any exchange in the world. You have to allow fetching of any URL to make the application work. If that is true, then a reasonable audit would not allow that app to run on my.yahoo.com, because of the dangers involved. A possible CORS solution is to check that the URL does not refer back to a user private resource on my.yahoo.com and so do a check on the domain in the URL from HotTrades. However, now you have to wonder about other domains that accept cross-domain requests from my.yahoo.com, such as finance.yahoo.com. How do you list all other domains that might be giving special cross-domain access to my.yahoo.com? You can't; it's an unbounded list that is not even under the control of my.yahoo.com. This is also what Maciej said in his Don't Be a Deputy Slides - Guarantee that requests on behalf of a third party look different than your own. How do I make a GET request for public data look different? I look forward to seeing DBAD explained in greater depth. I am completely unconvinced by what has been presented to date. If it is not possible to deploy an app with the level of distinction possible, then you don't deploy it. You are correct that it is possible to use CORS unsafely. It is possible to use UMP unsafely, Again, that is broken logic. It is possible to write unsafe code in C++, but it is also possible to write unsafe code in Java, so there's no security difference between the two languages. Please, this illogical argument needs to die. I did not say that they were the same. since - as others have expressed - everything depends on the URL being unguessable. or putting an unguessable token somewhere else in the request. In CORS, everything depends on the cookie being unguessable and confidential. Adam has shown how hard that is. True, and yet people use it all the time to provide a good enough level of security.
Re: widget example of CORS and UMP
On Fri, May 14, 2010 at 12:27 PM, Tyler Close tyler.cl...@gmail.com wrote: On Fri, May 14, 2010 at 12:20 PM, Ojan Vafai o...@chromium.org wrote: On Fri, May 14, 2010 at 12:00 PM, Tyler Close tyler.cl...@gmail.com wrote: On Fri, May 14, 2010 at 11:27 AM, Dirk Pranke dpra...@chromium.org wrote: You are correct that it is possible to use CORS unsafely. It is possible to use UMP unsafely, Again, that is broken logic. It is possible to write unsafe code in C++, but it is also possible to write unsafe code in Java, so there's no security difference between the two languages. Please, this illogical argument needs to die. This feels like a legal proceeding. Taken out of context, this sounds illogical, in the context of the rest of the paragraph Dirk's point makes perfect sense. My email included all of Dirk's text. I didn't remove it from context. I don't think it makes any sense, even in context. In the same way that CORS has security problems, so does UMP. No, not in the same way. The security issues are different in nature and severity. You can't just say there exist problems in both, so they're equivalent. That's not sensible. Ojan said in the same way, not me, and I did not say that they were equivalent. I agree that the security issues are different in nature. Your assessment of the relative severity of the two problems differs from others' assessments. At this point, I think this thread has run its course, unless there are further specific criticisms against the example I gave. I think the important takeaway is that as long as the two sites are only running trusted code (i.e., no third party gadgets), CORS met the intended use case securely. As soon as a third party was introduced, the potential for confused deputies arose and life got a whole lot more complicated. -- Dirk
Re: widget example of CORS and UMP
On Fri, May 14, 2010 at 12:27 PM, Dirk Pranke dpra...@chromium.org wrote: On Fri, May 14, 2010 at 12:00 PM, Tyler Close tyler.cl...@gmail.com wrote: On Fri, May 14, 2010 at 11:27 AM, Dirk Pranke dpra...@chromium.org wrote: On Fri, May 14, 2010 at 10:18 AM, Tyler Close tyler.cl...@gmail.com wrote: On Fri, May 14, 2010 at 1:15 AM, Maciej Stachowiak m...@apple.com wrote: OK, so there's two vulnerability scenarios: Actually, there is at least one other kind of vulnerability in the CORS design that has not been mentioned by anyone yet and that does not require XSS or untrusted code. Before I describe the attack, I want to remind everyone that the purpose of this particular scenario was to study the usability of CORS and UMP in a benign situation. This example only has a page from Yahoo talking to servers also operated by Yahoo. There are also no side-effects in this example; it's purely a data presentation example. Given that CORS and UMP are new protocols and that this is the most benign scenario we can conjure, I think it's fair to expect a solution with strong security properties. It should be damning if the solution to this very simple scenario introduces complex security problems. We are talking about enabling a class of functionality (cross-origin messaging) that isn't currently possible on the web. Obviously if it is possible to do so securely and easily, that's a good thing. If that is not possible, and the options are to enable things that have relative degrees of security or ease of use, then it becomes much more debatable. Damning is a strong word to use in this situation, If the introduced security problems are complex and therefore hard or infeasible to solve, then damning is the right word. If the simple, benign scenario is made infeasible, that's damning. especially since I think most people would see the interchange between Maciej and I that neither solution (CORS or UMP) makes things trivially securable. Another conclusion could be that doing this stuff is just hard. There's a big difference between trivially and infeasible. What are the issues with UMP where we cannot provide concrete guidance to developers? As I've shown, there are hard unknowns in the CORS solution. You've shown that there are cases where CORS is not secure. I don't know that I would agree with your assessment that you've shown that there are hard unknowns. Further down in this email, you punt on my example, saying that it can't be deployed. If there are classes of applications that CORS cannot address, and these classes are important, then there are hard unknowns in CORS. For example, will the Security Considerations section of CORS have to say: It is not safe in CORS to make a GET request for public data using a URL obtained from a possibly malicious party. Validating the URL requires global knowledge of all origins that might grant special access to the requestor's origin, and so return private user data. As Maciej has shown, simply saying make sure the URL can't be easily obtained is not that easy. I saw him assert that. I didn't see him show that. What are the pitfalls that have not been addressed in the UMP spec? If the Yahoo Finance portfolio was designed to use UMP instead of CORS, this hack would not compromise any private portfolio data since the attacker doesn't know the unguessable secret for anyone's private portfolio. If the code had been audited, then it is reasonable to assume that someone would have caught that allowing the HotTrades service to tell the user to fetch *any url at all* was a bad idea, and the API should have been restricted to GET http://finance.yahoo.com/stock/%s/instaprice; instead of GET %s. You've changed the scenario so that now HotTrades can only happen on Yahoo listed securities, instead of those listed on any exchange in the world. You have to allow fetching of any URL to make the application work. If that is true, then a reasonable audit would not allow that app to run on my.yahoo.com, because of the dangers involved. Or, a reasonable audit could say: that's a fine app, so long as you're using UMP. If CORS requires the app to be rejected, that's a failure for CORS and this WG. I see the WG's role here as defining a protocol that enables applications. Saying don't do that, as has become popular of late on this list, is failure. A possible CORS solution is to check that the URL does not refer back to a user private resource on my.yahoo.com and so do a check on the domain in the URL from HotTrades. However, now you have to wonder about other domains that accept cross-domain requests from my.yahoo.com, such as finance.yahoo.com. How do you list all other domains that might be giving special cross-domain access to my.yahoo.com? You can't; it's an unbounded list that is not even under the control of my.yahoo.com. This is also what Maciej said in his Don't Be a Deputy Slides - Guarantee that requests on
Re: widget example of CORS and UMP
On Fri, May 14, 2010 at 1:44 PM, Tyler Close tyler.cl...@gmail.com wrote: On Fri, May 14, 2010 at 12:27 PM, Dirk Pranke dpra...@chromium.org wrote: On Fri, May 14, 2010 at 12:00 PM, Tyler Close tyler.cl...@gmail.com wrote: On Fri, May 14, 2010 at 11:27 AM, Dirk Pranke dpra...@chromium.org wrote: On Fri, May 14, 2010 at 10:18 AM, Tyler Close tyler.cl...@gmail.com wrote: On Fri, May 14, 2010 at 1:15 AM, Maciej Stachowiak m...@apple.com wrote: OK, so there's two vulnerability scenarios: Actually, there is at least one other kind of vulnerability in the CORS design that has not been mentioned by anyone yet and that does not require XSS or untrusted code. Before I describe the attack, I want to remind everyone that the purpose of this particular scenario was to study the usability of CORS and UMP in a benign situation. This example only has a page from Yahoo talking to servers also operated by Yahoo. There are also no side-effects in this example; it's purely a data presentation example. Given that CORS and UMP are new protocols and that this is the most benign scenario we can conjure, I think it's fair to expect a solution with strong security properties. It should be damning if the solution to this very simple scenario introduces complex security problems. We are talking about enabling a class of functionality (cross-origin messaging) that isn't currently possible on the web. Obviously if it is possible to do so securely and easily, that's a good thing. If that is not possible, and the options are to enable things that have relative degrees of security or ease of use, then it becomes much more debatable. Damning is a strong word to use in this situation, If the introduced security problems are complex and therefore hard or infeasible to solve, then damning is the right word. If the simple, benign scenario is made infeasible, that's damning. especially since I think most people would see the interchange between Maciej and I that neither solution (CORS or UMP) makes things trivially securable. Another conclusion could be that doing this stuff is just hard. There's a big difference between trivially and infeasible. What are the issues with UMP where we cannot provide concrete guidance to developers? As I've shown, there are hard unknowns in the CORS solution. You've shown that there are cases where CORS is not secure. I don't know that I would agree with your assessment that you've shown that there are hard unknowns. Further down in this email, you punt on my example, saying that it can't be deployed. If there are classes of applications that CORS cannot address, and these classes are important, then there are hard unknowns in CORS. I should have mentioned that, as many others have pointed out, simply running the widget off-origin (or in a sandboxed iframe) would also work. I do not agree with your second sentence. We know the circumstances that make cookie-based solutions dangers; you yourself have been very helpful in pointing them out. So, I don't think your hard unknown characterization is accurate. For example, will the Security Considerations section of CORS have to say: It is not safe in CORS to make a GET request for public data using a URL obtained from a possibly malicious party. Validating the URL requires global knowledge of all origins that might grant special access to the requestor's origin, and so return private user data. Yes, one would imagine saying something quite similar to that. As Maciej has shown, simply saying make sure the URL can't be easily obtained is not that easy. I saw him assert that. I didn't see him show that. What are the pitfalls that have not been addressed in the UMP spec? Well, he didn't show that any more than I showed how to get the unguessable URL in the first place. However, the fact that he caught errors in my description of what you had to protect against seemed like a strong argument. If the Yahoo Finance portfolio was designed to use UMP instead of CORS, this hack would not compromise any private portfolio data since the attacker doesn't know the unguessable secret for anyone's private portfolio. If the code had been audited, then it is reasonable to assume that someone would have caught that allowing the HotTrades service to tell the user to fetch *any url at all* was a bad idea, and the API should have been restricted to GET http://finance.yahoo.com/stock/%s/instaprice; instead of GET %s. You've changed the scenario so that now HotTrades can only happen on Yahoo listed securities, instead of those listed on any exchange in the world. You have to allow fetching of any URL to make the application work. If that is true, then a reasonable audit would not allow that app to run on my.yahoo.com, because of the dangers involved. Or, a reasonable audit could say: that's a fine app, so long as you're using UMP. If CORS requires the app to be rejected, that's a failure for
Re: widget example of CORS and UMP
On Thu, May 13, 2010 at 6:13 PM, Maciej Stachowiak m...@apple.com wrote: On May 13, 2010, at 5:37 PM, Dirk Pranke wrote: One could also observe that with the naive implementation of the CORS API, *any* site could trivially fetch the user's portfolio data, which is presumably not desirable, and so Yahoo! Finance would also need to check the Origin: header. With the UMP solution, this is not strictly necessary but might be a useful defense in depth. The disadvantage of requiring the Origin header means that this is not really an Open API - Yahoo! Finance has to whitelist the callers. Not very web friendly, but this is maybe okay since this particular API was never intended to be Open. Actually, with UMP you can't check the Origin header, since it will be missing (or Origin: null) regardless of the origin.. But with CORS you can add defense in depth by requiring an unguessable token in the request, as with the UMP solution. Good point; you're right. Now suppose that My Yahoo! allows the user to install third-party gadgets. Suddenly neither Yahoo! Finance nor the browser can distinguish a safe request from a trusted gadget from an unsafe request from an untrusted gadget. Since the CORS solution uses well-known URLs, it is now helpless against exposing this data to a third party. How can we protect against that? One solution would be to run the third-party gadget in an IFRAME (and from a different domain), again. But this would partially defeat the goal we started with in the first place. Another approach would be to attempt to inspect the widget code (either by a human or by something like Caja) and only allow appropriately sanitized code to execute. However, given that the URL is just a string, I suspect it would be difficult to write a general purpose sanitizer to protect against this, or at least to do so and allow the resulting sanitized gadget to do anything very interesting. Maybe a human could do it correctly - this is more or less the definition of trusted code, after all. If you don't run the code in an off-domain iframe or through a sanitizer like Caja, then everything on your site is vulnerable, not just resources protected via CORS. Using different-origin iframes with postMessage to communicate to the container seems like a fine solution for third-party gadgets. What goal is it defeating? Why would embedding gadgets inline without a frame be a goal? One could argue that maintaining off-domain iframes is a hack, or is a maintenance burden. You are correct of course that if you don't do either, you are vulnerable. Alternately, tools like Caja would block all use of XHR other than the anonymous kind. Exactly, so the off-domain IFRAME is the only option here. Thus, any of the reasonably secure ways to embed a third-party widget would not be vulnerable. What about the UMP-based solution; is it vulnerable? If the page containing the third-party gadget does not also contain the Yahoo!-provided portfolio gadget, then the $UNGUESSABLE_ID is not easily obtained, and so, not really. Actually, if any page served off of my.yahoo.com contains $UNGUESSABLE_ID, and the widget is embedded on the My Yahoo origin and not protected with a tool like Cja, then the third-party gadget can trivially get the unguessable ID. It doesn't even have to use it right away while the My Yahoo site is embedding widgets in an insecure way - it can exfiltrate it for later use at the time and place of its choosing. True. I did not consider this interestingly different, but in retrospect I was perhaps wrong. This is the main risk of UMP compared to CORS. Because secret tokens are the only security tool you have, you have the problem of maintaining confidentiality of a shared secret. If that shared secret is embedded in Web pages you serve, and/or embedded in a URL, that is hard to do. Agreed. In this particular use case, protecting that URL is probably not difficult, but it is a general problem. If the page does contains both the third-party gadget and the Yahoo!-provided portfolio gadget, then there would have to be a way to prevent the third-party gadget from being able to crawl the DOM and extract the $UNGUESSABLE_URL. I don't think that that's possible unless you put the third-party gadget in an IFRAME, again. Or, you can again run the third-party gadget through a sanitizer, but in this case we know that you can implement this programmatically, since that's what Caja does. Indeed, but a gadget running same-origin doesn't even have to craw the DOM, it could use XHR or other means (e.g. iframes) to get access to any resource on the origin unless somehow prevented from doing so. Which Caja does. Agreed. A third option to protect the API would be to modify the Yahoo! Finance API to require an unguessable token even in the CORS case (so you would use cookies + token). This is the analogy to what we do today for XSRF
Re: widget example of CORS and UMP
On Thu, May 13, 2010 at 6:40 PM, Dirk Pranke dpra...@chromium.org wrote: On Thu, May 13, 2010 at 6:13 PM, Maciej Stachowiak m...@apple.com wrote: I think a more likely use case for CORS does not involve embedded gadgets at all. Consider the example of a social network asking for access to your GMail contacts. Fair enough. Sounds like a different email thread; I'll see what I can do :) Okay, having thought about this for a few minutes, I think that this is essentially identical to the calendar example you worked through in your DBAD slide deck (and which is also listed as an example use case in the CORS spec) (it's just a GET instead of a PUT). So, rehashing that thread here doesn't make a lot of sense, but incorporating it into the security considerations section does. Do you agree? -- Dirk
Re: widget example of CORS and UMP
On Thu, 13 May 2010, Dirk Pranke wrote: The initial, insecure CORS solution is straightforward ... a gadget running on My Yahoo! sends an XHR with the users' credentials to http://finance.yahoo.com/api/v1/my_portfolio; and gets some JSON back. If I understand this right, you are saying that the user visits my.yahoo.com, and that page does an XHR to finance.yahoo.com, right? One interesting aspect of the CORS solution is that there is no way for the CORS-based gadget to get another user's data; it is simply not possible to request it, since a different set of cookies cannot be included in the request. The CORS solution requires you to believe in the security of proper cookie handling. With an HttpOnly cookie, cookies can be handled pretty safely but I imagine all of us are fairly aware that cookies get exposed all the time and hence this is hardly a perfect solution, maybe just good enough. One could also observe that with the naive implementation of the CORS API, *any* site could trivially fetch the user's portfolio data, which is presumably not desirable, and so Yahoo! Finance would also need to check the Origin: header. Actually it just needs to send back a header saying that only my.yahoo.com is allowed to read it, and the client will take care of it. Now suppose that My Yahoo! allows the user to install third-party gadgets. Suddenly neither Yahoo! Finance nor the browser can distinguish a safe request from a trusted gadget from an unsafe request from an untrusted gadget. If my.yahoo.com is running _untrusted_ script in the context of my.yahoo.com, then forget XHR -- the game is already over long before we get to CORS. For example, the script could do a convincing phishing attack trivially, get the user's credentials, and then send them to the attacker for use offline. UMP or CORS are irrelevant here. If you want to run untrusted script, you can use iframe sandbox, and then CORS is neutralised (since the Origin is unguessable and unforgable), which seems to me to be what we want in that scenario. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'