This site runs best with JavaScript enabled.
Wombat

Luke Mayhew

Front-end dev. Mentor to struggling developers. Pursuer of growth, wisdom, and a life well-lived.

How to avoid ruining lives (front-end security matters)

Luke Mayhew

April 30, 2019


You don’t want to be this guy.

Ever been asked something in an interview that just totally stumped you? I have. It’s been a while, but I remember those painful moments where you’re racking your brain and coming up blank. I had a new one the other day though. A worse one. See, it’s one thing to be asked something hard and not know. But when I was asked to explain Cross-Site Scripting, I knew it was Web Dev 101 concept — I remember learning about it way back when after all. So after 5 years of professional experience, I knew I should know, and I still came up blank.

But if this was just about looking stupid in front of my interviewers, it wouldn’t be quite such a big deal (even though it would still be a “1/10 would not do again”). The thing is, though, I knew that by not knowing about basic front-end security, I wasn’t just letting myself down in the interview, I was letting the world down.

Alright, sure, I get that that sounds a bit melodramatic — it’s just a bruised ego, right? And security is really for back-end devs anyway, isn’t it? If that’s what you’re thinking I’ll let you off easy this time and just chalk it up to you coming down with a bad case of “not-my-job-itis” today (we all have those moments sometimes, just don’t let it become a habit).

Except here’s the thing: the internet is a dangerous place. What would happen to your company if it became that latest hacking scandal? What if a friend or family member who uses your company’s product broke down and told you how that hack had ruined their life? Maybe hackers stole their life savings. Maybe their reputation was ruined and they lost their job. The impact of the Ashley Madison hack of 2015 was measured in lives lost, not just passwords stolen. Imagine your friends and loved ones torn apart by that security breach. And now imagine that it came back to you, and your work, and something you could have done toward better security but didn’t.

As makers of technology, we have a responsibility to the people we serve. A lot of responsibility, actually, and one area of that responsibility is keeping them safe. Do you really want to just say “Oh well, not my job. I’ll let someone else tackle security — like the back-end devs or devops folks”? Good luck saying that to your loved ones whose lives have been ruined by using your work. Nothing in development happens in isolation — a front end does nothing without a back end, and a back end can’t be used without a front end into it, and on and on it goes. We all work together, and washing your hands of things that “aren’t my job” is irresponsible and dangerous.

So yes, security is our concern as front-end developers. And here’s the quick-n-dirty on the two most common ways we can protect our people:

Cross-Site Scripting (XSS)

xkcd 327

You think this only happens to back-end devs? Think again. (https://xkcd.com/327/)

XSS is remarkably straightforward for a security exploit. It essentially boils down to giving a malicious party a way to inject code into your site, and have the browser run it thinking it’s part of your site. Here’s an example of all it takes to be vulnerable to this exploit:

1const username = document.querySelector('input').value;
2document.querySelector('#greeting').innerHTML = `Hi ${username}!`;

Seems harmless enough, but what happens if the user types some malicious code into the input element? For example:

1<img src="x" onload="const cookies=document.cookie; const xhr=new XMLHttpRequest(); /* Send cookies to attacker’s site here */" />

An XSS vulnerability essentially gives the attacker full access to do anything that the user could do — sending a bank transfer, stealing all of their data; if your code can do it, the attacker can do it. The good news is that it’s fairly easy to avoid, especially when using modern frameworks and libraries rather than direct DOM manipulation. Keep in mind that the example above isn’t the only way XSS can happen — it can happen when using URL query parameters, or server-rendered content (either through traditional server-side languages/frameworks like Ruby on Rails, or through server-side rendering of front-end content like React). For a the full details on XSS check out the very handy Excess XSS site.

Cross-Site Request Forgery (CSRF)

What? Another Cross-Site something or other? What the heck? Yes, it’s confusing (I actually explained (very poorly) CSRF instead of XSS in my interview), but don’t worry, I’ll give you an easy way to remember the difference at the end of the post.

A CSRF attack works by taking advantage of two things:

  1. Browsers automatically send all cookies for a site whenever performing a request to that site.
  2. This is true of any request to that site, regardless of where it’s originating from.

Imagine we’ve got an endpoint on the back end that looks something like https://bank.com/transfer?to=landlord&amount=1000 . We think that’s all fine and dandy, because it’s locked down to only work for authenticated users. However, all a CSRF attacker has to do is create a link (in an email, on a website, etc.) that hits that endpoint with malicious parameters and then trick you into clicking it. For example:

1<a href="https://bank.com/transfer?to=meanperson&amount=1000000">
2 OMG this is the CUTEST cat picture EVER!
3</a>

You click that, the request goes off to the bank, the browser kindly sends your authentication cookies, and the bank shrugs and says “Ok, if you say so, my oh-so-authentic-looking user.” Now, if you’re a smarty-pants you might be thinking, “Ok well sure, but GET requests shouldn’t be making changes, so problem solved.” Not so fast. The same technique could be done by tricking you onto a site with a form that auto-submits (via JS) a POST against the site with the right info.

So how do we defend against this? Well, that’s a tad trickier than with XSS. In fact, there are multiple different approaches, but one common one for Single Page Applications is to make use of a CSRF token. This token is generated by the server and added to the page for the SPA to grab once it’s loaded. The SPA sends the token with each request, and the server can then verify that the request has both the authentication token and the CSRF token. Since any request originating from an attacker would be coming from a site that wasn’t served up with one of our CSRF tokens, requests triggered by an attacker get rejected.

As always with security there’s a lot of edge-cases and different implications to consider, so make sure you do your homework on CSRF before implementing it and calling it a day!


XSS and CSRF are only the tip of the iceberg when it comes to web security. They’re the two that are most likely to affect you as a front-end developer, but they’re by no means the whole picture. Even if the solutions aren’t always implemented on the front-end, don’t forget that each of us has a part to play, and we can only play that part if we’ve got the eyes to see and mind to understand. A safer web for our families, friends, and ourselves starts with each of us taking responsibility and working together!

P.S. I promised you an easy way to remember the difference between Cross-Site Scripting and Cross-Site Request Forgery, and I don’t like to disappoint, so here it is. Cross-Site Scripting involves injecting a script into the real webpage, and Cross-Site Request Forgery involves tricking the user (or the browser) to make a request that they don’t really want to, starting from a malicious webpage/email/etc. So “… Scripting” is allowing the bad guys to inject a script, and “… Request…” is tricking you into making a (bad-for-you) request. Simple, yes, but only once you can see the pattern without being dazzled by the extra words :)