mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-25 12:06:00 +00:00
security fixes
This commit is contained in:
@@ -11,6 +11,7 @@ const apps = require('./apps');
|
|||||||
const getMapExport = require('../utility/getMapExport');
|
const getMapExport = require('../utility/getMapExport');
|
||||||
const dbgateApi = require('../shell');
|
const dbgateApi = require('../shell');
|
||||||
const { getLogger } = require('dbgate-tools');
|
const { getLogger } = require('dbgate-tools');
|
||||||
|
const platformInfo = require('../utility/platformInfo');
|
||||||
const logger = getLogger('files');
|
const logger = getLogger('files');
|
||||||
|
|
||||||
function serialize(format, data) {
|
function serialize(format, data) {
|
||||||
@@ -25,6 +26,25 @@ function deserialize(format, text) {
|
|||||||
throw new Error(`Invalid format: ${format}`);
|
throw new Error(`Invalid format: ${format}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkSecureFilePaths(...filePaths) {
|
||||||
|
for (const filePath of filePaths) {
|
||||||
|
if (filePath.includes('..') || filePath.includes('/') || filePath.includes('\\')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkSecureDirectories(...filePaths) {
|
||||||
|
for (const filePath of filePaths) {
|
||||||
|
const directory = path.dirname(filePath);
|
||||||
|
if (directory != filesdir() && directory != uploadsdir() && directory != archivedir() && directory != appdir()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
list_meta: true,
|
list_meta: true,
|
||||||
async list({ folder }, req) {
|
async list({ folder }, req) {
|
||||||
@@ -51,6 +71,9 @@ module.exports = {
|
|||||||
delete_meta: true,
|
delete_meta: true,
|
||||||
async delete({ folder, file }, req) {
|
async delete({ folder, file }, req) {
|
||||||
if (!hasPermission(`files/${folder}/write`, req)) return false;
|
if (!hasPermission(`files/${folder}/write`, req)) return false;
|
||||||
|
if (!checkSecureFilePaths(folder, file)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
await fs.unlink(path.join(filesdir(), folder, file));
|
await fs.unlink(path.join(filesdir(), folder, file));
|
||||||
socket.emitChanged(`files-changed`, { folder });
|
socket.emitChanged(`files-changed`, { folder });
|
||||||
socket.emitChanged(`all-files-changed`);
|
socket.emitChanged(`all-files-changed`);
|
||||||
@@ -60,6 +83,9 @@ module.exports = {
|
|||||||
rename_meta: true,
|
rename_meta: true,
|
||||||
async rename({ folder, file, newFile }, req) {
|
async rename({ folder, file, newFile }, req) {
|
||||||
if (!hasPermission(`files/${folder}/write`, req)) return false;
|
if (!hasPermission(`files/${folder}/write`, req)) return false;
|
||||||
|
if (!checkSecureFilePaths(folder, file, newFile)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
await fs.rename(path.join(filesdir(), folder, file), path.join(filesdir(), folder, newFile));
|
await fs.rename(path.join(filesdir(), folder, file), path.join(filesdir(), folder, newFile));
|
||||||
socket.emitChanged(`files-changed`, { folder });
|
socket.emitChanged(`files-changed`, { folder });
|
||||||
socket.emitChanged(`all-files-changed`);
|
socket.emitChanged(`all-files-changed`);
|
||||||
@@ -77,6 +103,9 @@ module.exports = {
|
|||||||
|
|
||||||
copy_meta: true,
|
copy_meta: true,
|
||||||
async copy({ folder, file, newFile }, req) {
|
async copy({ folder, file, newFile }, req) {
|
||||||
|
if (!checkSecureFilePaths(folder, file, newFile)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (!hasPermission(`files/${folder}/write`, req)) return false;
|
if (!hasPermission(`files/${folder}/write`, req)) return false;
|
||||||
await fs.copyFile(path.join(filesdir(), folder, file), path.join(filesdir(), folder, newFile));
|
await fs.copyFile(path.join(filesdir(), folder, file), path.join(filesdir(), folder, newFile));
|
||||||
socket.emitChanged(`files-changed`, { folder });
|
socket.emitChanged(`files-changed`, { folder });
|
||||||
@@ -86,6 +115,10 @@ module.exports = {
|
|||||||
|
|
||||||
load_meta: true,
|
load_meta: true,
|
||||||
async load({ folder, file, format }, req) {
|
async load({ folder, file, format }, req) {
|
||||||
|
if (!checkSecureFilePaths(folder, file)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (folder.startsWith('archive:')) {
|
if (folder.startsWith('archive:')) {
|
||||||
const text = await fs.readFile(path.join(resolveArchiveFolder(folder.substring('archive:'.length)), file), {
|
const text = await fs.readFile(path.join(resolveArchiveFolder(folder.substring('archive:'.length)), file), {
|
||||||
encoding: 'utf-8',
|
encoding: 'utf-8',
|
||||||
@@ -105,12 +138,20 @@ module.exports = {
|
|||||||
|
|
||||||
loadFrom_meta: true,
|
loadFrom_meta: true,
|
||||||
async loadFrom({ filePath, format }, req) {
|
async loadFrom({ filePath, format }, req) {
|
||||||
|
if (!platformInfo.isElectron) {
|
||||||
|
// this is available only in electron app
|
||||||
|
return false;
|
||||||
|
}
|
||||||
const text = await fs.readFile(filePath, { encoding: 'utf-8' });
|
const text = await fs.readFile(filePath, { encoding: 'utf-8' });
|
||||||
return deserialize(format, text);
|
return deserialize(format, text);
|
||||||
},
|
},
|
||||||
|
|
||||||
save_meta: true,
|
save_meta: true,
|
||||||
async save({ folder, file, data, format }, req) {
|
async save({ folder, file, data, format }, req) {
|
||||||
|
if (!checkSecureFilePaths(folder, file)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (folder.startsWith('archive:')) {
|
if (folder.startsWith('archive:')) {
|
||||||
if (!hasPermission(`archive/write`, req)) return false;
|
if (!hasPermission(`archive/write`, req)) return false;
|
||||||
const dir = resolveArchiveFolder(folder.substring('archive:'.length));
|
const dir = resolveArchiveFolder(folder.substring('archive:'.length));
|
||||||
@@ -143,6 +184,11 @@ module.exports = {
|
|||||||
|
|
||||||
saveAs_meta: true,
|
saveAs_meta: true,
|
||||||
async saveAs({ filePath, data, format }) {
|
async saveAs({ filePath, data, format }) {
|
||||||
|
if (!platformInfo.isElectron) {
|
||||||
|
// this is available only in electron app
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
await fs.writeFile(filePath, serialize(format, data));
|
await fs.writeFile(filePath, serialize(format, data));
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -275,6 +321,11 @@ module.exports = {
|
|||||||
|
|
||||||
simpleCopy_meta: true,
|
simpleCopy_meta: true,
|
||||||
async simpleCopy({ sourceFilePath, targetFilePath }, req) {
|
async simpleCopy({ sourceFilePath, targetFilePath }, req) {
|
||||||
|
if (!platformInfo.isElectron) {
|
||||||
|
if (!checkSecureDirectories(sourceFilePath, targetFilePath)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
await fs.copyFile(sourceFilePath, targetFilePath);
|
await fs.copyFile(sourceFilePath, targetFilePath);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user