Web app security



Winter 2 batch

Security/privacy nerd

What we're covering

tl;dr: high-level vulnerabilities specific to webapps

What we're not covering

Injection vulnerabilities

Rely on injecting text with special meaning into the app

Usual culprit: string concatenation

Most common type: SQL injections

Trivial example

function searchFirstNames(req, res, next) {
	var query = "SELECT 'firstname' FROM 'users' WHERE 'username' LIKE '%";
	query += req.params.searchQuery + '%;';
	db.query(query , function(response) {
		// Do something

Database sees: SELECT 'firstname' FROM 'users' WHERE 'username' LIKE '%%'

xkcd about a SQL injection "Exploits of a Mom" by Randall Munroe; CC-BY-NC 2.5


Substitutions (use safe APIs)


Frameworks don't necessarily do this for you

XSS attacks

XSS = Cross Site Scripting

Relies on injecting text interpreted specially by the browser

Almost always used to create a scripting context

Trivial example

I forgot :(
var postCompose = document.getElementById('postCompose'),
    postDisplay = document.getElementById('postDisplay'),
    postDisplayButton = document.getElementById('postDisplayButton');

postDisplayButton.addEventListener('click', function(event) {
	postDisplay.innerHTML = postCompose.value;

XSS solutions

Use an autoescaping template language

Use an escaping library (don't do it yourself)

Prefer well-known libraries

If not, whitelists

Content Security Policy

Password mishandling

Your password database will be compromised

The tl;dr is: use a well-established algorithm

We're going to talk about why anyway

Spoiler: at the end I'll say "don't use passwords"


A hash function is any function that can be used to map data of arbitrary size to data of fixed size. -Wikipedia

Takes in an arbitrary amount of data

Outputs a deterministic fixed-length string

Changes are obvious

Very hard to reverse

Password hashing

Hash passwords so the attacker has to guess

Use strong hashing functions that are slooooooow

That means no (plain) SHA-1, no SHA-256, no MD5, etc.



Plaintext values that are hashed with the password

Salting breaks rainbow tables

Just use an algorithm

PBKDF2 (conservative, generally SHA-256, vulnerable to ASICs/GPUs)

bcrypt (newer, Blowfish, vulnerable to FPGAs)

Both of these take care of salting

Do not use:

scrypt (too young, weaker than bcrypt for password hashes)

Your own custom solution (see don't be a Dave on security.SE)

Two-factor authentication

Make users prove they have something in addition to knowing something

Something they know: password

Something they have: phone

Screenshot of FreeOTP two-factor authentication app

Implementation options

SMS (more insecure)


No password?

Consider removing passwords

Just use email, SMS or TOTP instead

Passwords are almost always the weak points (xkcd agrees)


Cross Site Request Forgery

Confused deputy attack

Tricks the browser into requesting a state change

Relies on browsers always sending auth information

Trivial example

<a href="https://mybank.com/account/manage?action=changeemail&email=alex@strugee.net">Click to download PDF</a>


Easiest way: verify same-origin + CSRF tokens

Server embeds a token in web pages when generating them

Requests must authenticate using that token

Use your framework

Other prevention techniques

Things that do not prevent CSRF


Session ID in the URL

A "secret" cookie

Only accepting POST requests



HTTP Strict Transport Security

Keep stuff up-to-date

X-Frame-Options: DENY

X-Content-Type-Options: nosniff

Tips II

X-Download-Options: noopen

X-XSS-Protection: 1; mode=block (reportedly buggy sometimes? Use a UA sniffer)

Referrer-Policy: same-origin / no-referrer



Access this presentation again


Or get the source code