23 Feb 2013

Pagebox — sandboxing XSS attacks.

View FAQ and proof of concept (Sinatra app) on Github  Here I explain the idea and problems I stumbled upon.

Demo online

XHR
Pagebox is a technique for building bullet-proof web apps, which can dramatically improve XSS protection for complex and multi-layer websites with huge attack surface.
Web is not super robust (Cookies, Clickjacking, Frame navigation, CSRF etc) but XSS is an Achilles' heel, it is a shellcode for the entire domain.

If we prove /some_path to be vulnerable to XSS, we can interact with the whole website. This might lead to bad things happening — for example, malicious XSS on /some_path may attempt to, damn it, /withdraw our money. Pagebox presents the solution to this problem.

Sandboxed pages

The idea I want to implement is to make every page independent and secure from other vulnerable pages located on the same domain.

Developers can limit interactions of this particular page with others—by either blacklisting things that clearly shouldn't be done, or by taking a more restrictive approach and whitelisting only allowed things.

frames
Pagebox splits the entire website into many sandboxed pages with unique origins. Every page is not accessible from other pages unless developer allowed it explicitly - you simply cannot window.open/<iframe> other pages on the same domain and extract document.body.innerHTML because of the CSP header: Sandbox.
frames
Every page contains a signed serialized object in <meta> tag, and sends it along with every XMLHttpRequest and <form> submission. Meta tag contains signed information about what was permitted for this URL.
Boxed pages are assigned their pagebox scope, which either limits or allows only particular kinds of request (suppose you're viewing the messages page, you only have the :messages scope, which indicates only message query/creation is allowed; attempt to access any other part would be denied.) Backend checks if the permissions were tampered, if they're good and the action is allowed, it processes the request. To some extent, it's Cross Page Request Forgery protection.

Pagebox can look like: ["follow", "write_message", "read_messages", "edit_account", "delete_account"]. Or it can be more high-level: ["default", "basic", "edit", "show_secret"]
permitted URLs

Problems

Now page can only submit forms, but XHR CORS doesn't work properly - nobody knew we will try it in such way. I'm stuck with XHR-with-credentials and I need your help and ideas.
1) Every page is sandboxed and we cannot put 'allow-same-origin' to avoid DOM interactions
2) When we sandbox a page it gets a unique origin 'null', when we make requests from 'null' we cannot attach credentials (Cookies), because wildcard ('*') is not allowed in Access-Control-Allow-Origin: * for with-credentials requests.
when responding to a credentialed request,  server must specify a domain, and cannot use wild carding.
3) Neither * nor null are allowed for Access-Control-Allow-Origin. So XHR is not possible with Cookies from sandboxed pages.
4) I was trying to use not sandboxed /pageboxproxy iframe, which would do the trick from not sandboxed page and return result back with postMessage, but when we frame not sandboxed page under sandboxed it doesn't work either.
I don't know how to fix it but I really want to make pagebox technique work. It fixes the Internet.

Feel free to troll ask me questions in comments or at homakov@gmail.com - I'm happy to help! Please share your ideas how to make it real.