Cross site request forgery, CSRF, is the third big web attack. I've talked about cross site scripting
in the past. I've talked about SQL injection. This is number three, and it's the lesser-known one.
Web browsers are fairly trusting things. I've said this before: if you give them some code to run,
they don't cast a value judgment on it. They can't tell if it's malicious. They will just run it.
Now, this was kind of okay in the early days of the web, when there wasn't online banking and things like that.
The worst you could do is put a comment somewhere. Nowadays, bit more complicated.
The web runs on data being sent back and forth, and that data can be encoded in a couple of ways.
You can have what's called a GET request, and that's like if you look up, if you're using this on desktop,
and you look up at the browser address bar, you'll see: youtube.com/watch, that's the name of the page,
and then a ?v= a string of characters.
That means that you're going to the watch page, and then the rest of that gets stripped off and sent
to the logic at YouTube which says, oh, I want this video, so pull these details out of the database.
There's another way of doing that, called POST, which is the kind of thing where you have a form
with a button at the bottom of it. And when you hit "go", then all that data gets bundled up and sent
along with the request, but not in the address bar. And traditionally, if you put it in the address bar,
it's designed for fetching data. It's called a GET. So that means that you can take this YouTube URL,
and copy and paste it to somewhere else. And just bundling the data up, like when you click "go" on a form,
is called a POST. And that's meant for writing things, things that happen once. So that when you hit refresh
or go back to the same page, it doesn't do the same thing twice. So if you enter a comment,
it doesn't put all your comment's details in the URL bar, and you can't copy and paste that to a friend,
and they all post the same comment. And that's reasonably good for the early days of the web,
but since then, it's got a bit more complicated. Let's say you have a form on your website for an online bank.
So let's design a really bad online bank form. Let's have, send some money from your account
to this account number, and send this much. And then there's a "go" button. And let's say that
as long as you're logged in, as long as you've been to all the authentication checks, and used that little
chip & PIN device that gives you a password to type in, you've got access to that form.
You type in the account number, you type in how much you're transmitting, you select "go."
First of all, this won't use a GET request. It won't appear up top like YouTube does.
It'll bundle it up in a POST, it'll send the request, and your bank will send back that it's done.
But the trouble is, that form is, well, almost public. You know how it's designed. So let's imagine you set up
a fake webpage somewhere else that has that form on it. And maybe, just maybe, you hide some of those
details, so they're already typed in. So it already has your account number in it, and, say, £1,000.
and then when someone comes along, and they want to put a comment on your website—
So let's design a really malicious blog.
Let's, let's call it "My Awesome Blog".
Let's write some really inflammatory content that people will love to comment on.
And here, is a comment box.
But off here, offscreen where they can't see it, or even completely invisible,
is a box that says 'account number', prefilled with your account number; 'amount', a thousand pounds.
I've written a hundred. Uhm, a hundred pounds.
'Cause apparently my hand has lower ambitions than my brain does.
And when you click that 'go' button, it's not going to My Awesome Blog.
It goes to the really badly designed online bank.
Which probably says: oh! We've got a request here!
Don't know what this all blog nonsense is about, but look, we've got an account number, we've got some money - transfer it!
Because we've already been authorized.
Because you logged in to that online bank in another tab, while you were bored. And, well...
Great. The money is gone.
And it gets worse than that. Because, if you've noticed, when you type a comment on YouTube,
You click "Post". It doesn't load the whole page back, like it used to in the early days of the web.
Now, it does it all in the background, silently.
And just sends a thing back, saying "Yeah."
"That's fine. No worries."
Well, that would work with this too.
You wouldn't even need to click the 'go' button.
It could just be that when I load up my site, My (malicious) Awesome Blog,
it just creates that form in the background and sends off that request.
There's a few things in browsers designed to stop you from doing that, but there are ways around them.
Now, that's obviously quite a big problem.
Online banks are generally not designed that way, unless they are designed incompetently.
But a lot of web forums, a lot of smaller sites have problems like that.
If you've ever designed something with a delete your account button,
then frequently, it just goes to something like /delete. With maybe, you know, ?confirm=true on it.
And you assume that the only time that form would be visible, is when the user is logged in,
and has clicked: No, I really want to delete my account. I could copy that 'delete your account' form
and just put it in the background of my completely irrelevant web page somewhere else.
And you wouldn't even see if it fired, because it's all happening in the background using modern web technologies.
And, you wouldn't notice. It would delete your account quietly in the background because that form,
that 'delete you account' form or that transfer the money form, hasn't checked where the request is coming from.
There was something in what's called HTTP, the hypertext transfer protocol,
the very basics of the web, designed to stop this and it's called the Referer header.
and it means, that when you click a link or submit a form, it includes the things
it says Referer: this site.
So you know if the form request is coming from the actual online bank, or the actual
delete your account form, and not some malicious site elsewhere.
The trouble is, if you start checking for that, a lot of users start complaining
because that Referer header isn't always sent like it should. Maybe you've got an adverb blocker
or maybe you've got some kind of privacy tool that's blocking that as well.
The way to get around that, is a one time key. What the Americans call a nonce, and which the British definitely do not call a nonce.
The one time key works, by the form on your website generating a unique code.
It can be anything, just a random string of characters, each time you create the form.
And then storing that [string of characters] and saying right, anything that comes back,
anything that I see, needs to have this token with it.
and this code, this token you've generated is in the form as well.
Completely hidden, invisible to the user is something that says, token: random string of characters.
I think I just wrote a number plate. Uhm, this random string is meaningless, but what it represents
is that this form that I just made and I just sent out to the user, is the one that's coming back.
So meanwhile, on My (malicious) Awesome Blog, I don't know what this token is, I can't possibly know
what this token is, because it changes per user and it changes every time the form is requested, or at least
every few minutes. And if you copy that form, if you take that token and try and use it 5 minutes later or
10 minutes later or when the form has already been submitted, or for a different person, or for any one of these things
Then I'll look at that token and I'll go: that's wrong. I'm not having that (?) and suddenly,
Cross Site Request Forgery doesn't work anymore. And there're still theoretical attacks and lucky flux
that could get past this, but in general, that solves it. So if you're designing web forms for anything which is permanent
anything like deleting an account, posting a comment, authorizing someone, or even transferring money, if you're not using this,
this is a pretty big security hole, and if the sites you're using aren't using this, well...
you now know what might happen when you go to some malicious blog somewhere out there.
So that's Cross Site Request Forgery, and it is the third attack and everyone knows about XSS,
if you're a web developer, Cross Site Scripting (XSS) is the one you know about.
SQL injection, database attacks are the one you know about, but this...
This one went under the radar for a long time, and there's still a lot of developers that don't know about it.
So if you're designing a site, or using a site that has anything kind of permanent to it, have a look
and see if a token is being sent. 'Cause if it isn't, might be a bit of a security hole there.
You start with a script tag and then everything stops, you've got a closing script tag down here.
Nothing in this section will actually appear on the user's screen...
Now let's say I type in "Tom" with a quote mark in it...