View in English

  • Global Nav Open Menu Global Nav Close Menu
  • Apple Developer
Search
Cancel
  • Apple Developer
  • News
  • Discover
  • Design
  • Develop
  • Distribute
  • Support
  • Account
Only search within “”

Quick Links

5 Quick Links

Videos

Open Menu Close Menu
  • Collections
  • Topics
  • All Videos
  • About

More Videos

Streaming is available in most browsers,
and in the WWDC app.

  • Overview
  • Transcript
  • Strategies for Securing Web Content

    Whether you use web content in your app via an embedded WebKit view, deliver pure web apps, or create web content to be embedded by others, it's important to ensure that you are using the most current web security standards. Learn techniques like such as special cookie attributes and HTTP response headers designed to secure your web content against the latest threats that include cross-site scripting, cross-site request forgeries, and speculative execution attacks, commonly known as Spectre.

    Resources

      • HD Video
      • SD Video
    • Presentation Slides (PDF)

    Related Videos

    WWDC 2018

    • Better Apps through Better Privacy
    • What’s New in Safari and WebKit
  • Download

    Hello everyone. My name is John Wilander. I am an engineer on the Safari and WebKit team and I'm here to present to you today how to secure web content. Or, as I like to call it, take the Swede's advice.

    So, you might be asking yourself, web content, that's a pretty broad term. Is this session really for me? Yes, it is for you. To start off, apps use tons of web content. It may be used for ads, login flows, splash screens. You might be using Safari View Controller to-- for parts of your app. You might have whole parts of your UI rendered in a web view.

    You might also have companion web apps that are supposed to be rendered in a web browser and that are sharing content or providing a joint experience across apps and web apps. So, really, yes, the session is for you.

    And security is important.

    You want to stay in business? You want to provide the best customer experience. You want to be ahead of your competition. You want to get this right so that when they don't they are the ones to fall, you stay in the market.

    OK. What are we going to cover today? We're going to have a look at first securing your transports. This is just a brief mentioning from me about basics that we need to do before we do the rest. If you don't secure your transports, most other bets are off.

    Then we'll go into a look at cross-origin lockdown. This is basically me showing you a bunch of technologies that are available to you in WebKit and in browser engines across the line that can help you get into more secure defaults for your web content. We would like to opt in for you, but we can't test your sites for you or your web content for you, so we need you to opt in. And then, as a motivation, if you feel, well, why should I care about these security mechanisms, I'll actually show you some attack scenarios and map them back to the security technologies so that you understand where they come into play and how they can defend your web content.

    So, let's head right in to securing your transports. This one should be familiar to you. So, this is about moving to HTTPS and WSS.

    WSS is for web sockets.

    Now, just the fact that HTTP and WS, the plain text equivalents, still exist is not an excuse to keep using them. You need to move to secure transports because that's what's going to ensure that the content that you are rendering in a browser or in your app comes from the server you expect it to come from and no one has fiddled around with the content in transport. So, moving to HTTPS for your main content. There are a couple of technologies that can help you get there.

    First on your to-do list-- except for just moving to HTTPS in general-- is strict transport security or HSTS. This is an HTTP response header you can send to the rendering engine, such as WebKit, and tell it, hey, my domain should always be loaded over HTTPS. If there's ever an HTTP request from me, just automatically upgrade it for me to HTTPS. Never making plain text connections to my server, please.

    And this is also a thing you can tell the rendering engine for how long it should remember this. So, typically at least half a year ahead in time.

    Now, you might also be loading content off of other servers, servers that are not under your control, not your domain name.

    There's also a header you can send to the browser engine called upgrade insecure requests, also an HTTP response header, which tells the browser, hey, go ahead and upgrade all those other links to content too, even if it's not from my server and even if they have not set strict transport security.

    So, those two things that will automatically upgrade to secure transports.

    Another thing you need to do is make sure that you mark your cookies secure. This is an attribute you add in your set cookie header, semi-colon secure. This means that you're telling the network stack this cookie should only ever be sent over a secure transport. If there for some reason is a plain text request for my server or to my server, don't send the cookie.

    And, since you should be using secure transports, all of your cookies should be marked secure.

    Final-- finally on your to-do list here for secure transports is specific for apps. You might have heard about app transport security or ATS. It is the default behavior for iOS apps, meaning that they should be using only secure transports for network traffic.

    Now, there is an opt out you can have in your info p list to say, hey, you know, for web content, I'd still like to do insecure requests.

    Don't do that. You should be saying no in this info p list and specifically for arbitrary web content loads.

    OK. Now we've secured the transport. Let's move on. We're now going to look at cross-origin lockdown.

    The reason why I call it lockdown is this is really you opting into saner, safer, more secure defaults for your web content. We're locking it down to more or less what it should have been all along and then you open up the specific things you want to do.

    So, let's move in and look at what are cross-origin loads anyway. What are we going to lock down? Well, web technologies have this powerful feature where you can weave together content from different servers and different origins.

    Different domain names, if you so will.

    An example of this is images. You can load images from any server on the web into your web content and that's a cross-origin load.

    You can also load scripts from other servers.

    Interestingly, those scripts actually execute with the same powers and privileges as your own scripts, so you need to be really careful what scripts you load off of other servers. They more or less own your web content. They are executing with the same powers as you.

    And, as a third example, iframes. You can embed full pages from other servers. Cross-origin, meaning from a different domain name. These are three examples of cross-origin loads. Now, we've had a security mechanisms-- security mechanism on the web for over 20 years that has provided basic protection for these cross-origin loads and it's called the same-origin policy.

    And it differentiates-- here you've got these examples with real domain names. So, you've got the example for loading the image, you've got a CDN where you loaded the script, and you may have a social widget, an iframe, coming from social.example here.

    And, just to mention, when I say .example it's just me being sure that I'm not talking about real websites here. If it's easier for you, you can think of it as .com or .org.

    Anyway, these are the cross-origin loads and the same-origin policy keeps track of where did I load this image from or where did I load this script from, where did I load this iframe from, so that it can provide basic protection. That basic protection means that your page in this example cannot reach into that iframe from social.example and read its bytes, read its contents, or write to its contents. The same-origin policy is guarding, saying this part of the page actually came from a different server, you're not allowed to just go straight in there and change things or read what the user happened to enter into that form, for instance. An easier way to think of the same-origin policy is just matching two pages, two tabs in a browser. One tab shouldn't be able to just go into another tab and see what the user's doing over there.

    It's the same-origin policy effectively doing its job there too.

    So, the lockdown. How do we lock this down properly? We've got the same-origin policy, but it's not good enough. So, you need to opt in to some more defaults. Starting out with subresource integrity-- I'll go through them and I'll mention them here. This is just a simple change in the markup for your script tags.

    The second part is content security policy. This is providing a full-on security policy for your whole page where you can say, hey, I only want to load scripts from over here. I don't want to have any frames from other servers, and so on. We'll look at that.

    And the third category here are simple server configurations. These are HTTP response headers that you send out telling the browser engine, hey, I want more secure defaults, I don't want these old legacy APIs that you've been supporting because I don't need them. Please help me here. So, let's dive into it and look at subresource integrity.

    Now, this is a perfectly plausible way of loading that framework from the CDN, your content delivery network.

    And that script tag is going to just contain the URL to fetch that script, right? As I mentioned, you're now relying on that CDN to provide you with the right script that's going to make your web content work the way it's supposed to.

    But actually, if they decide to, you know, bump the version or if something goes wrong on that server, they're serving you-- they're sending you the wrong script, your web content may be crippled. It may-- something may go wrong. It might not work the way it's supposed to. You know what script you're expecting, but what you're sending out when you're just sending a script tag like this-- looking like this-- is just telling the browser whatever you get back in JavaScript, execute it.

    A much better way is to say, no, I want to make sure it's the script I expect. And-- but you can use the integrity attribute in your script tags. In there you provide a check sum, in this case with the algorithm sha256, saying this is the check sum of the script I expect to get from my CDN, and only if I get something that matches this check sum, then you execute it.

    So, the browser engine will go through and make sure to compare that check sum before executing the code.

    Well, what happens if it doesn't match? What if they bumped the version or something went wrong and I got the wrong script? Now my web content doesn't work anymore. Well, you add a check. In this case, you've loaded or tried to load a framework. You checked did the framework load OK, do I have that object in my dom now. If not, go load it from my own server which I am in control of and I don't make changes to willy-nilly.

    That may reduce performance, but at least you have a still functioning web content or website.

    OK. That's sub-resource integrity. Let's move on to content security policy. I mentioned this is like setting a policy for your page, like what should be allowed here, and I actually think of it as an architecture policy. If you're a software engineer, you want to keep track of your dependencies. What am I allowed to do here? Who-- what can I load and what can't I load? So, this is again an HTTP response header. So, when you're sending out a page from your server, you add this header to the response, saying, hey, I'm going to run with a content security policy. I'm going to be in control of the content on my page.

    Then you start out by saying the default source for loading any kind of content from remote servers is myself. Only load from my server by default.

    Now you've locked it down completely and if there is any kind of content load in the page trying to pull something in from a server that's not yours, it will just be denied because WebKit will deny that because it doesn't match the policy you've set.

    And, as you see, I made a comment there. No inline. That is also part of the default behavior. Once you set it this way, you're also saying no inline scripting. Only load scripts from files. That's why I keep thinking of it as an architecture policy because you're separating logic into files, separating from markup, and separating from styling, which are also in files. CSS files.

    OK. Now, you wanted to load that script from cdn.example and if you just go with a default source self, then that's going to be locked down. Right? You can't do remote script loading. Well, there's a whitelisting mechanism in the content security policy. You just say script source, hey, let's open up for cdn.example because I actually want to load script from there. Now you can load from your own server and cdn.example, but nowhere else.

    Well, you might want to have that social media plugin, little widget in there in an iframe, well, you can add a frame source directive saying I want to be able to load iframes from social.example, but no one else gets to have an iframe on my page. Again, you're in control of that.

    And there's even a directive for the reverse case when your content is being loaded in an iframe on someone else's page. In this example, news.example is loading your content in an iframe. You can send out the directive-- the last directive here in content security policy frame ancestors. This is telling the browser, hey, check whosever framing me and all the way up to the top page and they all have to be on my list of what I allow. So, in this case, your web content has said news.example, I have a business deal with them, they're allowed to have my content in an iframe.

    OK. That's quite a lot, so let's just review this line by line quickly so we know what it's saying. Content security policy, you start out default source self. Lock everything down. Everything that's going to be loaded with a source attribute, like loaded from a server, needs to be from my origin, my domain.

    Then you open up. For script, you add what domain names do I allow scripts from.

    You say where do I allow myself to load frames from.

    You whitelist them. And, finally, if you're ever going to be in an iframe yourself under someone else's page, you put them in that white list for frame ancestors.

    OK. That's the content security policy. It has more knobs to turn and we'll also see in a couple of the attack scenarios a few flavors of these things.

    Moving on. We're going to have a look at cookies. Cookies are-- they actually were called magic cookies in the beginning of the web, and they really are magic in that we use them for so many things. And perhaps the most sensitive thing is they authenticate users. Once you have logged in with your credentials, you get a cookie that holds your session and that cookie, if it's moved or its stolen and moved to another browser engine in many cases can impersonate that user. So, you really need to protect your cookies. As I already mentioned, you should mark them all secure so that they never leak in plain text requests. But there are more things to do, right? So, looking at Http Only cookies. This is fairly old technology. I would guess this has been around for at least 15 years, the ability to say HTTP only. You might be familiar with the web API document.cookie. This is a way for JavaScript to read and write cookies.

    JavaScript is powerful. And, as I mentioned, if you load JavaScript from other servers, they have access to all of your user's cookies through this API.

    You should not be offering them that much power. Instead, you should protect your cookies, especially your authentication cookies that are effectively a way to log in as a user by marking them Http Only.

    This means that-- this cookie-- and this is the set cookie header you are seeing here where we are sending HTTP only, which means don't expose this cookie in the document.cookie API.

    So, JavaScript can now not see this cookie and of course not fiddle with it, steal it, or manipulate it. So, this is something you should be doing. We also have another thing, new technology as of the betas, SameSite cookies.

    Again, you are setting this on the set cookie header that you-- when you're setting the cookie in the browser.

    See here I've got the same site attribute equals strict. There's also a lax version of this, but what this is basically saying is this particular cookie, only send it when I am the page owner, when I am the main page, not when I'm embedded. When I own the whole user experience, I have the whole web view, then send this cookie.

    So, in the embedded case, if your web content is being embedded by someone you don't trust, the SameSite cookie will not be sent and your server can detect this. Aha! I didn't get that SameSite cookie, so either this user is not logged in or I'm being embedded and I'm not going to allow this thing to happen were that, for instance, a sensitive transaction.

    So, that's getting in control of being embedded. SameSite cookies.

    OK. Cross-origin lockdown. We're now going to look at really brand new technology. WebKit is first implementing these two new response headers and they're all about restricting who gets to load your resources. Cross-origin resource policy.

    We've already mentioned these two types of content that are allowed to be loaded cross-origin, images, and scripts.

    And they've been around since the origins of the web and therefore there has never really been a mechanism to say, hey, I actually don't want any other sites to load my scripts or load my images.

    Could I just only load them myself please? No, we've had this thing on the web where anyone can load images and scripts from any server.

    And now we're providing you with a control to tell the browser, hey, I don't want that. And it's called the cross-origin resource policy.

    In this particular example here, I'm giving it the directive same, meaning only my own site can load this. Only when my domain name is the main page domain and I'm pulling in this image, then load the image into the web content process. Same thing for script here. So, when someone else comes along and tries to cross-origin load your image or your script and you're sending this response header, those things won't be loaded.

    So, that puts you in control. And this is new technology.

    Finally, in the cross-origin lockdown, we've got the cross-origin window policy. Now we're really getting into the weeds of old web APIs. You might be familiar with the ability to open someone else's page-- or for that matter your own page-- in a new window.

    Not like a regular link navigation you click and you may open a new tab or navigate in the same tab, instead you're opening a full-on new window.

    Back in the days, we even saw this in a form of ugly pop-overs or pop-ups and those kind of things, but it's the old API window.open. And it has some weird things going on.

    So, if your content is opened by someone else, it looks to you as if, whoa, the user just went to my site, I got my SameSite cookie, everything looks fine, but the opener maintains a handle and kind of owns your window and has certain APIs to control that window that the opener can even navigate your window outside of your control.

    And with the new response header cross-origin window policy, you finally get to say no to this. Most sites are not in the practice of using this API and this kind of communication where the opener owns the window. Like, it's a very rare thing to see on the web, but it's there and it works that way by default. By sending this header, in this case deny, you're saying that handle should not be there.

    It's OK to open me, but you don't get to control me from that point.

    There is also a way added in this-- I'm not showing it here-- but you can say allow post message. You might want to be able to talk between these two windows without giving the opener control of your window and then you can say allow post message.

    OK. That's also new technology and now we've gone through the cross-origin lockdown.

    As you can see, that's not too hard. It's a set of response headers. It's the content security policy where you whitelist things, and it's the integrity attribute for script tags that's more or less what we're talking about here. I'll give you some motivation. We're going to look at some attack scenarios. What are you defending against and how to these security technologies fit in with these attacks? We're going to look at cross-origin attacks, speculative execution attacks-- some people may have heard about Spectre-- and we're going to look at window control attacks. Let's dive into the cross-origin ones.

    We're going to talk about cross-site scripting, when something goes bad with your CDN. And that one you kind of could tell that I was going for, right? And cross-site request forgeries.

    Cross-site scripting. Imagine you have built a messaging app. You have it as a native app with a web view for rich formatting, for instance, and you may have a companion web app that one can go or your users can go to in a regular web browser, and you can send messages to each other and maybe with very rich formatting.

    Most of your users are, of course, nice. Nice people sending each other nice messages. Some of them are angry sending angry messages, but every now and then comes along a malicious user who might send a message looking like this.

    It starts out nice, hello, but then it contains markup.

    Now, if you have made a mistake somewhere in the chain, in the native apps web view or on the website, where this will actually be interpreted as real markup instead of a message, suddenly the attacker, the malicious user here, is able to run scripts in the recipient's browser engine.

    In this case, trying to steal the cookies of that user. But remember, the scripts are running with full power. They can take over your whole UI, make requests on your-- on the victim user's behalf.

    Cross-site scripting, which this is an example of, is a bad thing. You don't want it to happen to you.

    Luckily, you have marked your authentication cookies Http Only, right? So, ha, they're not available to that malicious script.

    Now, Http Only cookies don't protect you against cross-site scripting. That script is still running.

    Http Only cookies protect your cookies.

    So, you need to do something more and what did you do? Content security policy.

    You started out with default source self, right? Saying, eh, only I get to run script on my page please.

    And that means by default no inline scripting and that whole class of bugs just goes away.

    Now there is no way to inject script into your web pages and make them execute because you set the policy for the page.

    OK. What could happen if your CDN gets compromised? This is bad and let's just hope it doesn't happen, but it can happen. So, you're loading the framework off of that CDN and you really rely on this because it's executing with the same powers as your own scripts.

    Now, what if they've been compromised and are redirecting that script request to evil.example, loading attack code.

    Now suddenly you thought you got a framework-- maybe they were nice enough to bundle in the framework, but they're also doing some nasty things.

    So, what did you do? Well, you whitelisted script source in your content security policy, so the browser will just refuse to execute any code coming from evil.example.

    OK. Oh, now the attacker needs to be a little bit more sneaky.

    He or she is probably going to change the script on the CDN server instead of redirecting it to the evil.example server. So-- and it's on your white list, so you're going to load and execute that script.

    But, you've got subresource integrity to save you. You are in control of the integrity of that script coming from a server that you don't own and if it doesn't match the check sum, you're going to load it off of your own server instead.

    So, that attack is also foiled.

    OK. That's compromised CDN. Final of the cross-origin attack, the cross-site request forgeries. This really ties into the last word, forgeries. These are-- this is the attacker trying to forge a request to look like something one of your users is trying to do, where they're actually not.

    So, we're back at the messaging app and you have this forum where the user is supposed to be able to send messages. And, frankly, when it comes down to it, it's going to be HTTP requests. Probably in HTTP post when that message comes into the server and look at the cookies, everything looks good, and then you'll send that message off to its recipient, right? Well, now comes along the malicious attacker that of course has phished one of your users, meaning sent a link and lured that user onto the attacker's site, evil.example, and is showing some really, really fascinating stats on cats.

    That makes the victim stay around for a little while at least. I mean you've got to check these stats out.

    What the victim user doesn't realize is that there's a hidden resource load with your web content sending a message on the victim user's behalf-- which of course automatically adds the cookies, that's just how the web works, right? If a request goes out on the wire, cookies are added, and to your servers this looks like I guess this user wants to send this message.

    That could be spam, that could be sending links for malicious software. It could be breaking up with a partner-- ah, OK, they won't go that far, but malicious software, we'll stay there.

    So, you don't want this to happen. Luckily, you have used same-site cookies.

    They will not be sent in the embedded case, which means that your server will detect I'm being embedded here. I don't allow the user to send messages from an iframe under some other page. I need to own the UI when I do this sensitive thing, such as sending messages, I'm just going to deny this request.

    This, again, puts you in control.

    OK. We have now covered cross-origin attacks and looked at how some of those security mechanisms help us. We're going to move on to something that's really exotic and new; Spectre attacks or speculative execution attacks.

    What I'm going to cover here is what speculative execution is, how it can be turned into an attack, and then we'll look at how to defend against it.

    So, now we're deep down in a CPU. It's executing code. It has reached a conditional. It's going to do something conditionally. It's asking itself, hey, I've got an array index here, x. Is this index OK? Is this in bounds or out of bounds for my array read? Because if it's out of bounds, I should do some error handling here, but if it's in bound I should go ahead and load that data in the array.

    Now, modern CPUs learn over time if they see the same code path over and over again that, hey, x is always in bound.

    It's always OK to load this array.

    Why don't I go ahead and speculatively do that, before I know whether it's OK or not? And this is how it works. It does this code-- takes this code path speculatively, loads that data, and then when the final answer comes in, in this case, oops, no, this is one of the rare cases where x was not OK, you shouldn't have been loading that data, it backs it out and takes the right code path. How is this OK? Well, it's OK because the speculative path is not committed. It is only done in advance so that we can take advantage of, oh, I'm already done with all of that work when the final answer to the original question comes in. And that's speculative execution.

    How can this be turned into an attack? It turns out that cache effects that are a result of the speculative execution can be monitored by malicious code and then they can leak that data read that was never supposed to happen. It was out of bounds, that load should have not happened, but it effects caches and by measuring caches the-- an attacker can leak that data that was not supposed to be loaded.

    OK. How does this map to web content? Remember the same-origin policy? This thing that has been protecting us for 20 years that makes sure that the main frame from one origin cannot reach into and read the bytes of some other frame, maybe your embedded content.

    With speculative execution attacks, we can no longer rely on the same-origin policy.

    There is now an ability-- if you can run scripts and you're in the same process, the same web content process as some other content, you can read that content through speculative execution attacks.

    OK. This is a big challenge for the web. I can tell you, I've been sitting in meetings with the other browser vendors. We are working super hard to try to fix this by default for the web, but we need your help.

    If you can opt into a bunch of things-- we've already looked at the defense mechanisms, right? If you can opt into these, you can help us by telling us, hey, I have sensitive content. I'm willing to have better defaults. You don't have to support these legacy APIs for me. Then we can be much more aggressive in fighting speculative execution attacks on your behalf.

    So, let's look at how this maps.

    The basic thing you're going to try to do here to fight speculative execution attacks is making sure your web content never ends up in the same web content process as a frame from evil.example. If they have a frame evil.example, they can execute code in your-- in the same process that your web content resides in and read your bytes.

    So, how do we make sure this never happens? OK. We've got these things. First, WKWebView. Now we're looking at apps using WebKit as a framework.

    I'm looking here at Safari, which is an example of an app that has been using WKWebView and we sometimes refer to it as Modern WebKit, has been using it for many, many years. And it provides excellent advantages.

    For instance, these three tabs, the evil.example, your web content, and webkit.org are all rendered in separate web content processes.

    Further, WKWebView provides you with a separate process for networking. This is where cookies get added and HTTP headers are parsed and et cetera.

    Now, speculative execution attacks all rely on being in the same web content process and doing the speculation thing to try to read things that the attacker wasn't supposed to be able to read. Well, if you have separated things into different processes, this attack doesn't work, right? You cannot do speculative execution attacks across process boundaries, so this is already a defense here and of course that's super important that the web content process cannot reach into the network process and do speculative execution attacks there.

    But if you are still using UIWebView, which, by the way, we are deprecating as of the betas, you're not in a very good place.

    Now, if you have evil.example and you have your web content and you've got the network stack and then you put this all in your app, from the view of a speculative execution attack, this all blends together.

    It's all the same process space.

    There are no guards for speculative execution attack in this scenario.

    You need to get off of UIWebView.

    If you move to WKWebView, you'll instead get this. Out of process, separated, badness happening in the evil.example content process cannot affect the rest.

    OK. We've moved to WKWebView. Let's look at how content security policy can help you. You might have an embedded social widget from social.example, but then you might have an injection attack, maybe it's the messaging thing again where someone can send markup in a message and you accidentally render it and they pull in an iframe from evil.example.

    Well, you may also have an ad there that you want to have there and then the ad network gets compromised and redirects to evil.example and then pulls in an iframe. And, remember, you never want to be in a web content process together with a frame from evil.example.

    So, what have you done? You have deployed content security policy and you've specified from where you allow frames and please don't allow evil.example.

    This is how you protect accidentally getting a frame in your process from evil.example.

    So, the reverse. Can evil.example pull your web content into the evil process? Of course.

    So, how do you protect against that? We are back at the content security policy and now we see frame ancestors. And this is what I referred to earlier with a slightly different flavor. You can actually say none and this means never iframe me.

    This content should never be in an iframe from someone else. This is my content. Only I get to render this thing.

    So, this-- if you place this, that-- the evil.example page cannot pull in your content in an iframe. And, of course, we do that blocking in the network process. That's important, right, because a speculative execution attack can only happen in the same process space, so we cut it off before it enters where evil.example can execute JavaScript.

    OK. HttpOnly cookies, do they really map to speculative execution attacks? Yes, they do. They're even more important here than to try to fight cross-site scripting.

    Why? Well, remember that old API document.cookie is the way to look at cookies from JavaScript? Now that we don't-- we can't rely on the same-origin policy anymore, evil.example can reach into an iframe from your content and actually read the cookies.

    Super bad. But if you mark them HttpOnly, WebKit will make sure to keep them in the network process. We don't need to move them into the web content process because they never need to be exposed in the document.cookie API.

    So, this automatically protects the cookies against speculative execution attacks.

    SameSite cookies. This is basically giving your server control of the embedded case. Again, evil.example has decide to try to pull off a speculative execution attack against your content.

    Loaded an iframe with your content, but the SameSite cookie doesn't get sent, so your server will know that, hey, I'm being embedded here. I'm not going to allow this. So, you're going to deny this whole resource load. Server side.

    And that way not end up in evil.example's process.

    Finally, to fight these attacks, cross-origin resource policy.

    Now, this was the new header I told you about where you can tell the web browser engine that, hey, images, scripts, and other things from my server, only I get to load them. So, if you say-- send this header for your images and your scripts on your server, we will make sure to block them from being loaded by evil.example and we'll do that block in the network process. Again, giving you that process separation so that a speculative execution attack cannot read your bytes.

    OK. We have the final attack category to have a look at and this is a pretty brief one. Window control attacks.

    So, we're going to look malicious window navigation, sometimes referred to as tabnapping, and then the defense.

    Again, we're back here at evil.example and instead of embedding your content, thus the window.open opens your content in a new window and you don't get to know. You don't get to decide, yeah, OK, someone opened my web page. And the SameSite cookie may be sent here. You might think everything's good, but evil.example could wait until your user loses focus of that page of yours and then use the handle to navigate it to a fraud page that looks like your page and asks the user to please log in again, of course stealing the credentials and sending them off to the attacker.

    This is one of the things that can happen if you leave the control up to the opener.

    Instead, you deploy the cross-origin window policy, you deny this thing, and there will be no handler for the attacker page to navigate your window with. So, that's the final defense in attack.

    It's time to take action. We're going to review what we've been looking at here, just so that you know what you need to go back to your office or your home and start working on.

    First, we have to secure these transports. Move to HTTPS and WSS.

    You should have secure cookies. You should also mark them HttpOnly. If you take the Swede's advice, just make all of your cookies HttpOnly and secure.

    And you need to migrate off of UIWebView to WKWebview. These are the basics.

    Then we have the defense mechanisms we've been going through. Content security policy will help you here with cross-site scripting and speculative execution attacks.

    HttpOnly cookies will provide you with some kind of protection against cross-site scripting, meaning the scripts can't steal the cookies, but it will definitely help you against speculative execution attacks because HttpOnly cookies are kept in the network process.

    Subresource integrity. This is the way you fight against a compromised CDN. Someone's executing code on your page that you never wanted to be there.

    SameSite cookies, this is a way to fight forged requests done invisibly by some phishing page to your server. You will know that because the SameSite cookie won't be sent when you're embedded and so you don't accept the request.

    It also happens against speculative execution attacks because if an evil page is trying to pull in your resources to be able to leverage an attack against them, again, SameSite cookies won't be sent and you can deny the load. Then we get into these new technologies, the cross-origin resource policy. This is the way you can say that images, scripts, and other cross-origin loads, deny them, I only want to load this on my page. And, finally, controlling windows is making sure that that handle goes away if someone else opens your web content in their own window.

    These are fairly easy to adopt, especially for you. You know your sites, you know your web content, you know your apps, you know how they're supposed to work. If we would just turn this on by default for all of you, it would probably break a few things, so you need to opt into this. And by opting in means you should check that the security works-- you can try to pull off an attack against your own content, make sure that, yeah, my content security policy is defending me, good, and of course test that the functionality that should be there is there.

    We have a blog. The WebKit project is an open source project. We have a blog where we talk about these technologies and other things. This is where we'll update you on those two last response headers. The cross-origin resource policy and the cross-origin window policy. Because we're still discussing those with the other browser vendors, trying to make sure that they're standard so that the same response headers work across all the browsers. And so there might be slight name changes or added attributes that we still don't have here. Also, it's so brand new that you actually won't have access to this until seed two or the public seed. We don't have full support for these in the developer seed yet.

    Quick shout out to these other sessions. Please come see us, including me, at the Safari, WebKit, and Password AutoFill Lab tomorrow at 2:00. You can come there and discuss with me or my co-workers how to deploy these technologies and make them work the best for you.

    And there's also a session on Friday that's more general on what's new in Safari and WebKit.

    Thank you.

    [ Applause ]

  • Looking for something specific? Enter a topic above and jump straight to the good stuff.

    An error occurred when submitting your query. Please check your Internet connection and try again.

