fix: server crashes when receiving file download request with invalid byte range; this fixes a security vulnerability that allows an attacker to impact the availability of the server instance; the fix improves parsing of the range parameter to properly handle invalid range requests ([GHSA-h423-w6qv-2wj3](https://github.com/parse-community/parse-server/security/advisories/GHSA-h423-w6qv-2wj3)) [skip release] (#8237)
This commit is contained in:
@@ -228,22 +228,35 @@ export class GridFSBucketAdapter extends FilesAdapter {
|
||||
const partialstart = parts[0];
|
||||
const partialend = parts[1];
|
||||
|
||||
const start = parseInt(partialstart, 10);
|
||||
const end = partialend ? parseInt(partialend, 10) : files[0].length - 1;
|
||||
const fileLength = files[0].length;
|
||||
const fileStart = parseInt(partialstart, 10);
|
||||
const fileEnd = partialend ? parseInt(partialend, 10) : fileLength;
|
||||
|
||||
res.writeHead(206, {
|
||||
'Accept-Ranges': 'bytes',
|
||||
'Content-Length': end - start + 1,
|
||||
'Content-Range': 'bytes ' + start + '-' + end + '/' + files[0].length,
|
||||
'Content-Type': contentType,
|
||||
});
|
||||
let start = Math.min(fileStart || 0, fileEnd, fileLength);
|
||||
let end = Math.max(fileStart || 0, fileEnd) + 1 || fileLength;
|
||||
if (isNaN(fileStart)) {
|
||||
start = fileLength - end + 1;
|
||||
end = fileLength;
|
||||
}
|
||||
end = Math.min(end, fileLength);
|
||||
start = Math.max(start, 0);
|
||||
|
||||
res.status(206);
|
||||
res.header('Accept-Ranges', 'bytes');
|
||||
res.header('Content-Length', end - start);
|
||||
res.header('Content-Range', 'bytes ' + start + '-' + end + '/' + fileLength);
|
||||
res.header('Content-Type', contentType);
|
||||
const stream = bucket.openDownloadStreamByName(filename);
|
||||
stream.start(start);
|
||||
if (end) {
|
||||
stream.end(end);
|
||||
}
|
||||
stream.on('data', chunk => {
|
||||
res.write(chunk);
|
||||
});
|
||||
stream.on('error', () => {
|
||||
res.sendStatus(404);
|
||||
stream.on('error', (e) => {
|
||||
res.status(404);
|
||||
res.send(e.message);
|
||||
});
|
||||
stream.on('end', () => {
|
||||
res.end();
|
||||
|
||||
@@ -266,5 +266,10 @@ export class FilesRouter {
|
||||
}
|
||||
|
||||
function isFileStreamable(req, filesController) {
|
||||
return req.get('Range') && typeof filesController.adapter.handleFileStream === 'function';
|
||||
const range = (req.get('Range') || '/-/').split('-');
|
||||
const start = Number(range[0]);
|
||||
const end = Number(range[1]);
|
||||
return (
|
||||
(!isNaN(start) || !isNaN(end)) && typeof filesController.adapter.handleFileStream === 'function'
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user