Hacker Time
Presented by: Evan Johnson
Start at
Originally aired on December 4, 2020 @ 11:30 AM - 12:00 PM EST
Join Evan Johnson as he speaks with security professionals about recent security news!
English
Security
News
Transcript (Beta)
All righty and we are live. Welcome to Hacker Time. Thanks for joining me for another episode of the number one security show anywhere on the Internet, especially on Cloudflare TV, Hacker Time with yours truly.
I'm Evan Johnson and you can follow me on Twitter.
I'm ejcx underscore. I work here on the Cloudflare product security team and I'm here to talk to you today about one of the most important topics in all of security, cross-origin resource sharing.
It's probably not the most important topic, but it is a nuanced and really interesting topic with really serious issues when you get your cross -origin resource sharing policy improperly set.
You can do a lot of damage to your website and if you're a SaaS company or you have a website with a lot of users and sensitive information going into that website, they could be exposed to different attacks if you get your cross -origin resource sharing policy wrong.
It's an easy thing to get wrong and that's why it's interesting.
Welcome. I hope everybody is staying safe and wearing a mask and hunkered down throughout the pandemic and staying inside watching Cloudflare TV.
Without further ado, I'm going to start talking about walking through an old talk that I gave on cross -origin resource sharing or CORS.
I gave this talk at AppSecUSA in Washington DC a few years ago and it was about CORS, but about the bigger picture around standards, web standards.
And I used this metaphor that didn't really land at the time.
I think people laughed, I'm not really sure, but the idea was that as everybody basically in these days have has a website and if they don't yet, they will.
They have people using the website, there's e-commerce, there's all sorts of business happening on the Internet and it's really hard to stay secure.
And so I said that the Internet is not really a series of castles where it's really well fortified, like structures, really good security at every website.
There's a lot of errors that people make and it's really expensive to get security right.
Like you look at the biggest tech companies out there and Google has made enormous investments in security, billions of dollars.
All of the big tech companies have made enormous investments in security and it's not cheap.
And so it's, I mean, one of the reasons that Cloudflare exists is kind of to bring that security to every website out there, that same level of security to every website out there.
But there's still work to do to get to that goal and it is really expensive to do security well.
And so I had this picture of like this deflated bouncy castle and it's just, it's hard, like security is really hard.
And so this is what the castles look like.
I think people imagine these really well fortified structures and they're really not.
And I kind of built off of that in this talk to talk about the core fundamental piece of security on the Internet.
So this is same origin policy. So same origin policy is the thing that it's kind of the bandaid keeping the, all of web security together.
Um, and what it says is that when you're on website one and website one, there's all this code running in your browser on the front end of website one.
So I'm on Google docs right now.
You can see, uh, if it makes a web request to website two, it should get blocked.
And the reason for that by default, it should be blocked by default. Uh, and the reason for that is because of cookies.
So your browser is so, so smart that it will, whenever you, whenever you make a web request, uh, to, um, another webpage, it wants to include the cookies and to kind of make sure that this is secure by default and you, you can't steal those cookies.
The, the, the kind of attack that you might imagine here is that you're on evil.com and it makes a asynchronous JavaScript request from the front end of evil.com over to bank.com.
And if, if, if you were just logged into your bank, you'll still have your cookies and, uh, they could potentially steal money.
They could do anything bad that you don't want them to do.
So, uh, same origin policy means that that's blocked. You can only make web requests from evil.com to evil.com, the same origin and origin is the scheme.
So the, uh, so if you're on HTTPS, evil.com, it has to be the HTTPS, the host, which is evil.com, the port you could be on evil.com port 80, port 81, port 82.
Um, and, uh, some other things, I think I'm forgetting one or two things in there, but, uh, it has to be the same origin.
So that's kind of the bandaid keeping it all, keeping all of web security together.
And what cross-origin resource sharing is, is when you poke little holes in, in that, that blanket deny policy.
And you say, you know, there are a few situations where I actually do want to make these cross-origin requests.
And I'll show you a concrete example of why you might want to do that.
But in cross-origin resource sharing, you might say, um, uh, what's, what's an example.
So what, what about Google analytics or an analytic service?
So you have example.com and it's making a request to send some information to example API.
In this case, it's getting some information. You'll see that this is what a HTTP request over the wire looks like.
It says get, uh, it's making a get request for some information from example.com and, uh, and the API is responding with some random information.
And so the method of doing this, the way you do cross-origin resource sharing is with an HTTP response header.
And in this case, it's access control, allow origin star.
What this is saying is example, API .com is saying any website, any origin, any front end can make requests to me.
And it's okay.
There are not some sensitive bank. Anybody can make requests and it's not going to violate, uh, violate any security.
So, uh, you'll also notice that the origin header is here.
Uh, the origin header is what, uh, servers use to make decisions about whether or not to allow requests from that, from a specific, uh, website.
So in this model, it's important to note that um, that the server receiving the request makes the decision about whether or not to be receiving requests.
So a bank knows a bank security best.
Um, in, in my fictitious example, a few minutes ago, a bank gets to decide, uh, if, if it's a bank receiving the request, it makes sense that they'd want to make sure that those, uh, that they are allowed to set the security policy on that.
So CORS is for servers to poke holes in their same origin policy.
Um, and it's all driven. The, the two most important things to note are two things I already said.
One, it's all driven by the origin header. So, uh, so a client sends an origin header along with the request.
And based on that origin header, servers make decisions on how to set their cross-origin resource sharing policy if they so choose.
And then, uh, the other thing is if, if you find yourself in a situation where you need to use some, uh, some, where you need to use CORS, uh, you probably want to start with STAR, which might be counterintuitive, but counterintuitive is actually, uh, in this case, STAR is actually safe.
And that's a big misconception in the world of CORS. So, uh, saying allow access control, allow origin, STAR is actually pretty secure because it means anybody can talk to me.
Anybody out there can talk to, can talk to me even if I'm a bank, but they're not allowed to send cookies.
And so if you, uh, if you are, uh, if from my bank and evil.com thing, uh, example, a few minutes ago, if you're evil.com and you send a request to a bank and a bank responds access control, allow origin, STAR, I will poke a hole in my same origin policy.
Uh, then, uh, but only with STAR, that means that evil.com will be like, oh, dang, I can't, I can't steal the cookies.
I can't the victim's cookies in this case. So there's no attack to be, to be made.
Um, so that's kind of an overview and there's a lot to get through in this.
There's like four CORS headers, uh, and the whole specification is being rewritten, but it's not really going anywhere.
CORS at this time is, uh, fast forward a few years from this talk.
I gave this talk in 2016, I see.
And fast forward a few years, um, they're, they're redoing all of, all of cross origin resource sharing because it was kind of complicated.
I made a, uh, I kind of at the end of this talk said, you know, we, where is it?
Uh, so these are all the different CORS headers.
I basically made the claim that this is really complicated.
Nobody's ever going to really get it right. It's too hard. Uh, if, if people in security barely get it, um, then there's a problem and CORS isn't alone.
There's a bunch of these web specifications that are just really, really complicated, really made for security people, not made for web developers, not made for, um, not made for people who just want things to be secure and to work.
Uh, there's just too much stuff. And actually I said, CORS is not alone in 2016.
Uh, this one has since been deprecated. So this one was really complicated and got deprecated.
This one got even more complicated. And, um, and SRI is a, is a good one.
I, I don't think that's so bad. Um, HSTS really widely deployed and not so bad and credential management never really got caught on, but this one just fully got ripped out of the Internet.
Uh, they, a few, I think 2018, um, the browsers kind of said, you know, that whole HPKP thing was a mistake.
So there's, there's a lot of security specifications that make the web work and it's just confusing and, uh, they should be simple.
So, um, so one of the points of this talk was that a lot of people get their CORS policies wrong.
This is good. This is fine.
This is a more complicated, uh, policy from a competitor that, uh, another CDN company that was, uh, uh, doing a good thing here.
And that was kind of my example.
And then there are a lot that do, uh, that do it poorly. So here's an example of one, this was a bug I responsibly disclosed, uh, probably, I guess, four years, five years ago now, and it was in the service streamable, uh, and they responded really quickly and fixed it in, I don't know, 25, 30 minutes at the time.
It was great, but it was a simple, the attack was as simple as sending a curl request with this evil origin header, seeing and seeing these two headers back.
So I, I did a bunch of research at the time about who's, who's just responding, uh, to anybody, uh, with sure, send me your cookies, send me everything, uh, you want across origin people who had basically turned off same origin policy.
I was looking for websites that had just turned it off and I found a significant number of them for everything from, uh, financial companies to all sorts of things.
Um, and that was, uh, that was really, really kind of a fun thing to find, but, um, but, uh, yeah, and this is, was a proof of concept of how to exploit the issue from the front end.
So if you're in the front end and you want to make a cross origin request, it's really not much of an attack or anything.
It's really just making a request cross origin from, from one website to another.
There's a million reasons to do this legitimately.
And so, uh, this was the example that I did for, uh, for streamable for who I responsibly disclosed this to.
So, uh, it was me kind of ripping out the stream key and, uh, and it's really simple to do.
It was, it was pretty neat.
Okay. So what else do we have here? I found a bunch of websites with this problem.
Same origin policy is really important. And then, yeah. So the content of this talk, uh, went on for a while.
I won't bug you or bore you, but, um, but kind of the crux of the talk again, demand simplicity.
Uh, all of these, all of these specs were a big mess.
A lot of, uh, not all of them. Like I said, HSTS was great. SRI great.
Um, CSP very useful, very important. It's gotten complicated, but, um, CSP is the audience for it is kind of security people.
So that's probably okay. Uh, and, um, but cores they're rewriting it and HPKP they ripped out and of, of browsers.
So security on the web is hard. We should, we should demand simplicity. It was, um, was kind of the crux of this talk.
Um, but if you take nothing away from the talk, take away three things.
Um, through one same origin policy is the, the, uh, the glue that holds Internet security together today.
So maybe not Internet security, maybe web security, same origin policy is the glue of web security.
So it allows one website to not talk to another website. Uh, and I'll show you a concrete example.
We'll, we'll build one in just a second. So that's the first takeaway.
The second takeaway, if you ever find yourself in a situation where you need to deploy cores, start with access control, allow origin star.
And if something's not working, um, ask yourself why, what's the use case, uh, do more research, but access control, allow origin star works for most use cases.
And, um, and it's a, it's a great place to start.
Um, and it's safe. It's a little counterintuitive because it says star and star usually is like, ah, that seems unsafe, but it is very safe.
And then last course is driven by, uh, the origin header.
And so, um, maybe that's not clear what I'm saying there, but it means that, uh, web requests from a client go to a server containing an origin header servers, make the decision based on that origins header about what policy to, to show it back to the clients.
Okay. So let's build a real world example of cross -origin resource sharing.
So first, I think I'm going to start with this proof of concept first because, uh, why not?
I'm going to take this proof of concept and I'm going to show you this API that I built called CSPR and G dot X, Y, Z.
And it stands for, well, it's just a bunch of letters, but it's a cryptographically secure pseudo random number generator.
And this is a Cloudflare worker running on the Cloudflare edge.
Uh, and it's an open API, so anybody can call it. It's just returning randomness from, uh, from the edge.
And you can specify how many bytes you want.
You can specify all these things, uh, the format you want, and it's pretty cool.
So let me show you what it looks like. If you make a request, return some random data and a timestamp and a status code, really simple.
And so I want to make a website that, uh, that shows this randomness and makes from the front end, makes a request to this website and, um, and, uh, will show some randomness.
Pretty simple.
And I can do that in my browser. Let me, let me start here. So let me make this large enough for you all to see.
A little bigger.
All right. This looks like it's a good enough size. We are going to start with a basic website index dot HTML.
Apologize for my keyboard.
If it's very loud, it's one of those buckling spring, uh, old, old style keyboards.
I love it. It feels great, but, um, it can be a little loud.
So, uh, I'll try to be a little quiet. So we want to head a body body, and that's basically it, uh, our simple website.
We can add a marquee cause, uh, we're doing some really serious web design here and we need a marquee.
Uh, so let's do example in the marquee and let's open index dot HTML.
Here we go.
Look at that. That's a great looking marquee. Okay. So let us, first of all, we need the, the marquee to be a little lot or larger and we will, uh, make a, make a request from my website to this, uh, CSPR and G dot X, Y, Z.
So let's try to do that. I'm going to paste in the request from earlier and let's just take it, replace this C S P R N G dot X, Y, Z.
And what you'll see here, I'm going to request the homepage, not the actual API.
And what you'll see here is that, um, this request should be blocked.
And the reason for that is because I don't have a course policy set on the homepage, but I do on the API.
And that's what I want to show you.
One gets blocked, one works and, uh, and you'll see exactly why in just a moment.
So, uh, let's do alert data, real simple. And then I think it's error or failure.
You don't need with credentials today.
So failure, alert, fail, plus sign.
Okay. The data. Okay. So I'm going to, when this website loads, we're going to see an alert box, which means that a request was made from my website to CSPR and G dot X, Y, Z.
And it'll either say some data or sale, say fail. And then probably nothing because it's a failure.
Uh, and let's give it a go. Um, who knows if this works?
All right. We didn't see an alert box. Why is that? Because dollar is not defined.
Oh, great. Yes. I need jQuery. That's what I'm missing here. Do I need jQuery?
I do need jQuery.
Dang. That's where everything that's, uh, where, you know, you made a mistake.
2016, this was already not okay, including jQuery in your website.
Uh, but, uh, now you really, you really probably don't need jQuery these days, but it only takes a second to add.
And so let's do it. Live programming script source.
I remember if you do that, it's been so long since I did any web programming and it probably didn't work again from origin.
Okay, great. It didn't work. Let me see if error gives us a better, uh, instead of failure.
I think it's error. Great.
Fail, object, object. That's exactly what I want to see. And, uh, fail. We can probably do json.stringify here.
Okay.
So we got a, we got a nice error message. The request failed from one, from, uh, my website to CSPRNG and let's see why.
So this debugging console is so important.
If you're a web security person, this is all you really need. This and curl, you don't need any fancy tools.
Um, in my day, this is all you needed. Okay.
So you see this request failed and you'll see access to XML HTTP request failed from origin null.
It's been blocked by course policy, no access control, allow header.
And you'll see, here's the actual request that got made. Uh, here's the HTTP.
This might be a little hard to see, but you'll see the, all the request headers that were made from, from this, from this website and you see origin null because I'm actually not on a website.
So, um, so that's a little, that's an important thing to note, but, um, you don't see a response header with, uh, with access control, allow origin star.
So it doesn't work. And now what you'll see is if I change this to V1 API, then it should work.
I think it'll work. Let's give it a go.
Object, object.
Okay. So it did work. It did work. I just got to add some more debugging here.
So let me add the word success. It's on stringify and last but not least open index.html.
And we got success, some random stuff here. And, uh, if I refresh it, we'll see different random stuff, different random stuff.
Might be a little tough to see on Cloudflare TV, but, uh, very cool.
It worked.
And let's actually go dig in, find that course policy and make sure we understand why it worked.
And you'll see, I made this request origin null. Uh, and whenever you make a cross origin request, your browser will automatically add on that origin null or origin with your actual origin.
I'm on a, um, I'm not really on an origin because this is just a file on my computer that I'm running in my browser, but the, um, the server responded with access control, allow origins star.
So that's kind of a quick 30 second demo on how cores works.
We don't see any error messages.
It just works. Uh, so I hope that made sense. I hope that was fun. And, um, we only have three minutes left, so I'm going to do a chess puzzle or two and hope you learned something today.
So, um, big fan of, uh, all of these chess puzzles.
It's kind of a recurring theme on this show. And, uh, I hope I can solve it in two minutes.
Okay. So this is a mess of a board real fast. Let's explain what I'm seeing here.
Uh, we are playing the black pieces. We have both Knights. We have both Bishops.
We have a Queen and two Rooks against both Knights, both Bishops, Queen and two Rooks, but everything is all over the board, all over the board.
And if this thing moves, we're in trouble, uh, because that comes with check.
So if this, if this moves, then suddenly our King is in check.
And so very important to make a move that responds to that.
So we can one move I'm looking at is here, but what will happen after that?
Um, I am not sure. Hmm.
This also looks, this is, uh, actually that's okay. Okay. So I think I'm just going to take this and see what happens.
Let's, uh, uh, my brain's not working well enough to really know if I'm making a big mistake here.
Nope. That's not the way to solve the puzzle.
So um, Oh, I can also take this. So this is kind of neat.
There's two attackers here. Well, there's one defender on this piece and there's two attackers.
Is it as simple as taking this? Okay. Well, I took that, but now my Queen is under attack.
It looks like when I move this, this will be attacked.
So I need to move my Queen in a way that it, uh, that it is saved. And this square doesn't work.
This square does work. Um, but I'd also like to save this pawn, but I don't think I can do that.
So I think I need to move, um, here. Nope. Wow.
It didn't work. Ah, okay. So I lose my Queen, take his Queen. All right. That was not a good puzzle.
And, um, very, very confusing for me this early in the morning.
They should, they should have a warning on those. Uh, it's not very cool that they would do this.
So this one is interesting. We only have 22 seconds though, but I believe it's going to be taking this Queen here and then you lose this and, uh, get to hide here.
So no, wow. I'm on a roll, but thank you for joining me on Hacker Time.
I hope to line up some great guests in the near future. And, uh, I will see you all next Friday.