CVE-2020-15236 (published 2020-10-05T15:15Z)

In Wiki.js before version 2.5.151, directory traversal outside of Wiki.js context is possible when a storage module with local asset cache fetching is enabled. A malicious user can potentially read any file on the file system by crafting a special URL that allows for directory traversal. This is only possible when a storage module implementing local asset cache (e.g Local File System or Git) is enabled and that no web application firewall solution (e.g. cloudflare) strips potentially malicious URLs. Commit 084dcd69d1591586ee4752101e675d5f0ac6dcdc fixes this vulnerability by sanitizing the path before it is passed on to the storage module. The sanitization step removes any directory traversal (e.g. `..` and `.`) sequences as well as invalid filesystem characters from the path. As a workaround, disable any storage module with local asset caching capabilities such as Local File System and Git.

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:P/I:N/A:N)
CVSS v3 base score: 7.5, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)

Weakness information:
cwe_id: CWE-22
cwe_name: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
description: The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
extended_description: 
            Many file operations are intended to take place within a restricted directory. By using special elements such as ".." and "/" separators, attackers can escape outside of the restricted location to access files or directories that are elsewhere on the system. One of the most common special elements is the "../" sequence, which in most modern operating systems is interpreted as the parent directory of the current location. This is referred to as relative path traversal. Path traversal also covers the use of absolute pathnames such as "/usr/local/bin" to access unexpected files. This is referred to as absolute path traversal.
         
         

Fix information:
repo_url: https://github.com/Requarks/wiki
commit_details: repo_url: https://github.com/Requarks/wiki
author: NGPixel
author_date: 2020-10-03 01:44:57-04:00
msg: fix: strip directory traversal sequences from asset paths
repository: repo_url: https://github.com/Requarks/wiki
repo_name: requarks/wiki
description: Wiki.js | A modern and powerful wiki app built on Node.js
repo_language: Vue
owner: Requarks
file_changes: filename: page.js
change_type: ModificationType.MODIFY
diff: @@ -5,6 +5,8 @@ const path = require('path')
 
 const localeSegmentRegex = /^[A-Z]{2}(-[A-Z]{2})?$/i
 const localeFolderRegex = /^([a-z]{2}(?:-[a-z]{2})?\/)?(.*)/i
+// eslint-disable-next-line no-control-regex
+const unsafeCharsRegex = /[\x00-\x1f\x80-\x9f\\"|<>:*?]/
 
 const contentToExt = {
   markdown: 'md',
@@ -30,10 +32,14 @@ module.exports = {
     // Clean Path
     rawPath = _.trim(qs.unescape(rawPath))
     if (_.startsWith(rawPath, '/')) { rawPath = rawPath.substring(1) }
+    rawPath = rawPath.replace(unsafeCharsRegex, '')
     if (rawPath === '') { rawPath = 'home' }
 
     // Extract Info
-    let pathParts = _.filter(_.split(rawPath, '/'), p => !_.isEmpty(p))
+    let pathParts = _.filter(_.split(rawPath, '/'), p => {
+      p = _.trim(p)
+      return !_.isEmpty(p) && p !== '..' && p !== '.'
+    })
     if (pathParts[0].length === 1) {
       pathParts.shift()
     }
@@ -73,7 +79,7 @@ module.exports = {
       ['date', page.updatedAt],
       ['tags', page.tags ? page.tags.map(t => t.tag).join(', ') : ''],
       ['editor', page.editorKey],
-      ['dateCreated', page.createdAt],
+      ['dateCreated', page.createdAt]
     ]
     switch (page.contentType) {
       case 'markdown':

programming_language: JavaScript