Developer Footer

  • Videos
  • WWDC18
  • Strategies for Securing Web Content
  • Open Menu Close Menu
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • watchOS
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playgrounds
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    Open Menu Close Menu
    • Accessibility
    • Accessories
    • App Extensions
    • App Store
    • Audio & Video
    • Augmented Reality
    • Business
    • Design
    • Distribution
    • Education
    • Fonts
    • Games
    • Health & Fitness
    • In-App Purchase
    • Localization
    • Maps & Location
    • Machine Learning
    • Security
    • Safari & Web
    Open Menu Close Menu
    • Documentation
    • Curriculum
    • Downloads
    • Forums
    • Videos
    Open Menu Close Menu
    • Support Articles
    • Contact Us
    • Bug Reporting
    • System Status
    Open Menu Close Menu
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles
    • Feedback Assistant
    Open Menu Close Menu
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program
    • News Partner Program
    • Video Partner Program
    • Security Bounty Program
    • Security Research Device Program
    Open Menu Close Menu
    • Events Overview
    • App Accelerators
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Academies
    • Entrepreneur Camp
    • Ask Apple
    • Tech Talks
    • WWDC
    To view the latest developer news, visit News and Updates.
    Copyright © 2023 Apple Inc. All rights reserved.
    Terms of Use Privacy Policy Agreements and Guidelines