Rating:

## Owner:

> CaptainFreak

#### Solved?

-Yes

#### Tried:

1. Gynvael's node challenges helped in quickly solving this.

#### Solutions:

1. Express itslef uses npm package `qs` for parsing the query parameter and creating `req.query` object. It uses it with option of option of allowPrototypes by default for having query paramters as JS arrays and Objects.

References:
a. Express Code: https://github.com/expressjs/express/blob/master/lib/middleware/query.js#L36
b. QS security considerations: https://www.npmjs.com/package/qs#parsing-objects

Challenges had following code:

```javascript
const express = require('express')
const path = require('path')
const app = express()

//Don't forget to redact from published source
const flag = '[REDACTED]'

app.get('/', (req, res) => {
res.redirect('/page?path=index.html')
})

app.get('/page', (req, res) => {

let path = req.query.path

console.log(path)

//Handle queryless request
if(!path || !strip(path)){
res.redirect('/page?path=index.html')
return
}

path = strip(path)

path = preventTraversal(path)

res.sendFile(prepare(path), (err) => {
if(err){
if (! res.headersSent) {
try {
res.send(strip(req.query.path) + ' not found')
} catch {
res.end()
}
}
}
})
})

//Prevent directory traversal attack
function preventTraversal(dir){
if(dir.includes('../')){
let res = dir.replace('../', '')
return preventTraversal(res)
}

//In case people want to test locally on windows
if(dir.includes('..\\')){
let res = dir.replace('..\\', '')
return preventTraversal(res)
}
return dir
}

//Get absolute path from relative path
function prepare(dir){
console.log(path.resolve('./public/' + dir))
return path.resolve('./public/' + dir)
}

//Strip leading characters
function strip(dir){
const regex = /^[a-z0-9]$/im

//Remove first character if not alphanumeric

if(!regex.test(dir[0])){
if(dir.length > 0){
return strip(dir.slice(1))
}
return ''
}

return dir
}

app.listen(3000, () => {
console.log('listening on 0.0.0.0:3000')
})

```

so if we pass path[]=a&path[]=/../../index.js

req.path will become

```
req.path = ['a', '/../../index.js']
```

and strip() will now work on path[0] = 'a'

path.includes('../') in `preventTraversal` will fail because this array does not include that string.

but when and array is concatenated with string, its converted into string before, so path will become

'./public' + 'a,/../../index.js' = './publica,/../../index.js'

which when resolving will point to index.js where our flag is present.

Original writeup (https://github.com/TeamUnderdawgs/CTF-Docs/blob/master/redpwnCTF2020/Web/tux-fanpage.md).