Hello team, I hope you’re doing well! I was combing through your GitHub repository to look at the fixes for recent security releases and found the fix for CVE-2021-22151 to be incomplete. The current fix makes assumptions that are true on Linux but that don’t hold on Windows.
The fixed code looks like this
const range = path.normalize(request.params.range);
return range.startsWith('..')
? response.notFound()
: new Promise((resolve) => {
const fontPath = path.join(__dirname, 'fonts', 'open_sans', `${range}.pbf`);
fs.readFile(fontPath, (error, data) => {
// snipped
});
});
The assumption is that any path traversal attempts, once normalized, will start with ..
. This seems to hold on Linux, however on Windows this can happen (using the NodeJS REPL for demonstration here):
> let range = path.normalize('c:../../../../../../../path_traversal')
undefined
> console.log(range)
c:..\..\..\..\..\..\..\path_traversal
> range.startsWith('..')
false
> const fontPath = path.join(__dirname, 'fonts', 'open_sans', `${range}.pbf`);
undefined
> console.log(fontPath)
c:\path_traversal.pbf
Path traversal happened even if the range
didn’t start with ..
.
This requires Kibana to be installed on Windows.
.pbf
file somewhere on disk for demonstration. I did it with echo hax > c:\path_traversal.pbf
..%2f
depending on how deep Kibana is installed.Thom Heymann already had a great suggestion in their code review
> The best way to solve this is to resolve the path from range and ensure it is inside your fonts directory.
I think this would fix the issue once and for all!
Path traversal disclosing .pbf
files