KNOWN GitHub

Web Security 06 - CSP

All the sample code is in https://github.com/brianshen1990/WebSecurity .

1. What is Content Security Policy

The HTTP Content-Security-Policy response header allows web site administrators to control resources the user agent is allowed to load for a given page. With a few exceptions, policies mostly involve specifying server origins and script endpoints. This helps guard against cross-site scripting attacks (XSS).

For example, if I open my github blog, it will load resources from Google. I trust google, so It's OK that some google scripts are in my site.

But what if my site load some resource from other site that I don't trust? So CSP is very important in this situation.

The syntax of CSP is simple, but we can define complex situations.

Content-Security-Policy: <policy-directive>; <policy-directive>

For example:

Content-Security-Policy: default-src 'self' http://example.com;
                         script-src http://example.com/

This definition means all resources can be only loaded from the current site and http://example.com, but scripts can be only loaded from http://example.com/.

There are many kinds of source:

  • child-src
  • connect-src
  • font-src
  • frame-src
  • img-src
  • manifest-src
  • media-src
  • object-src
  • prefetch-src
  • script-src
  • style-src
  • worker-src

2. Sample

Let's assume one bad user in our blog system post a blog. The content includes some malicious scripts.

And when other users read his article, the page will load like this staticFile/blogView.html :

<html>
<head>
  <script type="text/javascript" src="jquery-3.3.1.min.js"></script>
</head>
<body>
  <div>
    <h5>Blog Title: Sample CSP</h5>
  </div>

  <div id="blogContent">

    <p>This is the content of my blog.</p>
    <script type="text/javascript" src="http://localhost:8889/hackCSP.js"></script>
    <p>And I will show you how dangerous if we do not use CSP.</p>

  </div>
</body>
</html>

To make the demo more simple, let assume that we do not set httpOnly to our cookies index.js :

app.use(session({
  secret: 'our apps little secret',
  resave: false,
  saveUninitialized: true,
  cookie: { maxAge: 60000, httpOnly: false }
}))

Since we load scripts from 8889, so let's add a malicious script staticHack/hackCSP.js :

$(document).ready(function () {
    var xxx = document.cookie;
    alert('I got cookie:' + xxx);
})

now let's begin:

node index.js
node indexHack.js

Open http://localhost:8888 to login, and then open http://localhost:8888/blogView.html :

Now we get the cookie, and we can use it to do anything.

3. How to fix

Actually, there are many ways to fix this problem:

  • Cookie httpOnly
  • User Content Filter
  • Content Security Policy

We will use Content Security Policy to solve this problem. So let's do a little modification to our safe site indexSafe.js :

app.use(helmet.contentSecurityPolicy({
  directives: {
    defaultSrc: ["'self'"]
  }
}));

and run again:

node indexSafe.js
node indexHack.js

We can see from the console that the resources from 8889 are refused to load.




Comments !

About the blog

Some notes at work and life to share

Brian Shen