# Harekaze 2019 "[a-z().]" (200)
Writeup by Ben Taylor
## Description
Descriptionif (eval(your_code) === 1337) console.log(flag);
http://(redacted) ([server/Dockerfile](https://github.com/TeamHarekaze/HarekazeCTF2019-challenges/tree/master/a-z/server))
- [a-z.tar.xz](https://github.com/TeamHarekaze/HarekazeCTF2019-challenges/blob/master/a-z/attachments/a-z.tar.xz)
## Solution
Wow, this was a fun problem! Maybe my favorite CTF problem yet. If you haven't tried working through it already, I highly recommend you give it a shot. There will be spoilers.
Since we we're graciously provided the source code, let's start by taking a look inside. Line 15 is what's important here:
``` JavaScript12 app.get('/', function (req, res, next) {13   let output = '';14   const code = req.query.code + '';15   if (code && code.length < 200 && !/[^a-z().]/.test(code)) {16     try {17       const result = vm.runInNewContext(code, {}, { timeout: 500 });18       if (result === 1337) {19         output = process.env.FLAG;20       } else {21         output = 'nope';22       }23     } catch (e) {24       output = 'nope';25     }26   } else {27     output = 'nope';28   }29   res.render('index', { title: '[a-z().]', output });30 });```
For the code to run it must (a) exist, (b) have a length less than 200, and (c) can only contain lowercase letters, parenthesis, and dots. Once these checks pass, we get to run in a [super locked down node context](https://nodejs.org/api/vm.html#vm_script_runinnewcontext_sandbox_options). If the code evaluates to the number `1337` (note the triple equals here — a string won't cut it).
My first thought was something along the lines of BF's competitor, [non alphanumeric JavaScript](http://patriciopalladino.com/blog/2012/08/09/non-alphanumeric-javascript.html). However, this JS standard relies heavily on `[`, `]`, and `+`, all of which we don't have access to.
Instead, we'll start more basic than what the challenge calls for — how do we get a string with our limited alphabet? Digging around in documentation, we find the [typeof](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof) operator. If we try to find the type of an undefined variable we get `"undefined"`. What if we try to get the type of that? We unlock the string `"string"`. Also note that we can get `"boolean"` by looking at the type of `true`.
``` JavaScript(typeof(x)) == "undefined"(typeof(typeof(x))) == "string"(typeof(true)) == "boolean"```
Great, we have strings. From here, we can use any string methods or properties that don't contain uppercase letters. For instance, `length`! This unlocks the numbers 6, 7, and 9. While we can't use `indexOf()` due to the uppercase `O`, inspecting a strings properties in any JavaScript console reveals the [search](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/search) method, which means we can search `"undefined"` for `"undefined"` to get `0` and `"undefined"` for `"boolean"` to get `-1`. Also note that since we have access to numbers, we also have access to the string `"number"` through `typeof`.
``` JavaScript(typeof(x)).length == 9(typeof(typeof(x))).length == 6(typeof(true)).length == 7(typeof((typeof(x)).length)) == "number"(typeof((typeof(x)).length)).length == 6(typeof(x)).search((typeof(x))) == 0(typeof(x)).search((typeof(true))) == -1```
Because we can use `concat`, it might be a good idea to form the digits individually and concatenate them since we're lacking any mathematical methods. How can we turn a number into a string? We can't use `toString`, `String`, or `+ ""`. But because JavaScript is a prototype based language, every instance is itself a "class". So using one string, we can access it's constructor with the `constructor` property! We can extend this ideas to numbers to get access to the `Number` class as well to turn strings back into numbers — remember, the final expression must evaluate to a number.
``` JavaScript(typeof(x)).constructor == String((typeof(x)).length).constructor == Number(typeof(x)).constructor((typeof(true)).length) == "7" // we have our first digit to concatenate!((typeof(x)).length).constructor("123") == 123```
Lets see if we can get a `"1"`. Because JavaScript is stupid-typed, `true` == 1. But if we try to pull a `String(true)` using our equivalence above, we get `"true"`. Therefore, we need to first cast the boolean to a number, then the number to a string, leaving us with the monstrosity below. (true => 1 => "1")
``` JavaScript((typeof(x)).length).constructor(true) == 1(typeof(x)).constructor(((typeof(x)).length).constructor(true)) == "1"```
The last digit that we need is a `"3"`. If you're dumb like me, you'll sit down for an hour or two and come up with something along the lines of `(typeof(x)).constructor((typeof(x)).constructor((typeof(x)).length.constructor(typeof(x))).length)`. No, I don't remember how this works and I don't plan on reverse engineering it. The point is, if you recall the rest of the constraints, we have to have an expression under 200 characters, so having _two_ 98 character expressions to get the `"3"`'s might be a problem. Thankfully, one of my teammates saved the day and brought up (in another conversation!) the `name` property of functions. This bad boy returns a string with the name of the function, which we can then take the length of. So really we just need any function with a three letter name. I decided to go with `(typeof(x)).big.name.length` to get `3`, which we can then cast to a string.
``` JavaScript(typeof(x)).constructor((typeof(x)).constructor((typeof(x)).length.constructor(typeof(x))).length) == "3"(typeof(x)).big.name.length == 3(typeof(x)).constructor((typeof(x)).big.name.length) == "3"```
Here is what the combined expression looks like right now. We're making a `"1"`, then concatenating the rest of the digits and parsing to an integer.
``` JavaScript((typeof(x)).length).constructor((typeof(x)).constructor(((typeof(x)).length).constructor(true)).concat((typeof(x)).constructor((typeof(x)).big.name.length)).concat((typeof(x)).constructor((typeof(x)).big.name.length)).concat((typeof(x)).constructor((typeof(true)).length)))```
If you look closely, you'll see this won't actually get us the flag. Why? It's 274 characters long. We need to do some optimizing.
Once again, JavaScript's stupid-typing comes in handy. We can append a number to a string and get a string, so we don't need to parse each number to a string, just the first digit. This gets us the following, clocking in at just 199 characters! We can also optimize `1 == (typeof(x)).match().length` to get down to 187 characters, and there might be a few extra parenthesis (though most are necessary due to `typeof`'s weird precedence), but either way, 199 < 200, and we get the flag!
``` JavaScript((typeof(x)).length).constructor((typeof(x)).constructor(((typeof(x)).length).constructor(true)).concat((typeof(x)).constructor((typeof(x)).big.name.length)).concat((typeof(x)).constructor((typeof(x)).big.name.length)).concat((typeof(x)).constructor((typeof(true)).length)))```
Flag: `HarekazeCTF{sorry_about_last_year's_js_challenge...}`