[Google CTF 2017] The X Sanitizer ‒ writeup

Another client-side web challenge from Google.

How does it work?

Firstly, we need to acknowledge how this “sandbox” works.

You input a html code on the website, your input will come through sandbox, and the page print out as Rendered sanitized HTML

ServiceWorkers is been used to prevent peoples getting out of sandbox. Basically, it controls and fetchs pages from its origin.

I spent little time on reading the documents about this, it’s very cool, make www better and more awesome.


You need to notice that there are two Content-Security-Policy at two different places:

    1. At the main page, there is

      means loading content from only itself is allowed.
    2. In the sandbox, it is

      means you can just only load <script> or <link rel=import> from any source but not inline


The strategies

So, there may be two ways to solve this:

  1. Escaping the sandbox
  2. Exploiting XSS at the main page, include some html/script from the website itself.

The first way I tried was exploiting inside sandbox to load scripting from outside, but… serviceWorker was setup for serving all pages from this origin.


You can see that it removes currentScript or link[rel=import] , to bypass it you can just insert one more <link rel=import> to let it remove the first one but not second.

There is another way to do that is DOM Clobbering.

this script definesremove variable again, turns it into element.

I was trying to abuse client,URL,pathname to make isSandbox returns FALSE. After long hours,

I failed ✘

Then the way must be running script in the main page, but how? As I mentioned earlier, loading from only itself is allowed…

How about let it load script from /sandbox?html=...


then the main page includes an import from /sandbox?html=...and treats it as HTML code.


Well, now /sandbox?html=script blah blah is considered as text/script. But I got a syntax error


Sure, the javascript should not startwith <!doctype HTML>...

I was getting close…

Much time later, I found this challenge writeup from Cure53. I realized I’m on the right track.

Just use the same payload to test…and it works!!!!

utf-16be is filtered in sanitizer.js (it must be a hint but I didn’t realize, I thought it’s a trap..haiz)

You can bypass it by encode utf-16beinto utf-1%36be (because it will come through sandbox via link href)

In the devtools window, we can see that it parses successfully the script from sandbox with bunch of unicode bytes.

I write a little/noob/lazy script to generate a unicode payload

then you can retrieve flag from your server

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *