fix potential path traversal
This commit is contained in:
@@ -117,9 +117,10 @@ class MediaController extends Controller
|
|||||||
try {
|
try {
|
||||||
$file = $this->upload($request);
|
$file = $this->upload($request);
|
||||||
|
|
||||||
if($file === true) {
|
if(is_array($file) && !empty($file['chunk'])) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'Chunk stored',
|
'message' => 'Chunk stored',
|
||||||
|
'upload_token' => $file['token'] ?? null,
|
||||||
]);
|
]);
|
||||||
} else if(!$file) {
|
} else if(!$file) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
@@ -150,8 +151,20 @@ class MediaController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
// else check if it received a file name of a previous upload...
|
// else check if it received a file name of a previous upload...
|
||||||
} else if($request->has('file')) {
|
} else if($request->has('upload_token') || $request->has('file')) {
|
||||||
$tempFileName = sys_get_temp_dir() . '/chunk-' . Auth::id() . '-' . $request->file;
|
$uploadToken = $request->input('upload_token', $request->input('file'));
|
||||||
|
$chunkUploads = session()->get('chunk_uploads', []);
|
||||||
|
|
||||||
|
if(!is_string($uploadToken) || !isset($chunkUploads[$uploadToken])) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Could not find the referenced file on the server.',
|
||||||
|
'errors' => [
|
||||||
|
'file' => 'Could not find the referenced file on the server.'
|
||||||
|
]
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tempFileName = $chunkUploads[$uploadToken];
|
||||||
if(!file_exists($tempFileName)) {
|
if(!file_exists($tempFileName)) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'Could not find the referenced file on the server.',
|
'message' => 'Could not find the referenced file on the server.',
|
||||||
@@ -165,7 +178,15 @@ class MediaController extends Controller
|
|||||||
if($fileMime === false) {
|
if($fileMime === false) {
|
||||||
$fileMime = 'application/octet-stream';
|
$fileMime = 'application/octet-stream';
|
||||||
}
|
}
|
||||||
$file = new UploadedFile($tempFileName, $request->file, $fileMime, null, true);
|
$fileName = $request->input('filename', 'upload');
|
||||||
|
$fileName = Helpers::cleanFileName($fileName);
|
||||||
|
if ($fileName === '') {
|
||||||
|
$fileName = 'upload';
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = new UploadedFile($tempFileName, $fileName, $fileMime, null, true);
|
||||||
|
unset($chunkUploads[$uploadToken]);
|
||||||
|
session()->put('chunk_uploads', $chunkUploads);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check there is an actual file
|
// Check there is an actual file
|
||||||
@@ -398,8 +419,25 @@ class MediaController extends Controller
|
|||||||
throw new FileTooLargeException('The file is larger than the maximum size allowed of ' . Helpers::bytesToString($max_size));
|
throw new FileTooLargeException('The file is larger than the maximum size allowed of ' . Helpers::bytesToString($max_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
$chunkKey = hash('sha256', $fileName);
|
$chunkUploads = session()->get('chunk_uploads', []);
|
||||||
$tempFilePath = sys_get_temp_dir() . '/chunk-' . Auth::id() . '-' . $chunkKey;
|
$uploadToken = $request->input('upload_token');
|
||||||
|
|
||||||
|
if($request->has('filestart')) {
|
||||||
|
$uploadToken = bin2hex(random_bytes(16));
|
||||||
|
$tempFilePath = tempnam(sys_get_temp_dir(), 'chunk-' . Auth::id() . '-');
|
||||||
|
if($tempFilePath === false) {
|
||||||
|
throw new FileInvalidException('Unable to create a temporary upload file.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$chunkUploads[$uploadToken] = $tempFilePath;
|
||||||
|
session()->put('chunk_uploads', $chunkUploads);
|
||||||
|
} else {
|
||||||
|
if(!is_string($uploadToken) || !isset($chunkUploads[$uploadToken])) {
|
||||||
|
throw new FileInvalidException('Invalid upload token.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$tempFilePath = $chunkUploads[$uploadToken];
|
||||||
|
}
|
||||||
|
|
||||||
$filemode = 'a';
|
$filemode = 'a';
|
||||||
if($request->has('filestart')) {
|
if($request->has('filestart')) {
|
||||||
@@ -420,9 +458,17 @@ class MediaController extends Controller
|
|||||||
$fileMime = 'application/octet-stream';
|
$fileMime = 'application/octet-stream';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(is_string($uploadToken) && isset($chunkUploads[$uploadToken])) {
|
||||||
|
unset($chunkUploads[$uploadToken]);
|
||||||
|
session()->put('chunk_uploads', $chunkUploads);
|
||||||
|
}
|
||||||
|
|
||||||
return new UploadedFile($tempFilePath, $fileName, $fileMime, null, true);
|
return new UploadedFile($tempFilePath, $fileName, $fileMime, null, true);
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return [
|
||||||
|
'chunk' => true,
|
||||||
|
'token' => $uploadToken,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ let SM = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const uploadFile = (file, start, title, idx, count) => {
|
const uploadFile = (file, start, title, idx, count, uploadToken = null) => {
|
||||||
const showPercentDecimals = (file.size > (1024 * 1024 * 40));
|
const showPercentDecimals = (file.size > (1024 * 1024 * 40));
|
||||||
const chunkSize = 1024 * 1024 * 2;
|
const chunkSize = 1024 * 1024 * 2;
|
||||||
const end = Math.min(file.size, start + chunkSize);
|
const end = Math.min(file.size, start + chunkSize);
|
||||||
@@ -168,6 +168,9 @@ let SM = {
|
|||||||
formData.append('file', chunk);
|
formData.append('file', chunk);
|
||||||
formData.append('filename', file.name);
|
formData.append('filename', file.name);
|
||||||
formData.append('filesize', file.size);
|
formData.append('filesize', file.size);
|
||||||
|
if (uploadToken) {
|
||||||
|
formData.append('upload_token', uploadToken);
|
||||||
|
}
|
||||||
|
|
||||||
if (start === 0) {
|
if (start === 0) {
|
||||||
formData.append('filestart', 'true');
|
formData.append('filestart', 'true');
|
||||||
@@ -205,6 +208,10 @@ let SM = {
|
|||||||
}
|
}
|
||||||
}).then((response) => {
|
}).then((response) => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
|
if (response.data && response.data.upload_token) {
|
||||||
|
uploadToken = response.data.upload_token;
|
||||||
|
}
|
||||||
|
|
||||||
if (end >= file.size) {
|
if (end >= file.size) {
|
||||||
uploadedFiles.push({ file: file, title: title, data: response.data });
|
uploadedFiles.push({ file: file, title: title, data: response.data });
|
||||||
|
|
||||||
@@ -227,12 +234,13 @@ let SM = {
|
|||||||
} else {
|
} else {
|
||||||
start = 0;
|
start = 0;
|
||||||
idx += 1;
|
idx += 1;
|
||||||
|
uploadToken = null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
start = end;
|
start = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadFile(files[idx], start, titles[idx] || '', idx, files.length);
|
uploadFile(files[idx], start, titles[idx] || '', idx, files.length, uploadToken);
|
||||||
} else {
|
} else {
|
||||||
showError(response.data.message);
|
showError(response.data.message);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user