Headline
CVE-2023-32235: 🔒 Fixed path traversal issue in theme files · TryGhost/Ghost@378dd91
Ghost before 5.42.1 allows remote attackers to read arbitrary files within the active theme’s folder via /assets/built%2F…%2F…%2F/ directory traversal. This occurs in frontend/web/middleware/static-theme.js.
Expand Up @@ -14,15 +14,45 @@ function isDeniedFile(file) { return deniedFiles.includes(base) || deniedFileTypes.includes(ext); }
/** * Copy from: * https://github.com/pillarjs/send/blob/b69cbb3dc4c09c37917d08a4c13fcd1bac97ade5/index.js#L987-L1003 * * Allows V8 to only deoptimize this fn instead of all * of send(). * * @param {string} filePath * @returns {string|number} returns -1 number if decode decodeURIComponent throws */ function decode(filePath) { try { return decodeURIComponent(filePath); } catch (err) { return -1; } }
/** * * @param {string} file path to a requested file * @returns {boolean} */ function isAllowedFile(file) { const decodedFilePath = decode(file); if (decodedFilePath === -1) { return false; }
const normalizedFilePath = path.normalize(decodedFilePath);
const allowedFiles = [‘manifest.json’]; const allowedPath = '/assets/’; const alwaysDeny = [‘.hbs’];
const ext = path.extname(file); const base = path.basename(file); const ext = path.extname(normalizedFilePath); const base = path.basename(normalizedFilePath);
return allowedFiles.includes(base) || (file.startsWith(allowedPath) && !alwaysDeny.includes(ext)); return allowedFiles.includes(base) || (normalizedFilePath.startsWith(allowedPath) && !alwaysDeny.includes(ext)); }
function forwardToExpressStatic(req, res, next) { Expand Down
Related news
Ghost before 5.42.1 allows remote attackers to read arbitrary files within the active theme's folder via /assets/built%2F..%2F..%2F/ directory traversal. This occurs in frontend/web/middleware/static-theme.js.